【switch編】Java言語で『じゃんけんゲーム』を作る
Java言語でプログラミングの勉強をしていくと、「じゃんけんゲーム」を作るというサンプルや課題が出てきます。
以前の記事では「if文を利用した作り方」について説明しました。今回は、「switch文を利用した作り方」について説明します。
プログラムを作る場合、正解はありません。どのようなプログラムを記述していても、最終的にユーザ(お客さん)が求める結果が得られれば、それが正解です。
同じ結果を得る場合でも、実は色々なプログラムの作り方があります。今回は【if編】とは違ったアプローチでプログラムを作成しています。
なお、if文を利用した作り方については、以下の記事を参考にしてください。
まず、この記事は以下のような人を対象としています。
対象者・Java言語でじゃんけんゲームの作り方を知りたい人
・switch文を使ってじゃんけんゲームを作りたい人
・if文とswitch文では、どのような違いになるのか知りたい人
この記事を読むと、次のようなことが理解できるようになります。
この記事を読むとできること・Java言語でじゃんけんゲームを作ることができる
・色々な作り方を知ることができる
if文を利用したじゃんけんゲームのプログラムを以前説明しました。
今回はswtich文を利用したプログラムを紹介します。
同じじゃんけんゲームでも、色々な作り方があるんですね!!
ぜひ、if文を利用したプログラムと比較してみて下さい。
どちらが正しいとかはありません。
とにかく、色々な作り方に慣れる必要があります。
メソッドの書き方を詳しく説明した記事を追加しました。ぜひ参照してください。
Java言語の基本を勉強したい人は次の書籍がおススメです!!
じゃんけんゲームの仕様
今回作成するじゃんけんゲームの仕様は、以前紹介した「if編」と同じです。
- グーは「0」、チョキは「1」、パーは「2」で表現する
- ユーザのじゃんけんの手は、キーボードから入力してもらう
- 「0」「1」「2」以外のデータが入力された時は、再入力させる
- コンピュータ側のじゃんけんの手は、乱数で自動的に求める
- ユーザの判定結果(勝ち、負け、引き分け)を画面に表示する
- メソッドを利用して作成する
もちろん今回も3部構成で考え、さらにメソッドで作っていきます。
プログラムの3部構成については、以下の記事を参照してください。
作成するメソッドの設計
仕様を元に、作成する各種メソッドを以下のようにします。これも、「if編」と全く同じです。
機能 | メソッド名 | 引数 | 戻り値 |
ユーザ側のじゃんけんの手を求める | getUser() | なし | 整数(0/1/2) |
コンピュータ側のじゃんけんの手を求める | getPc() | なし | 整数(0/1/2) |
ユーザの勝敗を判定する | judgeJanken() | ユーザの手(整数)、
コンピュータの手(整数) |
文字列 |
結果を表示する | showResult() | ユーザの手(整数)、
コンピュータの手(整数)、 判定結果(文字列) |
なし |
main()メソッドの内容(途中)
決定したメソッドをまずは、main()内に記述します。記述した内容は以下の通りです。
なお、まだ各メソッドの詳細内容を記述していないので、コンパイルエラーとなっていますが、気にする必要はありません。
もちろん、このmain()メソッド内の記述も「if編」のものと全く変わりません。
このようにmain()メソッド内に詳細な処理を記述せずにメソッド名のみ記述しておけば、処理方法がif文からswitch文に変わっても、main()メソッドの内容は全く修正する必要がなくなります。
※ この記事の最後には全てのコードを記載しています。
ユーザの手を取得:getUser()メソッド
ユーザの手をキーボードから入力するメソッドを説明します。
キーボードからデータを入力させる場合、「Scannerクラス」を利用します。
Scannerクラスの具体的な使い方は、今回は省略します。確認したい人は以下の記事を参照してください。
getUser()メソッドの記述内容
ユーザのじゃんけんの手をキーボードから入力してもらうメソッドの記述内容は以下のようになります。
「if編」では、「ScannerクラスのhasNext系のメソッド」を使って、正しいデータかどうかをチェックしていましたが、折角ですから今回は別の方法として「例外処理」を使ってデータのチェックを行います。
無限ループ
ユーザは1回で正しいデータを入力するかは不明です。何度も間違えるかも知れません。このような操作に対応するためには通常「無限ループ」を利用します。
正しいデータが入力されたかどうかをチェックし、正しい場合は無限ループを終了し、間違えている場合は無限ループを繰り返します。
例外処理
このサンプルでは、ユーザが入力したじゃんけんの手が整数かどうかのチェックを行わず、いきなり文字列として読み込んでいます(36行目)。
そして読み込んだデータを「Integer.parsInt()メソッド」で整数に変換しています。もし、読み込んだデータが整数の場合、例外は発生せず、指定した変数「numer」に代入されます。
しかし、小数点を含む値や文字列を入力している場合、整数に変換することができないのでNumberFormatException例外が発生します。
つまり、「例外が発生するか、しないか」で「入力されたデータが整数かそれ以外かをチェック」しています。
例外が発生した場合は、メッセージを表示して再入力処理に戻ります。
コンピュータの手を取得:getPc()メソッドの記述
コンピュータのじゃんけんの手を乱数で作成するメソッドの記述内容は以下のようになります。
このメソッドの処理内容も折角なので、「Randomクラス」ではなく「Mathクラスの各種メソッド」を使って作成します。
getPc()メソッドの記述内容
Mathクラスの各種メソッド
Mathクラスは「四捨五入」や「コサイン」など各種算術用のメソッドがまとめて定義されています。通常、他のクラスで定義されているメソッドは、new演算子でインスタンスを作成しなければ利用することはできません。しかし、これらのメソッドは頻繁に利用されるため、毎回わざわざインスタンスを作るのは面倒になります。
そこで、これらのメソッドはクラスメソッドとして定義されており、インスタンスを作成しなくても利用できるようになっています。
インスタンスを作成しなくても利用することができるのですが、その代わりに利用する時はクラス名を一緒に記述する決まりになっています。したがって、メソッド名の前にはクラス名として「Math.」を付けなければなりません。
Mathクラスの主なメソッドは以下の通りです。
メソッド名 | 機能 | 戻り値 |
ceil() | 小数点以下の切り上げ | double型 |
floor() | 小数点以下の切り下げ | double型 |
round() | 小数点以下の四捨五入 | double型 |
random() | 0.0から0.9999・・・の範囲で乱数を1つ生成 | double型 |
pow() | 累乗 | double型 |
Mathクラスのメソッドを使って乱数を求める方法
- Math.random()メソッドを実行し、乱数を1つ生成する
- 求めた値に乱数の種類(整数)を掛ける
- Math.floor()メソッドで小数点以下を切り捨てる
- 最後にint型にキャストする
まず、「Math.random()」メソッドを実行して、「0.0~0.9999・・・」の小数点を含む乱数を1つ作ります。この求めた値に生成したい乱数の種類を掛け算します。今回、求めたい乱数は「0,1,2の3種類のうちのどれか」なので、「3」を掛けます。求めた乱数に3を掛けると、「0.0~2.999・・・」の値になります。
次に、この値の小数点以下を切り捨てます。その結果、「0.0~2.999・・・」の値は「0.0~2.0」に変わります。つまり、小数点以下の余計な値を除外します。
求めた整数は小数点を含むdouble型ですが、使いたいじゃんけんの手はint型の整数です。したがって、double型で求められた値をキャスト「(int)」を使って型変換しています。この処理を行うと小数点以下が切り捨てられます。
具体的な値を使って説明します。
- Math.random()を実行したら、「0.4」が生成された
- 「0.4」に「3」を掛けると、「1.2」となる
- Math.floor()で小数点以下を切り捨てると、「1.0」となる
- 最後にint型にキャストすると「1」となる
つまり、この場合、結果として「1」という値が乱数の結果として返されます。
もう1つ具体的に計算してみます。
- Math.random()を実行したら、「0.9」が生成された
- 「0.9」に「3」を掛けると、「2.7」となる
- Math.floor()で小数点以下を切り捨てると、「2.0」となる
- 最後にint型にキャストすると「2」となる
したがって、この場合返される乱数の値は「2」となります。
Randomクラスは非常に便利ですが、他のプログラム言語では利用できないことがあります。しかし、このMathクラスのメソッドを利用する方法は他のプログラム言語でも利用できる場合があります。したがって、この方法も覚えておけば、乱数を作るプログラムを作成する場合、困ることはないでしょう。
勝敗の判定:judgeJanken()メソッドの記述
では、次にじゃんけんの判定を行うjudgeJanken()メソッドの内容を考えてみましょう。
プログラムを記述する前に、今回もじゃんけんの判定を実際に日本語で表現してみます。
今回はswtich文を利用するので「場合分け」で考えてみます。
ユーザの手が「0(グー)」の場合(ケース)では、コンピュータの手は「グー」「チョキ」「パー」の3つの場合(ケース)があります。ユーザの手が「1(チョキ)」、「2(パー)」の場合もコンピュータの手は同じように3ケースあるので、それらを全て書き出すと、次のようになります。
①.ユーザが0(グー)の場合で、コンピュータが0(グー)の場合は、「あいこ」
②.ユーザが0(グー)の場合で、コンピュータが1(チョキ)の場合は、「勝ち」
③.ユーザが0(グー)の場合で、コンピュータが2(パー)の場合は、「負け」
④.ユーザが1(チョキ)の場合で、コンピュータが0(グー)の場合は、「負け」
⑤.ユーザが1(チョキ)の場合で、コンピュータが1(チョキ)の場合は、「あいこ」
⑥.ユーザが1(チョキ)の場合で、コンピュータが2(パー)の場合は、「勝ち」
⑦.ユーザが2(パー)の場合で、コンピュータが0(グー)の場合は、「勝ち」
⑧.ユーザが2(パー)の場合で、コンピュータが1(チョキ)の場合は、「負け」
⑨.ユーザが2(パー)の場合で、コンピュータが2(パー)の場合は、「あいこ」
judgeJanken()メソッドの記述内容
以上のことを踏まえて、勝敗判定の記述内容は以下の通りとなります。
switch文の中に別のswtich文が記述されているので、非常に分かりずらいかも知れませんが、上で説明した①~⑨の項目と比較すれば、内容を把握できると思います。
このような判定方法もあるということを確認してください。
※ メソッドを記述した結果、import文が追加され、実際の行番号は変化しています。
結果の表示:showResult()メソッドの記述
以上で全ての処理が終了したので、結果を表示するメソッドを記述していきます。
まず、じゃんけんの手を「グー、チョキ、パー」という文字列で表示したいので、それらをString型の配列に保存しておきます( 113行目)。
配列の添え字は「0」から始まるので、添え字「0」には「グー」、添え字「1」には「チョキ」、添え字「2」には「パー」の文字列を保存します。ちょうど、添え字とじゃんけんの手を表す値が一致するようにします。
あとは、メソッドを呼び出す時にユーザの手とコンピュータの手が引数として渡されているので、その値を配列の添え字に指定すると、それぞれの手が文字列として取得できます。
System.out.printf()による出力
printf()メソッドは、標準出力(デフォルトはディスプレイ)に結果を表示する際に、様々な書式を指定することができます。
みなさんは、小数点を含む値を表示する時に「小数点以下第2位まで表示したいけど、どうしたら良いのか分からない・・・」ということはありませんか?
Mathクラスのround()メソッドを使って、値を小数点以下第2位になるように加工することができますが、この方法は以外と面倒です。Mathクラスのround()メソッドは「小数点以下第1位を四捨五入」するため、「小数点以下第3位を四捨五入する」処理は簡単にできません。
小数点以下第3位を四捨五入するために、小数点の位置を自分でずらす必要があります。
一方、printf()メソッドでは「値を小数点第2位までで表示する」といった書式を簡単に指定することができます。「Mathクラスのメソッドを使うと値が処理された変わっている」のですが、printf()メソッドでは「表示する時に見え方を変えているだけで値そのものは変わらない」ので注意して下さい。
まず、()内に「”」で表示したい内容を指定します。表示するメッセージはそのまま記述し、変数や計算式の結果を表示したい部分にはどんなデータを表示するのか「書式指定子」を記述します。
書式指定子はデータ型によって記述する英字が異なります。整数であれば「d(decimal):10進数」、小数点数であれば「f(float)」、文字列であれば「s(string)」となります。他にも書式指定子はありますが、とりあえずこの3つが良く使用されます。
printf()メソッドは、出力後に改行できないので、改行したければ明示的に「%n」と記述します。なお、「%n」は「”」内であれば幾つでも記述することができます。
「”」内で表示するメッセージの書式を指定しているので、()内の第2引数以降では、実際に表示する値を変数や計算式などで記述します。
第2引数以降に指定した値は「”」内の書式指定子の順番と一致します。最初に記述した「%d」には第2引数の「janken[user]」の値、次に指定した「%d」には「janken[pc]」の値が順番に代入されます。
表示する桁数を指定したい場合は「%5d」のように「%と英字の間に桁数」を記述します。この場合、整数を最大5桁で表示します。また、小数点以下の桁数を指定したい場合は、「%全体の桁数.小数点以下の桁数f」という形式で指定します。「%8.2f」と記述すると「全体が8桁、小数点以下は第2位まで表示(小数点以下第3位を四捨五入)する」となります。なお、全体の8桁には小数点の「.」も含まれるため、表示できる数値は全体で7桁となります。
全コード
以下に全コードを記載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
package mygame; import java.util.Scanner; public class JankenSwitch { public static void main(String[] args) { // ユーザの手をキーボードから入力してもらう int user = getUser(); // コンピュータの手を乱数で作成する int pc = getPc(); // 勝敗の判定を行う String result = judgeJanken(user, pc); // 結果を表示する showResult(user, pc, result); } public static int getUser() { // キーボード入力の準備 Scanner stdin = new Scanner(System.in); // 無限ルール while (true) { // メッセージの表示 System.out.println("あなたのじゃんけんの手を入力して下さい"); System.out.print("(グー:0、チョキ:1、パー:2) --> "); // 例外処理でデータのチェックを行う try { // トークンを文字列として読み込む String token = stdin.next(); // 文字列を整数に変換し、変数に代入 // 整数に変換できない場合、例外が発生 int number = Integer.parseInt(token); // 整数でも有効なのは「0,1,2」のみ if (number <= -1 || number >= 3) { // 範囲外は無効なデータなのでやり直し System.out.println("【エラー】入力できるのは「0~2」です"); continue; } else { // 0,1,2の場合、メソッドの結果として返す return number; } } catch (NumberFormatException e) { // 整数以外の場合、無効なデータなのでやり直し System.out.println("【エラー】入力できるのは整数だけです"); } } } public static int getPc() { // Mathクラスを利用して乱数をもとめる int no = (int) Math.floor(Math.random() * 3); return no; } public static String judgeJanken(int user, int pc) { String result = ""; // 判定結果を保存する switch (user) { case 0: // ユーザの手が0「グー」の場合 switch (pc) { case 0:// コンピュータの手が0「グー」の場合 result = "あいこ"; break; case 1:// コンピュータの手が1「チョキ」の場合 result = "勝ち"; break; case 2:// コンピュータの手が2「パー」の場合 result = "まけ"; break; } break; case 1: // ユーザの手が1「チョキ」の場合 switch (pc) { case 0:// コンピュータの手が0「グー」の場合 result = "まけ"; break; case 1:// コンピュータの手が1「チョキ」の場合 result = "あいこ"; break; case 2:// コンピュータの手が2「パー」の場合 result = "勝ち"; break; } break; case 2: // ユーザの手が2「パー」の場合 switch (pc) { case 0:// コンピュータの手が0「グー」の場合 result = "勝ち"; break; case 1:// コンピュータの手が1「チョキ」の場合 result = "まけ"; break; case 2:// コンピュータの手が2「パー」の場合 result = "あいこ"; break; } break; } // 勝敗結果を返す return result; } public static void showResult(int user, int pc, String result) { // じゃんけんの手を配列で定義 String[] janken = { "グー", "チョキ", "パー" }; // 結果の表示 System.out.printf("あなたの手:%s,コンピュータの手:%s\n", janken[user], janken[pc]); System.out.printf("結果:%s%n", result); } } |
実行結果
実際に今回のプログラムを実行した結果は以下の通りです。
入力チェックは次の5パターンです。
①.不適切なデータ(-1以下)
②.不適切なデータ(3以上)
③.整数以外のデータ(小数点を含む数値)
④.整数以外のデータ(文字列)
⑤.適切なデータ(0、1、2)のどれか
きちんと対応できていることが、確認できます。
まとめ
今回は、Java言語で「swtich文」を使って『じゃんけんゲーム』の作り方について説明しました。
switch文はif文と使い方が似ていますが、実際に比較するとその違いが理解できるかと思います。
if文を利用する場合、論理演算子を複数利用して条件式が複雑になりがちですが、swtich文を利用する場合、記述する場合分けの数は多くなりますが、直観的に判断することができます。
また、キーボードからデータを入力する方法も今回は「例外処理」を利用しています。さらに結果を出力する場合も、書式を指定することができるprintf()メソッドを利用しています。
プログラムを勉強する場合、プログラムを完成させたら終わりではなく、他の方法がないのか考えることが重要です。とにかく、様々な方法を体験してください。
・swtich文は場合分けを処理する際に利用する
・データ入力は例外処理でも実装することができる
・printf()を利用すると、書式を指定して結果を出力することできる
swtich文を利用したじゃんけんゲームのプログラムはどうでしたか?
ちょっとswtich文の記述が複雑ですね。
焦らずじっくり確認してみて下さい。