tictactoe——前世今生

类的协作 职责 以及 可修改性

simple tictactoe

完成的是就是根据输入打印每次的棋盘,并且进行判断输赢

Board类

成员变量是一个二维棋盘(把行列设为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;
    }
}

Game类

职责:进行游戏的进行,控制游戏的开始和终止。


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()

Tictactoe

在这里插入图片描述

这是整体包的结构
六个主要类
两个枚举类
FIVE是继承上面类的,因为属于他的一种(其实那个类也可以实现为接口)

根据题意建立接口GameWinStrategy,里面的方法分别两种策略进行实现
并且HV与HVD为组合关系,因为就多了一个斜方判断,但仍然不能说是继承关系(仅仅为了代码复用)

Game 类
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;
    }
}
Board类
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的实现
主要传递的参数也很清晰: 游戏策略(体现了多态,动态时链接),下一步位置,当前步数。
各自类也有各自类的职责,清晰美丽

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,我可以为您提供一份简单的JavaFX代码示例,用于实现TICTACTOE三子棋游戏。以下是示例代码: ```java import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.layout.GridPane; import javafx.stage.Stage; public class TicTacToe extends Application { private boolean playerXTurn = true; private Button[][] buttons = new Button[3][3]; private Label label = new Label("X's turn"); @Override public void start(Stage primaryStage) { GridPane gridPane = new GridPane(); gridPane.setHgap(10); gridPane.setVgap(10); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Button button = new Button(); button.setPrefSize(100, 100); button.setOnAction(event -> { if (button.getText().isEmpty()) { if (playerXTurn) { button.setText("X"); label.setText("O's turn"); } else { button.setText("O"); label.setText("X's turn"); } playerXTurn = !playerXTurn; checkWinner(); } }); buttons[i][j] = button; gridPane.add(button, i, j); } } Scene scene = new Scene(new javafx.scene.layout.VBox(gridPane, label), 320, 320); primaryStage.setScene(scene); primaryStage.show(); } private void checkWinner() { for (int i = 0; i < 3; i++) { if (!buttons[i][0].getText().isEmpty() && buttons[i][0].getText().equals(buttons[i][1].getText()) && buttons[i][0].getText().equals(buttons[i][2].getText())) { showWinner(buttons[i][0].getText()); return; } } for (int i = 0; i < 3; i++) { if (!buttons[0][i].getText().isEmpty() && buttons[0][i].getText().equals(buttons[1][i].getText()) && buttons[0][i].getText().equals(buttons[2][i].getText())) { showWinner(buttons[0][i].getText()); return; } } if (!buttons[0][0].getText().isEmpty() && buttons[0][0].getText().equals(buttons[1][1].getText()) && buttons[0][0].getText().equals(buttons[2][2].getText())) { showWinner(buttons[0][0].getText()); return; } if (!buttons[0][2].getText().isEmpty() && buttons[0][2].getText().equals(buttons[1][1].getText()) && buttons[0][2].getText().equals(buttons[2][0].getText())) { showWinner(buttons[0][2].getText()); return; } boolean isDraw = true; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (buttons[i][j].getText().isEmpty()) { isDraw = false; break; } } if (!isDraw) { break; } } if (isDraw) { showWinner("draw"); } } private void showWinner(String winner) { if (winner.equals("draw")) { label.setText("It's a draw!"); } else { label.setText(winner + " wins!"); } for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { buttons[i][j].setDisable(true); } } } public static void main(String[] args) { launch(args); } } ``` 在这份代码中,我们使用了JavaFX的GridPane布局,创建了一个3*3的按钮矩阵。每次点击按钮,就会在对应的位置上放置一个“X”或“O”,并检查是否有胜利者。当游戏结束时,游戏将不再响应任何点击操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值