TDD实战(四)“井字游戏” 需求三

虫师 创建于 12 个月 之前

最后更新时间 2018-09-25

需求3


现在考虑这个游戏的获胜规则,这部分工作会比较麻烦。我们必须检查所可能获胜的情况,只要满足其中一个,就宣布相应玩家获胜。

最先在水平、锤直或对角线上将自己的3个标记连起来的玩家获胜。

测试用例1


首先定义play() 的默认返回值:


@Test
public void whenPlayThenNoWinner(){
    String actual = ticTacToe.play(1,1);
    assertEquals("No winner", actual);
}

如果不满足获胜条件,则无人获胜。

实现代码1

这个用例很容易满足,修改 play() 方法如下:


public String play(int x, int y){
    checkAxis(x);
    checkAxis(y);
    setBox(x, y);
    lastPlayer = nextPlayer();
    return "No winner";
}

** 执行 测试用例1 检查它是否运行通过。

测试用例2


处理各种获胜条件。

@Test
public void whenPlayAndWholeHorizontalLineThenWinner(){
    ticTacToe.play(1,1);  //X
    ticTacToe.play(1,2);  //O
    ticTacToe.play(2,1);  //X
    ticTacToe.play(2,2);  //O
    String actual = ticTacToe.play(3, 1); //X
    assertEquals("X is the winner", actual);
}

X 玩家最新占满一条水平线,所以 X 玩家获胜。

实现代码2

为了让这个测试通过,需要检查是否有水平线全被当前玩家的棋子占据。现在需要记录哪些棋盘格是空的,还需要记录各个棋盘格被哪个玩家占据。


public String play(int x, int y){
    checkAxis(x);
    checkAxis(y);
    lastPlayer = nextPlayer();
    setBox(x, y, lastPlayer);
    for(int index = 0; index < 3; index++){
        if(board[0][index] == lastPlayer &&
            board[1][index] == lastPlayer &&
            board[2][index] == lastPlayer){
            return lastPlayer + " is the winner";
        }
    }
    return "No winner";
}

private void setBox(int x, int y, char lastPlayer){
    if(board[x-1][y-1] != '\0'){
        throw new RuntimeException("Box is occupied");
    }else {
        board[x-1][y-1] = lastPlayer;
    }
}

** 执行 测试用例2 检查它是否运行通过。

重构

前面代码虽然可以让测试通过,但并非没有改进的空间,所以现在要对上面的代码进行重构。

private static final int SIZE = 3;

public String play(int x, int y){
    checkAxis(x);
    checkAxis(y);
    lastPlayer = nextPlayer();
    setBox(x, y, lastPlayer);
    if(isWin()){
        return lastPlayer + " is the winner";
    }
    return "No winner";
}

private boolean isWin(){
    for(int i = 0; i < SIZE; i++){
        if(board[0][i] == lastPlayer &&
                board[1][i] == lastPlayer &&
                board[2][i] == lastPlayer){
            return true;
        }
    }
    return false;
}

重构之后代码结构看起来更好了。play() 方法保持了简洁。

** 执行 所有测试用例,保证此次重构没有对功能造成影响。

需求3 有些复杂,先休息一下!!

我要留言

暂无评论