fork download
  1. // コンピュータによるn人ジャンケン(270行) by 片山博文MZ
  2. // 2017年4月11日
  3. // License: CC BY
  4.  
  5. // 手を表す列挙型。
  6. enum Hand {
  7. グー,
  8. チョキ,
  9. パー,
  10. 無効な手
  11. }
  12.  
  13. // メインクラス。
  14. public class Main {
  15. // サブクラスComputerNJanken。
  16. static protected class ComputerNJanken {
  17. // 人数の最小値、最大値(定数)。
  18. public static final int MIN_PLAYERS = 2;
  19. public static final int MAX_PLAYERS = 10;
  20.  
  21. // メンバー変数(ComputerNJankenのインスタンスから使える)。
  22. protected int numOfCpu; // CPUの人数。
  23. protected Hand[] hands; // 手。
  24. protected String[] playerNames; // プレイヤーの名前。
  25. protected boolean[] survival; // 生き残りを表す。
  26. protected java.util.Random rand; // 乱数生成。
  27. protected java.util.Scanner scanner; // 入力スキャナー。
  28. protected int[] handCounters; // 手の個数。
  29.  
  30. // コンストラクタ
  31. public ComputerNJanken(java.util.Scanner scanner) {
  32. this(scanner, -1);
  33. }
  34. public ComputerNJanken(java.util.Scanner scanner, int numOfCpu) {
  35. this.rand = new java.util.Random();
  36. this.scanner = scanner;
  37. this.numOfCpu = numOfCpu;
  38. }
  39. // ゲームを行う。
  40. public boolean play() {
  41. // ゲーム開始。
  42. if (!start()) {
  43. println("ゲームを開始できませんでした。");
  44. return false; // 失敗。
  45. }
  46.  
  47. // ゲームループ。
  48. for (;;) {
  49. // 生き残りの人数を数える。
  50. if (getSurvivorCount() <= 1) {
  51. // 生き残りが1人以下。
  52. int iPlayer = getSurvivor();
  53. if (iPlayer == -1) {
  54. println("勝者なし。");
  55. } else {
  56. println("勝者は" + playerNames[iPlayer] + "です。");
  57. }
  58. return true; // 成功。
  59. }
  60.  
  61. for (;;) {
  62. // 手を出す。
  63. takeHands();
  64.  
  65. // 判定。
  66. if (judge()) {
  67. break;
  68. }
  69.  
  70. println("あいこです。");
  71.  
  72. // 生き残りを出力する。
  73. printSurvivors();
  74. }
  75. }
  76. }
  77. // 勝った方の手を返す。
  78. public Hand getWinnersHand(Hand hand1, Hand hand2) {
  79. int value1 = hand1.ordinal(), value2 = hand2.ordinal();
  80. if (value1 == value2) {
  81. return Hand.無効な手; // あいこ。
  82. }
  83. // 剰余(割り算の余り)の性質を利用した判定。
  84. if ((value2 - value1 + 3) % 3 == 1) {
  85. return hand1;
  86. }
  87. return hand2;
  88. }
  89.  
  90. //
  91. // 入出力。
  92. //
  93. public String readLine() {
  94. return scanner.nextLine().trim();
  95. }
  96. public void print(String str) {
  97. System.out.print(str);
  98. }
  99. public void println(String str) {
  100. System.out.println(str);
  101. }
  102. public void printSurvivors() {
  103. print("この時点で残っているのは ");
  104. if (survival[0]) {
  105. print(playerNames[0]);
  106. }
  107. for (int i = 1; i < numOfCpu; ++i) {
  108. if (survival[i]) {
  109. print(" と " + playerNames[i]);
  110. }
  111. }
  112. println("です。");
  113. }
  114.  
  115. // 人数の入力。
  116. protected void inputPlayerCount() {
  117. numOfCpu = -1;
  118. for (;;) {
  119. print("対戦人数を入力して下さい(" + MIN_PLAYERS +
  120. "人以上" + MAX_PLAYERS + "人以内): ");
  121. try {
  122. String line = scanner.nextLine().trim();
  123. numOfCpu = Integer.parseInt(line);
  124. if (!(MIN_PLAYERS <= numOfCpu && numOfCpu <= MAX_PLAYERS))
  125. throw new Exception();
  126. break;
  127. } catch (Exception e) {
  128. System.out.println("無効な値です。入力をやり直して下さい。");
  129. }
  130. }
  131. }
  132.  
  133. // ゲームスタート。
  134. protected boolean start() {
  135. println("コンピュータ同士でジャンケンをします。");
  136.  
  137. if (numOfCpu == -1) {
  138. inputPlayerCount();
  139. }
  140. if (numOfCpu == -1) {
  141. return false; // 失敗。
  142. }
  143.  
  144. // メンバー変数の初期化。
  145. hands = new Hand[numOfCpu];
  146. playerNames = new String[numOfCpu];
  147. survival = new boolean[numOfCpu];
  148. for (int i = 0; i < numOfCpu; ++i) {
  149. playerNames[i] = "CPU#" + i;
  150. survival[i] = true;
  151. }
  152. handCounters = new int[3];
  153.  
  154. return true; // 成功。
  155. }
  156.  
  157. // 手を出す。
  158. protected void takeHands() {
  159. for (int i = 0; i < numOfCpu; i++) {
  160. if (survival[i]) {
  161. hands[i] = Hand.values()[rand.nextInt(3)];
  162. }
  163. }
  164. }
  165.  
  166. // 手をその種類で数える。
  167. protected void countHands() {
  168. // ゼロで初期化。
  169. for (int i = 0; i < 3; i++) {
  170. handCounters[i] = 0;
  171. }
  172. // 生き残りの手の種類を調べて、種類ごとに数える。
  173. for (int i = 0; i < numOfCpu; i++) {
  174. if (survival[i]) {
  175. handCounters[hands[i].ordinal()] += 1;
  176. }
  177. }
  178. }
  179.  
  180. // プレイヤーの手を表示する。
  181. protected void printHands() {
  182. String str = "";
  183. for (int i = 0; i < 3; ++i) {
  184. Hand hand = Hand.values()[i];
  185. str += hand.toString() + " は ";
  186. str += handCounters[i];
  187. str += " 人、";
  188. }
  189. str += " です。";
  190. println(str);
  191. }
  192.  
  193. // 判定。
  194. protected boolean judge() {
  195. countHands(); // 手を数える。
  196. printHands(); // 手を表示する。
  197.  
  198. // 手のばらつきを調べる。
  199. int x = 0;
  200. if (handCounters[0] > 0) ++x;
  201. if (handCounters[1] > 0) ++x;
  202. if (handCounters[2] > 0) ++x;
  203. if (x == 1 || x == 3) {
  204. return false; // あいこ。
  205. }
  206.  
  207. Hand y = Hand.無効な手;
  208. Hand z = Hand.無効な手;
  209.  
  210. for (int i = 0; i < numOfCpu; i++) {
  211. if (survival[i]) {
  212. if (handCounters[hands[i].ordinal()] > 0) {
  213. if (hands[i] == y) {
  214. ;
  215. } else if (y == Hand.無効な手) {
  216. y = hands[i];
  217. } else {
  218. z = hands[i];
  219. break;
  220. }
  221. }
  222. }
  223. }
  224.  
  225. if (false) {
  226. println(y.toString());
  227. println(z.toString());
  228. }
  229.  
  230. // 勝者と敗者を出力。
  231. Hand winnersHand = getWinnersHand(y, z);
  232. println("勝ったのは " + winnersHand.toString() + " です。");
  233. for (int i = 0; i < numOfCpu; i++) {
  234. if (survival[i]) {
  235. if (hands[i] != winnersHand) {
  236. // 負け。
  237. println(playerNames[i] + "が負けました。");
  238. survival[i] = false; // ここでプレイヤーが死ぬ。
  239. }
  240. }
  241. }
  242.  
  243. return true; // 勝敗あり。
  244. }
  245.  
  246. // 生き残りの人数を数える。
  247. protected int getSurvivorCount() {
  248. int num = 0;
  249. for (int i = 0; i < numOfCpu; ++i) {
  250. if (survival[i]) {
  251. ++num;
  252. }
  253. }
  254. return num;
  255. }
  256.  
  257. // 生き残りのプレイヤーインデックスを取得する。
  258. // 失敗の場合-1を返す。
  259. protected int getSurvivor() {
  260. for (int i = 0; i < numOfCpu; ++i) {
  261. if (survival[i]) {
  262. return i;
  263. }
  264. }
  265. return -1;
  266. }
  267. }
  268.  
  269. // メイン関数。
  270. public static void main(String[] args) {
  271. java.util.Scanner scanner = new java.util.Scanner(System.in);
  272. ComputerNJanken janken = new Main.ComputerNJanken(scanner);
  273. janken.play();
  274. }
  275. }
  276.  
Success #stdin #stdout 0.07s 4386816KB
stdin
無効な入力のテスト
8
stdout
コンピュータ同士でジャンケンをします。
対戦人数を入力して下さい(2人以上10人以内): 無効な値です。入力をやり直して下さい。
対戦人数を入力して下さい(2人以上10人以内): グー は 3 人、チョキ は 2 人、パー は 3 人、 です。
あいこです。
この時点で残っているのは CPU#0 と CPU#1 と CPU#2 と CPU#3 と CPU#4 と CPU#5 と CPU#6 と CPU#7です。
グー は 2 人、チョキ は 2 人、パー は 4 人、 です。
あいこです。
この時点で残っているのは CPU#0 と CPU#1 と CPU#2 と CPU#3 と CPU#4 と CPU#5 と CPU#6 と CPU#7です。
グー は 3 人、チョキ は 2 人、パー は 3 人、 です。
あいこです。
この時点で残っているのは CPU#0 と CPU#1 と CPU#2 と CPU#3 と CPU#4 と CPU#5 と CPU#6 と CPU#7です。
グー は 3 人、チョキ は 2 人、パー は 3 人、 です。
あいこです。
この時点で残っているのは CPU#0 と CPU#1 と CPU#2 と CPU#3 と CPU#4 と CPU#5 と CPU#6 と CPU#7です。
グー は 5 人、チョキ は 3 人、パー は 0 人、 です。
勝ったのは グー です。
CPU#2が負けました。
CPU#5が負けました。
CPU#6が負けました。
グー は 2 人、チョキ は 2 人、パー は 1 人、 です。
あいこです。
この時点で残っているのは CPU#0 と CPU#1 と CPU#3 と CPU#4 と CPU#7です。
グー は 1 人、チョキ は 2 人、パー は 2 人、 です。
あいこです。
この時点で残っているのは CPU#0 と CPU#1 と CPU#3 と CPU#4 と CPU#7です。
グー は 3 人、チョキ は 1 人、パー は 1 人、 です。
あいこです。
この時点で残っているのは CPU#0 と CPU#1 と CPU#3 と CPU#4 と CPU#7です。
グー は 2 人、チョキ は 1 人、パー は 2 人、 です。
あいこです。
この時点で残っているのは CPU#0 と CPU#1 と CPU#3 と CPU#4 と CPU#7です。
グー は 2 人、チョキ は 0 人、パー は 3 人、 です。
勝ったのは パー です。
CPU#0が負けました。
CPU#1が負けました。
グー は 1 人、チョキ は 2 人、パー は 0 人、 です。
勝ったのは グー です。
CPU#3が負けました。
CPU#4が負けました。
勝者はCPU#7です。