はじめに
ミニマムなゲーム作りをしたいということで、Linuxを触りながらJavaを使ってシンプルなじゃんけんゲームを作成しています。
前回は、プレイヤーの入力を受け付け、CPUの手をランダムに決める処理を実装し、プレイヤーとCPUそれぞれの手を決められるようになりました!
今回はじゃんけんとして遊べる状態にするために、次の機能を追加します。
- プレイヤーとCPUの勝敗を判定する
- あいこの判定を行う
- 「1」「2」「3」で管理している手を「グー」「チョキ」「パー」と表示する
今回は、これまで数字として扱っていたプレイヤーとCPUの手を比較して勝敗を判定し、さらに結果を分かりやすく表示できるようにしていきます。
前提事項
前提事項としては以下のとおりです。
使用環境・ツール
- OS:Windows11 Home
- CPU:Intel
- Linux環境:Ubuntu
- OpenJDK 21
補助ツール
Chat GPT
AIにも慣れておきたいなぁ、ということで使用しています。
学習目的のため、実行するコマンドをただ提示させるのではなく、コマンドを実行する理由やコマンドの意味もをあわせて提示するように指示しました。
※念のため実際に説明や解釈が合っているか調べて確認しています。
その他
この記事内では、実行コマンドの下にコマンドの意味を記載しています。
今回のじゃんけんゲームのルール
前回までの実装では、プレイヤーとCPUの手を数字で管理しています。
今回も、以下のルールをそのまま使用します。
1 = グー
2 = チョキ
3 = パー
【例】
プレイヤー:1 → グー
CPU:2 → チョキ
なら、グーvs チョキになるので、プレイヤーの勝ちです。
if文で勝敗を判定する
では実際に機能を実装していきます。
まず、前回保存したソースコードに追記するため、コマンドラインにvim Janken.javaを入力し、Vimを開きます。
ここではまず、プレイヤーとCPUの手が同じかどうかを判定します。
if (playerHand == cpuHand) {
System.out.println("あいこです!");
}
ここで使用している==は、2つの値が同じかどうかを比較する演算子です。
例えば、
playerHand == cpuHand
なら、
「playerHandとcpuHandは同じですか?」
という意味になります。
プレイヤーとCPUが同じ手を出した場合は、あいこなので、
あいこです
と表示します。
プレイヤーの勝ちを判定する
次に、プレイヤーが勝つ条件を追加します。
じゃんけんでプレイヤーが勝つのは、次の3パターンです。
1(グー)vs 2(チョキ)
2(チョキ)vs 3(パー)
3(パー)vs 1(グー)
となります。
これをJavaで表すと、
else if ((playerHand == 1 && cpuHand == 2)|| (playerHand == 2 && cpuHand == 3)|| (playerHand == 3 && cpuHand == 1)) {
System.out.println("あなたの勝ち!");
}
となります。
ここでは&&と||という演算子を使っています。
&&は「~かつ」という意味
演算子の&&は「~かつ」という意味をもちます。
どういう風に使うのか?ですが例えば、
playerHand == 1 && cpuHand == 2
は、プレイヤーの手が1で、かつCPUの手が2という意味です。
つまり、プレイヤー・・・1(グー) vs CPU・・・2(チョキ)
という条件になります。
||は「または」を意味する
一方、||は「または」という意味を持ちます。
そのため、以下のように記述することで次のような条件を作ることができます。
(playerHand == 1 && cpuHand == 2)|| (playerHand == 2 && cpuHand == 3)|| (playerHand == 3 && cpuHand == 1)
プレイヤー・・・1(グー) vs CPU・・・2(チョキ)
または
プレイヤー・・・2(チョキ) vs CPU・・・3(パー)
または
プレイヤー・・・3(パー) vs CPU・・・1(グー)
この3つの条件のどれかに当てはまれば、プレイヤーの勝ち
負けの場合をelseで処理する
最後に、プレイヤーとCPUの手が同じでない、かつ上記の条件も満たしていない場合、つまり負けたときのを処理を実装していきます。
else {
System.out.println("あなたの負け!");
}
これを組み合わせると、勝敗判定は次のようになります。
if (playerHand == cpuHand) {
System.out.println("あいこです!");
} else if ((playerHand == 1 && cpuHand == 2)|| (playerHand == 2 && cpuHand == 3)|| (playerHand == 3 && cpuHand == 1)) {
System.out.println("あなたの勝ち!");
} else {
System.out.println("あなたの負け!");
}
処理の流れとしては、
プレイヤーとCPUの手が同じか?
↓
NO YES → あいこ
↓
プレイヤーが勝つ条件になっているか?
↓
NO YES → プレイヤーの勝ち
↓
プレイヤーの負け
となります。
実際に動かしてみる
あいこやCPUに勝ったりと、勝敗判定が正しく行われることを確認しました。
これで、プレイヤーとCPUの手を決めるだけだったゲームから、実際に勝敗を判定できるじゃんけんゲームになりました!
CPUの「2」ではなく「チョキ」と表示したい
勝敗判定ができるようになったところで、もう一つ気になるところがあります。
現在、CPUの手を表示すると、
CPU:2
のように数字で表示されます。
......なんだか味気ないですよね
ゲームとして考えると、
CPU:チョキ
と表示されたほうが分かりやすいと思います。
そこで、数字を「グー」「チョキ」「パー」に変換する処理を作ります。
String型を使って手の名前を保存する
手の名前は文字列なので、String型の変数に保存します。
String playerHandName;
Stringは、文字列を扱うためのデータ型です。
例えば、
String name = "グー";
とすると、nameという変数に「グー」という文字列を保存できます。
今回は、
1 → グー
2 → チョキ
3 → パー
という変換結果を文字列として扱います。
getHandNameメソッドを作る
ここで、数字を手の名前に変換する処理をメソッドとしてまとめます。
static String getHandName(int hand) {
if (hand == 1) {
return "グー✊";
} else if (hand == 2) {
return "チョキ✌";
} else {
return "パー✋";
}
}
※チョキだけQiitaだと黄色い手にならないのですが、開発環境ではグーやパーと同じ黄色い手になっています。
このメソッドは、整数を1つ受け取って、手の名前を文字列として返します。
例えば、
getHandName(1)ならグーが、
getHandName(2)ならチョキが、
getHandName(3)ならパーが返ってきます。
int handとは?
ここで、
static String getHandName(int hand) {
:
という部分が出てきました。
これは、handというメソッドが整数を1つ受け取ることを表しています。
例えば、
getHandName(playerHand)
と書いた場合、playerHandに入っている数字がhandに渡されます。
playerHand = 1
↓
getHandName(playerHand)
↓
hand = 1
↓
「グー」を返す
という流れです。
returnとは?
getHandName()の中には、
return "グー";
という記述があります。
returnは、メソッドから値を呼び出し元へ返すために使います。
例えば、
return "グー✊";
なら、
「グーという文字列を返す」
という意味です。
そのため、
String playerHandName = getHandName(playerHand);
と書くと、
playerHand
↓
getHandName()
↓
手の名前を返す
↓
playerHandNameに代入
という流れになります。
プレイヤーとCPUの両方で使う
今回作ったgetHandName()は、プレイヤーにもCPUにも利用できます。
String playerHandName = getHandName(playerHand);
String cpuHandName = getHandName(cpuHand);
例えば、
playerHand = 1
cpuHand = 3
だった場合、
getHandName(1) → グー
getHandName(3) → パー
となります。
そして、
System.out.println("あなた:" + playerHandName);
System.out.println("CPU:" + cpuHandName);
とすることで、
あなた:グー
CPU:パー
と表示できます。
ここで使っている+は、文字列とplayerHandやcpuHandNameに入っている値をつなげるために使用しています。
なぜわざわざメソッドにするのか?重要な保守性について
例えば、playerHand = 1は、私たちには「1=グー」と分かります。
それならわざわざ、以下のように記述する必要はないのでは?
もっと簡単にならないの?と考えました。
playerHand
↓
getHandName(1)
↓
「グー」
しかし、Javaというシステムからすると、「1=グー」なんて知ったこっちゃないのです。
Javaにとっては、playerHandという整数型の変数に1を入れた、というただそれだけです。
int playerHand = 1;
そもそも「1=グー」というのは、今回のゲームを作るために人間側が決めたルールです。
そこで、そのルールを実現するためにメソッドを使うのです。
さらに、この処理はプレイヤーにもCPUにも必要です。
となると、以下のようにgetHandNameという同じメソッドを使い回せるため、同じ処理を2回書かずに済みます。
String playerHandName = getHandName(playerHand);
String cpuHandName = getHandName(cpuHand);
今回のように、
同じ処理を何度も使うなら、1つにまとめる
という考え方は、今後プログラムを作っていくうえでも重要になります。
今は個人開発であり、簡単なプログラムなので保守性も考える必要はないですし、データも大きくありません。
しかし、さまざまな機能を作っていくとデータは大きくなります。
そして一部分のプログラムを変更したいとなったときに、同じ処理を複数個所にばら撒いていると
「こっちは直したけど、あっちは直していない」
みたいなことが発生し、それがバグにつながります。
これではいけませんね。
なので、プログラミングにおいては同じ処理を何度も使うなら1つにまとめることが大切なのです。
今回の実装結果
ここまで実装すると、実行結果は以下のようになりました。

(初手から負けてしまいました笑)
このように、数字ではなく手の名前が表示されるようになりました。
これで、
- プレイヤーの手を入力する
- CPUの手をランダムに決める
- プレイヤーとCPUの手を表示する
- 勝敗を判定する
という、じゃんけんの基本的な流れが完成しました。
まとめ
今回は、前回までに作った「プレイヤーとCPUの手を決める処理」に、勝敗判定と手の名前の表示を追加しました。
今回学んだことは以下のとおりです。
-
if、else if、elseによる条件分岐 -
==による値の比較 -
&&による「かつ」の条件 -
||による「または」の条件 -
String型による文字列の扱い - メソッドの作成
- 引数
int hand -
returnによる値の返却 - 同じ処理をメソッドにまとめて再利用する考え方
最初はCPUがランダムに数字を出すだけだったゲームですが、少しずつ機能を追加することで、だんだん「ゲーム」らしくなってきました。
次回は、今回作ったじゃんけんを1回で終了させず、何度も遊べるようにする機能を追加していきます。
「もう一度遊びますか?」という文言の表示と、yesかnoをy/nで入力できるようにして、よりゲームらしい形にしていきたいと思います。
これができたら、結構ちゃんとしたゲームになってきそうですよね!
