hrstt
7/4/2012 - 12:57 PM

mastermindゲームの課題回答用

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;
	}
	
}