JavaStrategy模式

本文最后更新于:1 年前

整体的替换算法

1 - 表示猜拳游戏中的的”手势”类

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){ // 如果this战胜了h则返回true
        return fight(h) == 1;
    }

    public boolean isWeakerThan(Hand h){ // 如果this战胜了h则返回false
        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];
    }
}

2 - 表示猜拳游戏中策略的类

public interface Strategy {
    public abstract Hand nextHand();
    public abstract void study(boolean win);
}

3 - 表示”如果这局猜拳获胜,那么下一局也出一样的手势”这一策略的类

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

4 - 表示”根据上一局的手势从概率上计算出下一局的手势,从之前的猜拳结果计算下一局出各种拳的概率”这一策略类

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

    private int getSum(int hv){
        int sum = 0;
        for (int i = 0; i < 3; i++) {
            sum += history[hv][i];
        }
        return sum;
    }

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

5 - 表示进行猜拳游戏的选手的类

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 " + "]";
    }
}

6 - 测试程序行为的类

// 需要提前设置好args的参数
public class Main {
    public static void main(String[] args) {
        if (args.length != 2){
            System.out.println("Usage: java Main randomSeed1 randomSeed2");
            System.out.println("Example: java Main 314 15");
            System.exit(0);
        }

        int seed1 = Integer.parseInt(args[0]);
        int seed2 = Integer.parseInt(args[1]);

        Player player1 = new Player("Taro", new WinningStrategy(seed1));
        Player player2 = new Player("Hana", new ProbStrategy(seed2));

        for (int i = 0; i < 15; i++) {
            Hand nextHand1 = player1.nextHand();
            Hand nextHand2 = player2.nextHand();
            if (nextHand1.isStrongerThan(nextHand2)){
                System.out.println("Winner: " + player1);
                player1.win();
                player2.lose();
            }else if (nextHand2.isStrongerThan(nextHand1)){
                System.out.println("Winner: " + player2);
                player2.win();
                player1.lose();
            }else {
                System.out.println("Even...");
                player1.even();
                player2.even();
            }
        }

        System.out.println("Total result: ");
        System.out.println(player1.toString());
        System.out.println(player2.toString());
    }
}

7 - 输出示例

Winner: [Taro:0 games, 0 win, 0 lose ]
Winner: [Taro:1 games, 1 win, 0 lose ]
Even...
Winner: [Hana:3 games, 0 win, 2 lose ]
Winner: [Hana:4 games, 1 win, 2 lose ]
Winner: [Hana:5 games, 2 win, 2 lose ]
Winner: [Hana:6 games, 3 win, 2 lose ]
Winner: [Taro:7 games, 2 win, 4 lose ]
Even...
Winner: [Hana:9 games, 4 win, 3 lose ]
Winner: [Taro:10 games, 3 win, 5 lose ]
Winner: [Taro:11 games, 4 win, 5 lose ]
Winner: [Hana:12 games, 5 win, 5 lose ]
Winner: [Hana:13 games, 6 win, 5 lose ]
Winner: [Taro:14 games, 5 win, 7 lose ]
Total result: 
[Taro:15 games, 6 win, 7 lose ]
[Hana:15 games, 7 win, 6 lose ]

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!