blog.waterlow.work

Ruby, Rails, js, etc...

【Java】【OldMind】ババ抜きを作りました

今回もゲームです。
ババ抜きを作りました。
以前トランプを切って一枚引くという流れを再現したので、それを流用しました。

ゲームについて

ババ抜きをリアルでやると心理戦の要素がかなり強く、それ以外は運のみと考えられます。
(そのため今回はゲストプレイヤーは作らずコンピュータのみです。(手抜き笑))
しかも1枚引くごとに状況が変化していくので、初めの手札だけで何ターンで上がれるかを初めの手札から求めるのはそこそこ難しいです。
プレイヤー数をかえてどんな振る舞いをするかは今後の課題です。

クラス設計について

クラス図はさぼりました…。
「手札を見てペアがあったら捨てる」という操作をプレイヤーに持たせてしまったせいでゲーム本体のクラス(OldMindクラス)とプレイヤーのクラス(OldMindPlayerクラス)のやりとりが複雑になってしまいました。以下の記事にはオブジェクト≠クラス設計らしいのですが今後の勉強方針に関しては迷いどころです。

その他勉強したところについて

・forループ内部でループしているArrayList自身を書き換えたいときは拡張for文では無理で明示的にイテレータを書いてwhileで回すor普通のfor文で書くなど工夫が必要。
・リングバッファでカードを配ったり引く順番を回したり。
・メソッドの命名規約(hasCard())

以下ソースです。

OldMindクラス
import java.util.ArrayList;
import java.util.Iterator;


public class OldMind {

	/**
	 * プレイヤーの人数
	 */
	private final int NUM_OF_PLAYERS = 2;

	/**
	 * NEXT_PLAYER_WHEN_TAKE = 3の時は3人隣の人からカードを取る
	 */
	private final int NEXT_PLAYER_WHEN_TAKE = 1;

	/**
	 * プレイヤーを入れておく配列
	 */
	private ArrayList<OldMindPlayer> players = new ArrayList<OldMindPlayer>();

	{
		for(int i = 0; i < NUM_OF_PLAYERS; i++){
			players.add(new OldMindPlayer());
		}
	}

	void startGame(){
		System.out.println("gameStart");
		// トランプ1セットを作る。
		AllCard cards = new AllCard();
		// ジョーカーを作って追加する。
		Card joker = new Card(99, null);
		cards.add(joker);
		// カードを切る
		cards.suffle();
		// このステップがいまいち
		ArrayList<Card> allCard = cards.getAllCard();

		// カードを配る
		int cardCounter = 0;
		for (Card c : allCard){
			players.get(cardCounter % NUM_OF_PLAYERS).takeCard(c);
			cardCounter++;
		}

		// ペアのカードを捨てる。
		// もし初めにカードを持っていないプレイヤーはゲームから除外する。
		Iterator<OldMindPlayer> itr = players.iterator();
		while(itr.hasNext()){
			OldMindPlayer player = (OldMindPlayer) itr.next();
			player.updateCounterAndFlug();
			if(player.hasCard()){
				// カードがないプレイヤーはプレイヤーリストから外す。
				itr.remove();
			}
		}

		// 最後の一人になるまでカードを引き合う
		int turnCounter = 0;
		while(players.size() != 1){
			OldMindPlayer takeCard = players.get(turnCounter % players.size());
			OldMindPlayer taken = players.get((turnCounter + NEXT_PLAYER_WHEN_TAKE) % players.size());
			takeCard.choiceRandomFrom(taken);
			turnCounter++;
			if(takeCard.hasCard()){
				players.remove(takeCard);
			}
			if(taken.hasCard()){
				players.remove(taken);
			}
		}
		System.out.println("gameEnd");
		System.out.println("経過したターンは" + turnCounter + "です。");
	}

	public static void main(String[] args) {
		for(int i = 0; i < 10; i++){
			long start = System.currentTimeMillis();
			OldMind game = new OldMind();
			game.startGame();
			long stop = System.currentTimeMillis();
			System.out.println("実行にかかった時間は " + (stop - start) + " ミリ秒です。");
		}
	}
}
OldMindPlayerクラス
import java.util.ArrayList;
import java.util.Random;

public class OldMindPlayer {
	private ArrayList<Card> myCard = new ArrayList<Card>();
	int[] cardCounter = new int[AllCard.MAX_RANK];
	boolean jokerFlug = false;

	private final int THROW_COUNTER = 2;

	public void updateCounterAndFlug(){
		cardCounter = new int[AllCard.MAX_RANK];
		for(Card c : myCard){
			if(c.getNumber() > AllCard.MAX_RANK){
				continue;
			}
			cardCounter[c.getNumber() - 1]++;
		}
		for(int i = 0; i < cardCounter.length; i++){
			if(cardCounter[i] / THROW_COUNTER == 0){
				continue;
			}
			int numOfPairs = cardCounter[i] / THROW_COUNTER;
			for(int j = 0; j < numOfPairs * THROW_COUNTER; j++){
				throwCard(i + 1);
			}
			cardCounter[i] = cardCounter[i] % THROW_COUNTER;
		}
	}

	public void takeCard(Card c){
		myCard.add(c);
	}

	/**
	 * @param num
	 */
	private void throwCard(int num){
		Card tmp = null;
		for(Card c : myCard){
			if(c.getNumber() == num){
				tmp = c;
			}
		}
		if(tmp != null){
			myCard.remove(tmp);
		}
	}

	/**
	 * @return 自分の持ってるカードの枚数
	 */
	private int getNumOfMyCards(){
		return myCard.size();
	}

	/**
	 * @return プレイヤーがカードを持っているかどうか
	 */
	public boolean hasCard() {
		return myCard.isEmpty();
	}

	/**
	 * @param player
	 * @return 他のプレイヤーの持ってるカードの枚数
	 */
	int getNumOfPlayerCards(OldMindPlayer player){
		return player.getNumOfMyCards();
	}

	Card giveCard(int cardNumber){
		return myCard.remove(cardNumber);
	}

	void getCardFrom(OldMindPlayer player, int cardNumber){
		myCard.add(player.giveCard(cardNumber));
	}

	void choiceRandomFrom(OldMindPlayer player){
		Random random = new Random();
		int choosing = random.nextInt(player.getNumOfMyCards());
		getCardFrom(player, choosing);
		updateCounterAndFlug();
	}
}