1

所以我试图找出一个关于井字游戏的教程。但我想知道我在哪里初始化计算机播放器。

所以我有一个抽象的 AIPlayer 类

public abstract class AIPlayer {
protected int ROWS = 3;  // number of rows
protected int COLS = 3;  // number of columns

protected Cell[][] cells; // the board's ROWS-by-COLS array of Cells
protected Seed mySeed;    // computer's seed
protected Seed oppSeed;   // opponent's seed

/** Constructor with reference to game board */
public AIPlayer(Board board) {
  cells = board.cells;
}

/** Set/change the seed used by computer and opponent */
public void setSeed(Seed seed) {
   this.mySeed = seed;
   oppSeed = (mySeed == Seed.CROSS) ? Seed.NOUGHT : Seed.CROSS;
}

/** Abstract method to get next move. Return int[2] of {row, col} */
abstract int[] move();  // to be implemented by subclasses
}

这是我找出计算机最佳移动的算法

import AIPlayer;
import Board;
import Seed;

import java.util.*;
/** AIPlayer using Minimax algorithm */
public class AIPlayerMinimax extends AIPlayer {

/** Constructor with the given game board */
public AIPlayerMinimax(Board board) {
  super(board);
}


int[] move() {
  int[] result = minimax(2, mySeed); // depth, max turn
  return new int[] {result[1], result[2]};   // row, col
}


private int[] minimax(int depth, Seed player) {
   //minmax code
}

private List<int[]> generateMoves() {
   //generate moves
}


private int evaluate() {

   //Evaluating
 }

private int evaluateLine(int row1, int col1, int row2, int col2, int row3, int col3) {
   // .. 

 }

private int[] winningPatterns = {

       //

};


private boolean hasWon(Seed thePlayer) {
   //

   }
}

这是我的 GameMain,它有图形和所有好东西

public class GameMain extends JPanel {
// Named-constants for the game board
public static final int ROWS = 3;  // ROWS by COLS cells
public static final int COLS = 3;
public static final String TITLE = "Tic Tac Toe";

// Name-constants for the various dimensions used for graphics drawing
public static final int CELL_SIZE = 100; // cell width and height (square)
public static final int CANVAS_WIDTH = CELL_SIZE * COLS;  // the drawing canvas
public static final int CANVAS_HEIGHT = CELL_SIZE * ROWS;
public static final int GRID_WIDTH = 8;  // Grid-line's width
public static final int GRID_WIDHT_HALF = GRID_WIDTH / 2; // Grid-line's half-width
// Symbols (cross/nought) are displayed inside a cell, with padding from border
public static final int CELL_PADDING = CELL_SIZE / 6;
public static final int SYMBOL_SIZE = CELL_SIZE - CELL_PADDING * 2;
public static final int SYMBOL_STROKE_WIDTH = 8; // pen's stroke width

private Board board;            // the game board
private GameState currentState; // the current state of the game
private Seed currentPlayer;     // the current player
private JLabel statusBar;       // for displaying status message

/** Constructor to setup the UI and game components */
public GameMain() {

    // This JPanel fires MouseEvent
    this.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {  // mouse-clicked handler
            int mouseX = e.getX();
            int mouseY = e.getY();
            // Get the row and column clicked
            int rowSelected = mouseY / CELL_SIZE;
            int colSelected = mouseX / CELL_SIZE;

            if (currentState == GameState.PLAYING) {
                if (rowSelected >= 0 && rowSelected < ROWS
                    && colSelected >= 0 && colSelected < COLS
                && board.cells[rowSelected][colSelected].content == Seed.EMPTY) {
                    board.cells[rowSelected][colSelected].content = currentPlayer; // move
                    updateGame(currentPlayer, rowSelected, colSelected); // update currentState
                    // Switch player
                    currentPlayer = (currentPlayer == Seed.CROSS) ? Seed.NOUGHT : Seed.CROSS;
                }
            } else {        // game over
                initGame();  // restart the game
            }
            // Refresh the drawing canvas
            repaint();  // Call-back paintComponent().
        }
    });

    // Setup the status bar (JLabel) to display status message
    statusBar = new JLabel("         ");
    statusBar.setFont(new Font(Font.DIALOG_INPUT, Font.BOLD, 14));
    statusBar.setBorder(BorderFactory.createEmptyBorder(2, 5, 4, 5));
    statusBar.setOpaque(true);
    statusBar.setBackground(Color.LIGHT_GRAY);

    setLayout(new BorderLayout());
    add(statusBar, BorderLayout.PAGE_END); // same as SOUTH
    setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT + 30));
    // account for statusBar in height

    board = new Board();   // allocate the game-board
    initGame();  // Initialize the game variables
}

/** Initialize the game-board contents and the current-state */
public void initGame() {
    for (int row = 0; row < ROWS; ++row) {
        for (int col = 0; col < COLS; ++col) {
            board.cells[row][col].content = Seed.EMPTY; // all cells empty
        }
    }
    currentState = GameState.PLAYING;  // ready to play
    currentPlayer = Seed.CROSS;        // cross plays first
}

/** Update the currentState after the player with "theSeed" has placed on (row, col) */
public void updateGame(Seed theSeed, int row, int col) {
    if (board.hasWon(theSeed, row, col)) {  // check for win
        currentState = (theSeed == Seed.CROSS) ? GameState.CROSS_WON : GameState.NOUGHT_WON;
    } else if (board.isDraw()) {  // check for draw
        currentState = GameState.DRAW;
    }
    // Otherwise, no change to current state (PLAYING).
}

/** Custom painting codes on this JPanel */
@Override
public void paintComponent(Graphics g) {  // invoke via repaint()
    super.paintComponent(g);    // fill background
    setBackground(Color.WHITE); // set its background color

    board.paint(g);  // ask the game board to paint itself

    // Print status-bar message
    if (currentState == GameState.PLAYING) {
        statusBar.setForeground(Color.BLACK);
        if (currentPlayer == Seed.CROSS) {
            statusBar.setText("X's Turn");
        } else {
            statusBar.setText("O's Turn");
        }
    } else if (currentState == GameState.DRAW) {
        statusBar.setForeground(Color.RED);
        statusBar.setText("It's a Draw! Click to play again.");
    } else if (currentState == GameState.CROSS_WON) {
        statusBar.setForeground(Color.RED);
        statusBar.setText("'X' Won! Click to play again.");
    } else if (currentState == GameState.NOUGHT_WON) {
        statusBar.setForeground(Color.RED);
        statusBar.setText("'O' Won! Click to play again.");
    }
}

/** The entry "main" method */
public static void main(String[] args) {
    // Run GUI construction codes in Event-Dispatching thread for thread safety
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            JFrame frame = new JFrame(TITLE);
            // Set the content-pane of the JFrame to an instance of main JPanel
            frame.setContentPane(new GameMain());
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setLocationRelativeTo(null); // center the application window
            frame.setVisible(true);            // show it
        }
    });
}
}

所以我的问题是,我如何初始化 AIPlayer 来和我竞争?目前这是一款多人游戏,Human vs Human。

4

1 回答 1

1

好吧,您可能想添加一个属性 go GameMain

private AIPlayer aiPlayer; 

将您的 AIPlayer 实例化为initGame()

aiPlayer = new AIPlayer(board)
aiPlayer.setSeed(Seed.NOUGHT);

然后,这取决于您希望 AI 播放器何时移动。你需要这样称呼:

public void AIMove() {
    int[] generatedMove = aiPlayer.move();
    board.cells[generatedMove[0]][generatedMove[1]].content = currentPlayer;
    updateGame(currentPlayer, generatedMove[0], generatexMove[1]);
    repaint();
}

这应该可行,但不是最好的代码设计。正如你所看到的,有很多重复,没有分离关注点和其他设计缺陷。但这对CodeReview.SE 来说是一个更好的问题。

于 2015-10-27T10:00:31.090 回答