【问题标题】:How to enable turn taking within game of Gomoku javafx [closed]如何在 Gomoku javafx 游戏中启用轮流 [关闭]
【发布时间】:2019-09-04 01:28:22
【问题描述】:

在我的程序中启用轮换时遇到困难。

棋盘上的一个图块被点击,这些坐标被传递给 playMakeMove(),它在棋盘矩阵中进行移动并设置文本以直观地表示移动。

虽然当涉及 2 个玩家(玩家,RandomAI)时,在使用循环交替回合后,该方法不起作用。 RandomAI 只是连续移动所有动作,玩家只在完全相同的位置移动一次(不等待鼠标点击)。

我认为这个问题可以通过等待一个瓷砖被点击(运行方法 playerMakeMove)然后让 RandomAI 轮流来解决。不知道如何实现这一点。

下面是两个类 BoardGUI 和 Game,还有另一个类(不包括在内)称为 Board。

public class BoardGUI extends Application {

    private final int BOARD_SIZE = 15;

    private Tile[][] tileBoard = new Tile[BOARD_SIZE][BOARD_SIZE];

    private Pane root = new Pane();

    private Parent createContent(Game game) {
        root.setPrefSize(755, 755);

        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                Tile tile = new Tile(i, j);
                tile.setTranslateX(j * 50);
                tile.setTranslateY(i * 50);

                tile.setOnMousePressed(e -> {
                    System.out.println("tile clicked");

                    // sets coordinates of tileClicked in game - to be used in making a player move
                    game.getTile().setRow(tile.getTileRow());
                    game.getTile().setColumn(tile.getTileCol());
                });

                root.getChildren().add(tile);

                tileBoard[i][j] = tile;
            }
        }
        return root;
    }

    @Override
    public void start(Stage primaryStage) {
        Game game = new Game();
        Scene scene = new Scene (game.GUI.createContent(game));
        primaryStage.setScene(scene);
        primaryStage.setTitle("Gomoku");
        primaryStage.show();


        for (int turns = 0; turns < (game.getBoardSize()*game.getBoardSize()); turns++) {
            if(game.getGameOver()) break;

            if(!game.isPlayerTurn()) {
                //AI make move
                game.makeMoveAIRandom(game.getGameBoard());
                game.setPlayerTurnTrue();
            }
            else {
                // player make move
                game.playerMakeMove(game);
            }
        }
        System.out.println("game over");
    }

     class Tile extends StackPane {

        Text text = new Text();
        int row, column;

        Tile(int x, int y) {
            this.row = x;
            this.column = y;

            Rectangle border = new Rectangle(50, 50);
            border.setFill(Color.BURLYWOOD);
            border.setStroke(Color.BLACK);
            text.setFont(Font.font(40));
            setAlignment(Pos.CENTER);
            getChildren().addAll(border, text);
        }

        void makeMove(Board board, int player, int row, int col) {
            System.out.println(row + " " + col);

            if (board.isMoveAvailable(row, col)) {
                drawTile(player);
                makeMoveMatrix(board, player, row, col);
            }
            System.out.println("makeMove executed");
        }

        void drawTile(int player) {
            System.out.println("setTextTile executed");
            text.setText("O");
            if (player == 1) text.setFill(Color.BLACK);
            else text.setFill(Color.WHITE);
        }

        void makeMoveMatrix(Board board, int player, int row, int col) {
            board.make_move(player, row, col);
        }

        int getTileRow() { return row; }

        void setRow(int row) { this.row = row; }

        void setColumn(int column) { this.column = column; }

        int getTileCol() { return column; }

    }

    Tile[][] getTileBoard() { return tileBoard; }
}


public class Game extends BoardGUI {

    private final int PLAYER_ONE = 1;
    private final int PLAYER_TWO = 2;
    BoardGUI GUI;
    private Board gameBoard;
    private int boardSize = 15;
    private int winLength = 5;
    private boolean turn = true;
    private boolean isGameOver = false;
    private Tile tileClicked = new Tile(0, 0);

    Game() {
        this.gameBoard = new Board(boardSize, winLength);
        this.GUI = new BoardGUI();
    }

    void makeMoveAIRandom(Board gameBoard) {

        Random random = new Random();
        int index = random.nextInt(gameBoard.availableMoves.size());
        int[] move = gameBoard.availableMoves.get(index);
        int row = move[0];
        int col = move[1];

        GUI.getTileBoard()[row][col].makeMove(gameBoard, PLAYER_TWO, move[0], move[1]);

        setGameOver(getGameBoard().check_win_all(PLAYER_TWO, row, col));

        gameBoard.availableMoves.remove(index);

        setPlayerTurnTrue();
    }

    void playerMakeMove(Game game) {

        int row = game.getTile().getTileRow();
        int col = game.getTile().getTileCol();

        game.GUI.getTileBoard()[row][col].makeMove(game.getGameBoard(), PLAYER_ONE, row, col);

        setGameOver(getGameBoard().check_win_all(PLAYER_TWO, row, col));

        System.out.println("player taken turn");
        setPlayerTurnFalse();
    }


    Board getGameBoard() { return gameBoard; }

    int getBoardSize () { return boardSize; }

    boolean isPlayerTurn() { return turn; }

    private void setPlayerTurnFalse() { turn = false; }

    void setPlayerTurnTrue() { turn = true; }

    boolean getGameOver () { return isGameOver; }

    private void setGameOver (boolean result) { isGameOver = result; }

    Tile getTile () { return tileClicked; }
}

【问题讨论】:

  • 您尝试在start 中实现游戏逻辑。没有什么可以阻止该逻辑在轮到任何玩家之前执行。您需要使用事件处理程序,以便在事件发生时得到通知,从而根据需要更改游戏状态。
  • "寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确的问题陈述对其他读者没有用处。请参阅:minimal reproducible example"。请包括缺少的代码并删除不需要的代码。

标签: java javafx gomoku


【解决方案1】:

您有 2 个主要选项来实现游戏循环。我只提供伪代码,而不是用 Java 编写它们的等价物,您可以询问是否在转换为 Java 时遇到问题。

第一个选项是触发用户采取行动的所有活动。因此,例如,“事件”可能是拖放、选项点击等,具体取决于游戏:

on user event:
    change state according to user's choice
    go to next player
    while next player is AI:
        perform automated move
        go to next player

第二个更通用的选项是设置一个定期触发的计时器,以检查是否可以发生 AI 动作。

on user event:
    change state according to user's choice
    go to next player

on timer tick:
    if current player is AI
       perform automated move
       go to next player

根据游戏机制,每一个都有自己的位置

【讨论】:

    【解决方案2】:

    下面是一个完整的可运行代码,实现了轮换。
    它还提出了一些改进和设计更改。请注意 cmets。
    游戏结束逻辑未实现。
    为方便起见,可以将整个代码复制粘贴到一个文件中 (BoardGUI.java) 并运行:

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import javafx.application.Application;
    import javafx.beans.property.BooleanProperty;
    import javafx.beans.property.SimpleBooleanProperty;
    import javafx.geometry.Pos;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.scene.layout.Pane;
    import javafx.scene.layout.StackPane;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.Rectangle;
    import javafx.scene.text.Font;
    import javafx.scene.text.Text;
    import javafx.stage.Stage;
    
    public class BoardGUI extends Application {
    
        private final static int BOARD_SIZE = 15;
    
        private final Tile[][] tileBoard = new Tile[BOARD_SIZE][BOARD_SIZE];
    
        private final Pane root = new Pane();
    
        private Parent createContent(Game game) {
            root.setPrefSize(755, 755);
    
            for (int i = 0; i < BOARD_SIZE; i++) {
                for (int j = 0; j < BOARD_SIZE; j++) {
                    Tile tile = new Tile(i, j);
                    tile.setTranslateX(j * 50);
                    tile.setTranslateY(i * 50);
    
                    final int row = i, col = j;
                    tile.setOnMousePressed(e -> {
                        //the click causes a move
                        //game.playerMakeMove(game, row, col); //no need to  pass a reference of Game to Game
                        game.playerMakeMove(row, col); //no need to  pass a reference of Game to Game
                    });
    
                    root.getChildren().add(tile);
                    tileBoard[i][j] = tile;
                }
            }
            return root;
        }
    
        @Override
        public void start(Stage primaryStage) {
    
            //there is no need to get a new instance of BoardGUI from Game.
            //Game game = new Game();
            //Scene scene = new Scene (game.gui.createContent(game));
    
            //instead:
            Game game = new Game(this);
            Scene scene = new Scene (createContent(game));
            primaryStage.setScene(scene);
            primaryStage.setTitle("Gomoku");
            primaryStage.show();
    
            //the player should make a move  (click) and it should trigger the next move
        }
    
        //method moved from Tile
        void makeMove(Board board, int player, int row, int col) {
    
            if (board.isMoveAvailable(row, col)) {
                tileBoard[row][col].drawTile(player);
                makeMoveMatrix(board, player, row, col);
            }
        }
    
        //method moved from Tile
        void makeMoveMatrix(Board board, int player, int row, int col) {
            board.make_move(player, row, col);
        }
    
    
        Tile[][] getTileBoard() { return tileBoard; }
    
        class Tile extends StackPane {
    
            Text text = new Text();
            int row, column;
    
            Tile(int row, int col) {
                this.row = row; column = col;
    
                Rectangle border = new Rectangle(50, 50);
                border.setFill(Color.BURLYWOOD);
                border.setStroke(Color.BLACK);
                text.setFont(Font.font(40));
                setAlignment(Pos.CENTER);
                getChildren().addAll(border, text);
            }
    
            void drawTile(int player) {
                text.setText("O");
                if (player == Game.PLAYER_ONE) {
                    text.setFill(Color.BLACK);
                } else {
                    text.setFill(Color.WHITE);
                }
            }
    
            int getTileRow() { return row; }
    
            void setRow(int row) { this.row = row; }
    
            void setColumn(int column) { this.column = column; }
    
            int getTileCol() { return column; }
        }
    
    
        public static void main(String[] args) {
            launch(null);
        }
    }
    
    class Game  {// there is no need for Game to extend BoardGUI
    
        public static final int FREE = 0, PLAYER_ONE = 1, PLAYER_TWO = 2;
        private final BoardGUI gui;
        private final Board gameBoard;
        private final int boardSize = 15, winLength = 5;
        private final Random random = new Random(); //no need to create new Randon with every move
        //replace this attribute with property so you could listen to it
        //private boolean turn = true;
        private final BooleanProperty playerTurn = new SimpleBooleanProperty(true);
    
        private boolean isGameOver = false;
    
        Game(BoardGUI gui) { //get a reference to BoardGUI rather than constructing it
            gameBoard = new Board(boardSize, winLength);
            this.gui = gui;
            playerTurn.addListener( (obs,oldValue,newValue) ->{//listen to turn changes
                if(!newValue) {
                    makeMoveAIRandom();
                }
            });
        }
    
        void makeMoveAIRandom() {
    
            if( playerTurn.get() ) return; //run only if not player turn
    
            List<int[]> availableMoves = gameBoard.getAvailableMoves();
            int index = random.nextInt(availableMoves.size());
            int[] move = availableMoves.get(index);
    
            gui.makeMove(gameBoard, PLAYER_TWO, move[0], move[1]);
            setPlayerTurnTrue();
            System.out.println("AI taken turn " + move[0] +"-"+ move[1]);
        }
    
        //void playerMakeMove(Game game, int row, int col) { //no need to path reference to this
        void playerMakeMove(int row, int col) {
            if(! playerTurn.get() ) return; //run only if player turn
    
            gui.makeMove(gameBoard, PLAYER_ONE, row, col);
            setPlayerTurnFalse();
            System.out.println("player taken turn " + row +"-"+col );
        }
    
        Board getGameBoard() { return gameBoard; }
    
        int getBoardSize () { return boardSize; }
    
        boolean isPlayerTurn() { return playerTurn.get(); }
    
        private void setPlayerTurnFalse() { playerTurn.set(false); }
    
        void setPlayerTurnTrue() { playerTurn.set(true); }
    
        boolean getGameOver () { return isGameOver; }
    
        private void setGameOver (boolean result) { isGameOver = result; }
    }
    
    class Board {
    
        private final int[][] board_matrix;
        private final int board_size, win_length;
    
        Board(int board_size, int win_length) {
            board_matrix = new int[board_size][board_size];
            this.board_size = board_size;
            this.win_length = win_length;
    
            for (int i = 0; i < board_size; i++) {
                for (int j = 0; j < board_size; j++) {
                    board_matrix[i][j] = Game.FREE;
                }
            }
        }
    
        boolean isMoveAvailable(int row, int col) {
    
            return board_matrix[row][col] != Game.PLAYER_ONE && board_matrix[row][col] != Game.PLAYER_TWO ;
        }
    
        void make_move(int player, int x_pos, int y_pos) {
            if (player == Game.PLAYER_ONE) {
                board_matrix[x_pos][y_pos] = Game.PLAYER_ONE;
            } else {
                board_matrix[x_pos][y_pos] = Game.PLAYER_TWO;
            }
        }
    
        List<int[]> getAvailableMoves(){
    
            List<int[]> availableMoves = new ArrayList<>();
            for (int row = 0; row < board_size; row++) {
                for (int col = 0; col < board_size; col++) {
                    if (board_matrix[row][col] == Game.FREE){
                        availableMoves.add(new int[]{ row, col});
                    }
                }
            }
    
            return availableMoves;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-10-07
      • 1970-01-01
      • 2023-01-16
      • 2023-03-12
      • 1970-01-01
      • 2021-02-14
      • 1970-01-01
      • 2021-07-22
      • 1970-01-01
      相关资源
      最近更新 更多