完成的是就是根据输入打印每次的棋盘,并且进行判断输赢
成员变量是一个二维棋盘(把行列设为final同时也应用于下面,可以增加可修改性,防止后续全部改变)
职责: 构建一个棋盘,并且记录每一次的情况,判定当前游戏的结果
这里比较巧妙的代码实现点是:虽然是X O 但在进行中我们可以让数字去代表这两个字符,并且判定结果
Gmae: turn=turn✖-1;
可谓是节省很多麻烦的关键因素
class Board {
final static int row = 3;
final static int col = 3;
private int[][] board = new int[row][col];
public void setBoard(int turn, String pos) {
int x = pos.charAt(1) - '1';
int y = pos.charAt(0) - 'A';
if (this.board[x][y] != 0)
System.out.println("Error. This place has been placed before");
else
board[x][y] = turn;
}
public void print() {
System.out.print(this.toString());
}
public String toString() {
String lineSeparator = System.getProperty("line.separator");
String ret = " A B C" + lineSeparator;
for (int i = 0; i < row; i++) {
ret += i + 1;
for (int j = 0; j < col; j++) {
if (board[i][j] == 1)
ret += " X";
else if (board[i][j] == -1)
ret += " O";
else
ret += " _";
}
ret += lineSeparator;
}
return ret;
}
/**
* 根据题目要求进行判断
* @return
*/
public Result getStatement() {
for (int i = 0; i < row; i++) {
int temp = 0;
for (int j = 0; j < col; j++)
temp += board[i][j];
if (temp == 3) return Result.X_WIN;
else if (temp == -3) return Result.O_WIN;
}
for (int i = 0; i < row; i++) {
int temp = 0;
for (int j = 0; j < col; j++)
temp += board[j][i];
if (temp == 3) return Result.X_WIN;
else if (temp == -3) return Result.O_WIN;
}
//检查对角线
if (row == col) {
int sum = 0, sum_two = 0;
for (int i = 0; i < row; i++) {
sum += board[i][i];
sum_two += board[i][row - i-1];
}
if(sum==3||sum_two==3) return Result.X_WIN;
else if(sum==-3||sum_two==-3) return Result.O_WIN;
} else {
System.out.println("行列不相等 嘻嘻");
}
return Result.DRAW;
}
}
职责:进行游戏的进行,控制游戏的开始和终止。
public class Game {
//棋盘与游戏是组合关系 有生命周期的联系
private Board checkBoard = new Board();
private int turn = 1; //步数 来以此在棋盘判断是放入哪个
//游戏主方法playGame
//输入为对弈双方轮番落子的位置,以英文逗号为间隔,X先走
public Result playGame(String s) {
String[] position = s.split(",");
for (String pos : position) {
checkBoard.setBoard(turn, pos);
checkBoard.print();
if (checkBoard.getStatement() != Result.DRAW)
break;
turn*=-1;
}
return checkBoard.getStatement();
}
}
Board与game的分离,各自实现各自的功能,并且很好的进行了协作
注意,有的同学实现了Player类,但会发现,这个类总是不断去调用board的内容,没有很好的实现单一原则,所以为何不都在board中实现呢?
这两个类之间是什么关系?
这两个类是 组合 关系,因为两者之间交互性较强,并且又生命周期的关系,游戏开始,棋盘肯定要建立,成员变量就要new Board()
这是整体包的结构
六个主要类
两个枚举类
FIVE是继承上面类的,因为属于他的一种(其实那个类也可以实现为接口)
根据题意建立接口GameWinStrategy,里面的方法分别两种策略进行实现
并且HV与HVD为组合关系,因为就多了一个斜方判断,但仍然不能说是继承关系(仅仅为了代码复用)
package cn.edu.nju.TicTacToe;
public class Game {
private int size;
/**
* Game的接口方法,我们会通过该方法进行测试
* @param gameMode 游戏模式,有四种可能,00,01,10,11
* @param moveStr 落子序列
* @param size 棋盘大小,size最小为3, 最大为9
* @return 游戏结果
*
* 根据需要改写方法,参数,返回结果类型不可修改
*/
public Result playGame(String gameMode, String moveStr, int size){
Board board = new Board(size,gameMode);
String[] moves = moveStr.split(",");
Result res = Result.GAMING;
for(int counter=0;counter<moves.length;counter++)
{
res=board.nextMove(moves,counter);
board.print();
// 游戏结束
if( !res.equals(Result.GAMING) )
break;
}
return res;
}
}
package cn.edu.nju.TicTacToe;
public class Board {
/**
* 成员变量的初始化代码请修改,请灵活选择初始化方式
* 必要时可添加成员变量
*/
protected char[][] cells;
protected GameChessStrategy chessStrategy; //五子方式
protected GameWinStrategy winStrategy; //输赢策略 横斜
protected Player player = Player.X;
/**
* 请修改构造方法,并添加合适的构造方法
*/
public Board(int boardSize, String gameMole){
cells = new char[boardSize][boardSize];
for(int i=0; i<boardSize; i++){
for(int j=0; j<boardSize; j++){
cells[i][j] = '_';
}
}
//00 01 10 11 不同方式不同策略 多态
char chess=gameMole.charAt(0);
chessStrategy= (chess=='0')? (new GameChessStrategy()):(new GameChessStrategyFIVE());
char win=gameMole.charAt(1);
winStrategy= (win=='0') ? (new GameWinStrategyStrategy_HVD()):(new GameWinStrategyStrategy_HV());
}
/**
* @param moves 下棋的位置
* @return 落棋之后的结果
*/
public Result nextMove(String []moves,int counter) {
chessStrategy.putChess(cells, nextPlay(), moves,counter);
return winStrategy.check(cells,moves,counter);
}
/**
* @return 下一个落棋的玩家
*/
protected Player nextPlay(){
Player res = player;
player = player == Player.X ? Player.O : Player.X; //进行player更替
return res;
}
/**
* 棋盘的输出方法,根据需要进行修改
*/
public void print(){
int length=cells.length;
System.out.print(" ");
for(int i=0;i<length;i++)
{
char temp=(char)('A'+i);
System.out.print(" "+temp);
}
System.out.println();
for(int i=0;i<length;i++)
{
System.out.print(i+1);
for(int j=0;j<length;j++)
System.out.print(" "+cells[i][j]);
System.out.println();
}
}
}
体现了接口,抽象方法的思想,很nice的实现
主要传递的参数也很清晰: 游戏策略(体现了多态,动态时链接),下一步位置,当前步数。
各自类也有各自类的职责,清晰美丽