Strategyパターン

委譲

% find . -name "*.java" -print0 |xargs -0 cat                                []
public class Hand {
	public static final int HANDVALUE_GUU = 0;
	public static final int HANDVALUE_CHO = 1;
	public static final int HANDVALUE_PAA = 2;
	/* クラス内だとプライベートのコンストラクタ呼べるのね。シングルトンと同じか */
	public static final Hand[] hand = { new Hand(HANDVALUE_GUU),
			new Hand(HANDVALUE_CHO), new Hand(HANDVALUE_PAA), };
	private static final String[] name = { "グー", "チョキ", "パー" };
	private int handValue;

	private Hand(int handValue) {
		this.handValue = handValue;
	}

	public static Hand getHand(int handValue) {
		return hand[handValue];
	}

	public boolean isStrongerThan(Hand h) {
		return fight(h) == 1;
	}

	public boolean isWeakerThan(Hand h) {
		return fight(h) == -1;
	}

	private int fight(Hand h) {
		if (this == h) {
			return 0;
		} else if ((this.handValue + 1) % 3 == h.handValue) {
			return 1;
		} else {
			return -1;
		}
	}

	@Override
	public String toString() {
		return name[handValue];
	}
}
public class Main {

	public static void main(String[] args) {
		int seed1 = 100;
		int seed2 = 200;
		Player p1 = new Player("p1", new WinningStrategy(seed1));
		Player p2 = new Player("p2", new ProbStrategy(seed2));
		for (int i = 0; i < 10000; i++) {
			Hand nextHand1 = p1.nextHand();
			Hand nextHand2 = p2.nextHand();
			if (nextHand1.isStrongerThan(nextHand2)) {
				System.out.println("Winner:" + p1);
				p1.win();
				p2.lose();
			} else if (nextHand2.isStrongerThan(nextHand1)) {
				System.out.println("Winner:" + p2);
				p2.win();
				p1.lose();
			} else {
				System.out.println("Even..");
				p1.even();
				p2.even();
			}
		}
		System.out.println(p1.toString());
		System.out.println(p2.toString());
	}

}
public class Player {
	private String name;
	private Strategy strategy;
	private int wincount;
	private int losecount;
	private int gamecount;

	public Player(String name, Strategy strategy) {
		this.name = name;
		this.strategy = strategy;
	}

	public Hand nextHand() {
		return strategy.nextHand();
	}

	public void win() {
		strategy.study(true);
		wincount++;
		gamecount++;
	}

	public void lose() {
		strategy.study(false);
		losecount++;
		gamecount++;
	}

	public void even() {
		gamecount++;
	}

	@Override
	public String toString() {
		return "[" + name + ":" + gamecount + " games, " + wincount + " win, "
				+ losecount + " lose]";
	}
}
import java.util.Random;

public class ProbStrategy implements Strategy {
	private Random random;
	private int prevHandValue = 0;
	private int currentHandValue = 0;
	private int[][] history = { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } };

	public ProbStrategy(int seed) {
		this.random = new Random(seed);
	}

	@Override
	public Hand nextHand() {
		int bet = random.nextInt(getSum(currentHandValue));
		int handValue = 0;
		if (bet < history[currentHandValue][0]) {
			handValue = 0;
		} else if (bet < history[currentHandValue][0]
				+ history[currentHandValue][1]) {
			handValue = 1;
		} else {
			handValue = 2;
		}
		prevHandValue = currentHandValue;
		currentHandValue = handValue;
		return Hand.getHand(handValue);
	}

	@Override
	public void study(boolean win) {
		if (win) {
			history[prevHandValue][currentHandValue]++;
		} else {
			history[prevHandValue][(currentHandValue + 1) % 3]++;
			history[prevHandValue][(currentHandValue + 2) % 3]++;
		}
	}

	private int getSum(int hv) {
		int sum = 0;
		for (int i = 0; i < 3; i++) {
			sum += history[hv][i];
		}
		return sum;
	}
}
public interface Strategy {
	public abstract Hand nextHand();

	public abstract void study(boolean win);
}
import java.util.Random;

public class WinningStrategy implements Strategy {
	private Random random;
	private boolean won = false;
	private Hand prevHand;

	public WinningStrategy(int seed) {
		random = new Random(seed);
	}

	@Override
	public Hand nextHand() {
		if (!won) {
			prevHand = Hand.getHand(random.nextInt(3));
		}
		return prevHand;
	}

	@Override
	public void study(boolean win) {
		won = win;
	}

}
Winner:[p1:9994 games, 3117 win, 3492 lose]
Even..
Even..
Winner:[p1:9997 games, 3118 win, 3492 lose]
Winner:[p2:9998 games, 3492 win, 3119 lose]
Winner:[p2:9999 games, 3493 win, 3119 lose]
[p1:10000 games, 3119 win, 3494 lose]
[p2:10000 games, 3494 win, 3119 lose]