ここでの解答例はクラスやメソッドを省略してあるので各自で補って実行してください。
【lesson 2-1】
プレイヤー2人で順番に数を 1~3 足していき 31 を言わせたほうが勝ち。
最初は 0 からスタート。
(1~3)や(12~15)のように入力すべき数値を表示する。
そのとき 31 より大きい数は表示しないようにする。
範囲外の数値を入力した場合は再度同じプレイヤーの入力。
解答例へ
【lesson 2-2】
カイジのEカードを作る。
先手:皇帝1枚・市民4枚
後手:奴隷1枚・市民4枚
じゃんけんと同じ三すくみの関係 皇帝⇒市民⇒奴隷⇒皇帝
先手は皇帝を出したときに後手が奴隷を出さなければ勝ち。
後手は奴隷を出したときに先手が皇帝を出せば勝ち。
1ターン目は皇帝側が先にカードを出し奴隷側が後から出す。
2ターン目は奴隷側から、と交互に入れ替わる。
1ゲーム終わったら皇帝と奴隷を入れ替えてもう1ゲーム。合計2ゲーム行う
実際にはカードは伏せて両者出揃ったところで開示するが、
コンソールで入力すると相手の手が丸見えになるのはご愛敬。
解答例へ
【lesson 2-3】
数当てゲームを作る。
1~9 までの重複しない4つの数字をランダムに決める。
ユーザーが4桁の数字を入力する。
1桁ずつ見て、その数字が4つの中になければ「✖」
並んでる場所は違うが4つの中にあるなら「△」
場所も数字も一致するなら「◎」を表示する。
例)ランダム 3456 入力 1475 の場合「✖◎✖△」
4桁とも◎になったら何回目で正解したか表示する。
5回目で正解しなかったらゲームを終了する。
解答例へ
【lesson 2-4】
map[9][9] の配列を作り 0~8 を代入して下記の通り出力する。
(3×3のブロックごとに 0~8 が1つずつ)
0 1 2 0 1 2 0 1 2
3 4 5 3 4 5 3 4 5
6 7 8 6 7 8 6 7 8
0 1 2 0 1 2 0 1 2
3 4 5 3 4 5 3 4 5
6 7 8 6 7 8 6 7 8
0 1 2 0 1 2 0 1 2
3 4 5 3 4 5 3 4 5
6 7 8 6 7 8 6 7 8
解答例へ
【lesson 2-5】
解答例へ
【2-1 解答例】
// プレイヤー( 1 or 2 )
int player = 1;
// 足していく数値
int num = 0;
// 導入
System.out.println( "0 から始まり交互に 1~3 を足していき 31 を言わせたほうが勝ち" );
// 31になるまでループ
while( true ) {
// 正常な入力があるまでループ
do {
System.out.println( "プレイヤー[ " + player + " ]のターン" );
// 最大値31まで
int max = ( 31 < num + 3 )? 31 : num + 3;
// ユーザー入力
System.out.println( "( " + ( num + 1 ) + "~" + max + ")を入力してください" );
int usrInput = new java.util.Scanner( System.in ).nextInt();
// 入力値が範囲内なら num を更新してループを抜ける
if( num < usrInput && usrInput <= max ) {
num = usrInput;
break;
}
// 注意
System.out.println( "◆◆◆範囲内の数を入力してください◆◆◆" );
} while ( true );
// プレイヤー交代
player = player % 2 + 1;
// 31に到達していたら結果表示
if( num == 31 ) {
System.out.println( "プレイヤー" + player + "の勝利!" );
break;
}
}
int max = ( 31 < num + 3 )? 31 : num + 3;この行で31より大きくならないようにしている。
player = player % 2 + 1;この書き方はよく使う。if文を使わず 1 と 2 を順次切り替える方法。
0 と 1 で切り替えたい場合 player = ( player + 1 ) % 2;
0~5 を順番に繰り返したい場合 player = ( player + 1 ) % 6;
0~5 を逆順も考慮すると player = ( player + MAX + v ) % MAX;
v は 1 か -1 が入る。MAX は8人なら 8(定数)。
player = 0 のとき v = -1 なら player = 7
player = 7 のとき v = 1 なら player = 0
カーソルキーで選択肢を選んだり、左端へ行ったら右端から出てくるような場面で使える。
問題に戻る
【2-2 解答例】
// ゲーム回数 皇帝側を1回ずつで2回
final int MAX_GAME = 2;
// ターン数
final int MAX_TURN = 5;
// 皇帝側
int plyEmperor = 0;
// 奴隷側
int plySlave = 1;
// 先手プレイヤー
int plyPrimary = 0;
// 後手プレイヤー
int plySecondary = 1;
// 獲得ポイント
int[] points = new int[ 2 ];
// どちら?
String[] name = { "皇帝", "奴隷" };
// カード名
String[][] cName = { { "皇帝", "市民"},{ "奴隷", "市民" } };
// 皇帝と奴隷は1枚ずつでどちらかが場に出れば決着するので
// カードの枚数を把握する変数は必要ないよ!
// 2ゲームやるよ!
for( int game = 0; game < MAX_GAME; game++ ) {
System.out.println( "【 " + ( game + 1 ) + " ゲーム目】" );
// 煽るよ!
System.out.println( "カードは配られた。いざ決戦の時!\nプレイヤー【 "
+ ( plyEmperor + 1 ) + " 】が皇帝です。" );
// ターンは5回までだよ!
for( int turn = 0; turn < MAX_TURN; turn++ ) {
System.out.println( "【 " + ( turn + 1 ) + " ターン目】" );
// 先手がカードを出すよ!
System.out.println( "先手:プレイヤー " + ( plyPrimary + 1 ) + " " + name[ plyPrimary ]
+ "側\nカードを出してください。\n1:" + name[ plyPrimary] + " 2:市民" );
int usrInputP;
// 1 か 2 が入力されるまでしつこく繰り返すよ!
do {
// 1 か 2 を入力するけど -1 して 0 か 1 にしてるよ!
usrInputP = new java.util.Scanner(System.in).nextInt() -1;
// 市民がのこっているかチェックするよ!
if( turn == MAX_TURN -1 && usrInputP == 1 ) {
System.out.println( "市民はもう出払いました。" );
usrInputP = -1;
}
} while( usrInputP < 0 || 1 < usrInputP );
// 後手がカードを出すよ!
System.out.println( "後手:プレイヤー " + ( plySecondary + 1 ) + " " + name[ plySecondary ]
+ "側。\nカードを出してください。\n1:" + name[ plySecondary ] + " 2:市民" );
int usrInputS;
// 1 か 2 が入力されるまでしつこく繰り返すよ!
do {
usrInputS = new java.util.Scanner(System.in).nextInt() -1;
// 市民がのこっているかチェックするよ!
if( turn == MAX_TURN -1 && usrInputS == 1 ) {
System.out.println( "市民はもう出払いました。" );
usrInputS = -1;
}
} while( usrInputS < 0 || 1 < usrInputS );
// カードをめくるよ!
int p = ( plyEmperor == plyPrimary )? plyEmperor: plySlave;
System.out.println( "先手:" + cName[ p ][ usrInputP ] + " 後手:" + cName[ ( p + 1 ) % 2 ][ usrInputS ] );
// 勝敗判定するよ!
int turnResult = 0;
switch( usrInputP + usrInputS ) {
case 0: // 皇帝と奴隷が出揃った場合
System.out.println( "ついに…奴隷が…\n皇帝を…討ち取ったーー!!\n奴隷側5点獲得!\n");
points[ plySlave ] += 5;
turnResult = 2;
break;
case 1: // 皇帝か奴隷のどちらかが出た場合
if( ( p == plyEmperor && usrInputP == 0 )||( p == plySlave && usrInputS == 0 ) ) {
System.out.println( "皇帝は市民を虐殺した!\n奴隷は機を逃した…。\n皇帝側1点獲得!\n" );
} else {
System.out.println( "奴隷は市民にむごたらしく殺された!\n皇帝側1点獲得!\n" );
}
points[ plyEmperor ]++;
turnResult = 1;
break;
case 2: // 市民同士
System.out.println( "引き分け!\n" );
break;
}
// 勝敗がついたらループを抜けて1ゲーム終了だよ!
if( turnResult > 0 ) break;
// 勝敗がつかない場合は先手後手を入れ替えるよ!
plySecondary = plyPrimary;
plyPrimary = ( plyPrimary + 1 ) % 2;
}
System.out.println( game + 1 + " ゲーム目終了しました。\nプレイヤー1:" + points[ 0 ]
+ "点\nプレイヤー2:" + points[ 1 ] + "点\ny:続行 y以外:終了" );
String usrInput = new java.util.Scanner(System.in).nextLine();
// y が入力されなければループを抜けて終了
if( ! usrInput.equals( "y" ) ) break;
// 次のゲームの初期化
// 皇帝と奴隷を入れ替える
plySlave = plyEmperor;
plyEmperor = ( plyEmperor + 1 ) % 2;
// 先手は皇帝側
plyPrimary = plyEmperor;
plySecondary = plySlave;
// 文字列も入れ替え
String str = name[ 0 ];
name[ 0 ] = name[ 1 ];
name[ 1 ] = str;
cName[ 0 ][ 0 ] = cName[ 1 ][ 0 ];
cName[ 1 ][ 0 ] = str;
}
初心者向けとしては長くなったし、先手後手などがわかりづらいので参考にしなくても良いw
だが、これだけのコードでEカードを実装できるのはプログラミングの面白いところ。
MAX_GAME = 2 など定数をまとめておくと修正が楽。意味のわからないリテラルも減る。
勝敗判定を switch( usrInputP + usrInputS ) としてるのは
皇帝+奴隷=0(奴隷勝ち)
皇帝+市民=1 奴隷+市民=1(皇帝勝ち)
市民+市民=2(引き分け) になるから
問題に戻る
【2-3 解答例】
// 何ターンやるか
int MAX_TURN = 5;
// 4つの数字
int[] num = new int[ 4 ];
// 何ターン目で正解したか
int correctTurn = 0;
// 重複無しでランダム生成
for( int i = 0; i < num.length; i++ ) {
boolean isMuch = false;
int n = new java.util.Random().nextInt( 9 ) + 1;
for( int j = 0; j < i; j++ ) {
// 同じものがあれば true
if( num[ j ] == n ) isMuch = true;
}
// true なら i-- して巻き戻し
if( isMuch ) {
i--;
continue;
}
// false なら代入
num[ i ] = n;
}
System.out.println( "4桁の数字を入力してください" );
for( int turn = 0; turn < MAX_TURN; turn++ ) {
// ユーザー入力
int usrInput = new java.util.Scanner( System.in ).nextInt();
// 4桁の数値を1桁ずつ取り出す 2345 なら { 2, 3, 4, 5 } にする
int[] in = new int[ 4 ];
for( int i = 3; i > -1; i-- ) {
in[ i ] = usrInput % 10;
usrInput /= 10;
}
// 比較照合
String comp = "";
for( int i = 0; i < num.length; i++ ) {
if( in[ i ] == num[ i ] ) {
// 場所と数字が合っている
comp += "◎";
} else {
boolean isMuch = false;
for( int j = 0; j < num.length; j++ ) {
if( in[ i ] == num[ j ] ) {
isMuch = true;
}
}
if( isMuch ) {
// 場所は違うが数字は合っている
comp += "△";
} else {
// その数字は含まれない
comp += "✖";
}
}
}
System.out.println( comp );
if( comp.equals( "◎◎◎◎") ) {
correctTurn = turn + 1;
break;
}
}
if( correctTurn > 0 ) {
System.out.println( correctTurn + "回目で正解しました!" );
} else {
System.out.println( "えっ!?" + MAX_TURN + "回もやったのに当てられないの?" );
System.out.println( "正解は " + num[ 0 ] + num[ 1 ] + num[ 2 ] + num[ 3 ] );
}
4桁を1桁ずつ取り出すのは簡単で usrInput % 10 で1の位が取り出せる。
usrInput / 10 すれば10の位が1の位に来るので同じ繰り返しで4桁取り出せる。
右側から取り出すので for( int i = 3; i > -1; i-- ) と、添え字を 3~0 に減らしていく。
for文と if文の多重ネストがあるが1つずつ追っていけば難しくはない。
ネストはインデントの位置でスコープがどこまでなのかきっちり把握しよう!
そのためには「ctrl」+「shift」+「F」でコード整形!
問題に戻る
【2-4 解答例】
int[][] map = new int[9][9];
for (int y = 0; y < 9; y += 3) {
for (int x = 0; x < 9; x += 3) {
for (int i = 0; i < 9; i++) {
map[i / 3 + y][(i % 3) + x] = i;
}
}
}
// for(int i = 0; i < 81; i++) map[i / 9][i % 9] = ((i / 9 * 3) + (i % 3)) % 9;
// 出力
for (int y = 0; y < 9; y++) {
for (int x = 0; x < 9; x++) {
System.out.print(map[y][x] + " ");
}
System.out.println("");
}
i が代入する数値。
for文の()の中で y と x は += 3 となっていることに注意。3×3ごとのブロックに分けている。
①[i / 3 + y] は i が 3 増えるごとに y が増える。
②[(i % 3) + x] は i が 0~2 を繰り返す。
①と②の組み合わせで3×3のブロックが 0~8 で埋まる。
わかりづらかったらデバッガーで追ってみよう!
コメントアウトした行では for文をネストせずに1行で同じ処理をしている。
問題に戻る
【2-5 解答例】
問題に戻る