mastermindゲームの課題回答用
package jp.hrst.sample;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Mastermind {
/** 入力サイズ */
private static int BET_SIZE = 4;
/** 挑戦回数 */
private static int TRY_COUNT = 10;
/**
* @param args
*/
public static void main(String[] args) throws IOException {
// 正解
String ownerBet = ownerBet();
// 入力待ち
for(int i = 0; i <= TRY_COUNT; i++ ) {
// 入力文字列読み込み
BufferedReader r = new BufferedReader(new InputStreamReader(System.in),1);
String playerBet = r.readLine();
// 入力文字列の内容確認
while (!validateArgs(playerBet)) {
System.out.println("Please, input unique 4-digit number.");
}
// blow: 正当に含まれる文字の数
int blow = countBlow(playerBet, ownerBet);
// hit: 正答と位置が同じ場所に出現した文字の数
int hit = countHit(playerBet, ownerBet);
// hit が文字列数と同じならば正解
if (hit == BET_SIZE) {
System.out.println("that's right! correct number is" + ownerBet + ".");
break;
}
else {
// 回答の回数が制限に達していたら正解を示して終了
if(i == (TRY_COUNT - 1)) {
System.out.println("game over! correct number is" + ownerBet + ".");
break;
}
// hit とblow の数をヒントにして与える
System.out.println("hits: " + hit +", blow: " + blow + "! try again.");
}
}
}
/**
* 挑戦者(入力)の文字列とオーナー(プログラム)の文字列を比較して,
* 同じ位置に同じ文字が出現した回数を返す
*
* @param playerBet
* @param ownerBet
* @return hit
*/
private static int countHit(String playerBet, String ownerBet) {
int hit = 0;
int length = playerBet.length();
for(int i = 0; i < length; i++ ) {
if(playerBet.charAt(i) == ownerBet.charAt(i) ) {
hit += 1;
}
}
return hit;
}
/**
* 挑戦者(入力)の文字列とオーナー(プログラム)の文字列を比較して,
* 順番は関係なく同じ文字が出現した回数を返す
*
* @param playerBet
* @param ownerBet
* @return blow
*/
private static int countBlow(String playerBet, String ownerBet) {
int blow = 0;
int length = playerBet.length();
for(int i = 0; i < length; i++) {
if(ownerBet.indexOf(playerBet.charAt(i)) != -1) {
blow += 1;
}
}
return blow;
}
/**
* 挑戦者の入力した文字列の内容の妥当性を図る
* 4桁の数字で,かつ,同じ文字を使っていなければ妥当.
*
* @param s
* @return
* @throws NumberFormatException
*/
private static Boolean validateArgs(String s) throws NumberFormatException {
// 数値以外をInteger.perseInt() の成否で検討
try{
Integer.parseInt(s);
int length = s.length();
// 4桁以上であれば不当
if (length > BET_SIZE) {
return false;
}
// 同じ文字が含まれていれば不当
// 4文字目は比較しない
for(int i = 0; i < length - 1; i++ ) {
// 調べる文字が,それ以降の場所に出現するか確認
if(s.indexOf(s.charAt(i), i+1) != -1) {
return false;
}
}
return true;
} catch(NumberFormatException e) {
// キャッチした例外は処理せず「不当」扱いとしてfalseだけ返す
return false;
}
}
/**
* オーナー(プログラム)の選択した4桁の数値を返す
* 4桁の中に同じ数値は含ませない
*
* @return bet
*/
private static String ownerBet() {
// 選択対象の数値をlist型で用意しておく
List<String> slot = new ArrayList<String>();
slot.addAll(Arrays.asList("0","1","2","3","4","5","6","7","8","9"));
// ランダムで抜き出すためにlistの大きさより一つ小さい値をランダムの最大値とする
int slot_size = slot.size() - 1;
// 文字列の大きさの分だけ,listからランダムに抜き出す
// 非復元抽出とするため,remove で抜き出す.
// 抜き出すためのランダムの最大値は繰り返すごとに1つずつ小さくなる.
String bet = "";
for(int i = 0; i < BET_SIZE; i++) {
bet += slot.remove((int)(Math.random()*(slot_size - i)));
}
return bet;
}
}