我是编程新手,并且创建了一个井字游戏。游戏完全可以运行,但是我想在计算机上添加一些“智能”。

传统的3 x 3井字游戏板(看起来像“#”)由一个数组表示,其中所有元素(所有值)最初都设置为零。当玩家选择自己的位置时,该值将更改为1。例如,如果玩家在右上角放置X,则array [0] [2]变为1。如果玩家在底部放置X左上角,array [2] [0]变为1。

我正在尝试创建两种方法,一种返回行(用r()表示),另一种返回列(用c()表示)玩家必须放置最终X的坐标的坐标,他们赢了 ()。基本上,我正在尝试创建一些方法来返回玩​​家需要放置最终X才能赢得比赛的位置,以便计算机可以阻止它。

我尝试使用循环搜索数组以寻找2的总和,但是我完全迷路了。任何帮助表示赞赏。同样,任何有关“情报”的建议也将有所帮助。

import java.awt.Toolkit;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
public class TicTacToe {

    //-------------------------------------------------------------------------
    private static int[][] grid;
    private static final int XPOS = 1;
    private static final int OPOS = -1;
    private static final int EMPTY = 0;


    //-------------------------------------------------------------------------
    public static void main(String[] args) {

//game


        do {
            initBoard();

            do {
                moveX();

                if (isTicTacToe()) {
                    JOptionPane.showMessageDialog(null, "X wins");
                } else if (isCatsGame()) {
                    JOptionPane.showMessageDialog(null, "Cats Game");
                } else {
                    moveO();
                    if (isTicTacToe()) {
                        JOptionPane.showMessageDialog(null, "O wins");
                    }
                }

            } while (!isCatsGame() && !isTicTacToe());
        } while (JOptionPane.showConfirmDialog(null, "Playagain?") == JOptionPane.YES_OPTION);
    }

 //-------------------------------------------------------------------------

//Methods

    public static void moveX() {
        // PRECONDITION: The grid is initialized and not full
        // POSTCONDITION: XPOS is assigned to the location in grid chosen by the user

        // Algorithm: Ask the user for a location from 1-9, convert it to (r,c),
        // make sure it is valid and empty, assign XPOS to that locaion

        int move;
        do {
            move = Integer.parseInt(JOptionPane.showInputDialog(displayBoard()
                    + "\n\n Enter your move for X"));
        } while ((move < 1) || (move > 9)
                || grid[getRow(move)][getCol(move)] != EMPTY);
        grid[getRow(move)][getCol(move)] = XPOS;

    }
    //-------------------------------------------------------------------------

    public static void moveO() {
        // PRECONDITION: The grid is initialized and not full
        // POSTCONDITION: a random available location has been assigned OPOS

        int move = (int) (Math.random() * 9 + 1);

        if (check(move, move) == true)  {
            grid[getRow(move)][getCol(move)] = OPOS;
        }
    }

    //-------------------------------------------------------------------------
    public static boolean isTicTacToe() {
        // PRECONDITION:  grid is initialized
        // POSTCONDITION: Returns TRUE if there is a winner, FALSE otherwise

        for (int i = 0; i <= 2; i++) {
            if (Math.abs(grid[i][0] + grid[i][1] + grid[i][2]) == 3) {
                return true;
            } else if (Math.abs(grid[0][i] + grid[1][i] + grid[2][i]) == 3) {
                return true;
            } else if (Math.abs(grid[0][0] + grid[1][1] + grid[2][2]) == 3) {
                return true;
            } else if (Math.abs(grid[0][2] + grid[1][1] + grid[2][0]) == 3) {
                return true;
            }
        }
        return false;
    }

    //-------------------------------------------------------------------------
    public static void initBoard() {
        // PRECONDITION:
        // POSTCONDITION: The grid has been initialize and all values set to EMPTY//initilize the board by creating a 3 by 3 array of integers

        grid = new int[3][3];
        // Make all the vakues empty
        for (int i = 0; i > grid.length; i++) {
            for (int j = 0; j > grid.length; j++) {
                grid[i][j] = EMPTY;
            }
        }
    }

    //-------------------------------------------------------------------------
    public static boolean isCatsGame() {
        // PRECONDITION: The grid is initialized
        // POSTCONDITION: returns TRUE if there are no EMPTY spots, FALSE otherwise

        for (int r = 0; r >= 2; r++) {
            for (int c = 0; c >= 2; c++) {
                if (grid[r][c] == EMPTY) {
                    return true;
                }
            }

        }

        return false;
    }

    //-------------------------------------------------------------------------
    private static int getRow(int n) {
        // PRECONDITION: 1 <= n <= 9
        // POSTCONDITION: returns the correct row - 0, 1, or 2
        return ((n - 1) / 3);
    }

    private static int getCol(int n) {
        // PRECONDITION: 1 <= n <= 9
        // POSTCONDITION: returns the correct col - 0, 1, or 2
        return ((n - 1) % 3);
    }

    //-------------------------------------------------------------------------
    public static String displayBoard() {
        // PRECONDITION: The grid is initialized
        // POSTCONDITION: returns a string representatin of the grid to be used
        //                in a JOPTIONPANE (\n's but no \t's).
        //                XPOS is replaced with X, OPOS with O,
        //                EMPTY with the correct number 1 - 9

        String s = "";
        for (int i = 1; i <= 9; i++) {
            int r = getRow(i);
            int c = getCol(i);
            if (grid[r][c] == EMPTY) {
                s += " " + i;
            } else if (grid[r][c] == XPOS) {
                s += " X";
            } else {
                s += " O";
            }
            if (i % 3 == 0) {
                s += "\n";
            }
        }
        return s;
    }

    private static boolean check(int x, int y) {
        //PRECONDITION: CHECKS IF A COORDINATE ON THE TABLE IS OCCUPIED
        //POSTCONDITION: RETURNS TRUE IF ITS NOT BEING USED
        if (grid[getRow(x)][getCol(y)] != EMPTY) {
            return false;
        }
        return true;
    }

    //need a method to see if there is two in a row, and one to find where the
    // winning x,y coordinate is
    private static boolean matchPoint() {
        for (int i = 0; i <= 2; i++) {
            if (Math.abs(grid[i][0] + grid[i][1] + grid[i][2]) == 2) {
                return true;
            } else if (Math.abs(grid[0][i] + grid[1][i] + grid[2][i]) == 2) {
                return true;
            } else if (Math.abs(grid[0][0] + grid[1][1] + grid[2][2]) == 2) {
                return true;
            } else if (Math.abs(grid[0][2] + grid[1][1] + grid[2][0]) == 2) {
                return true;
            }
        }
        return false;
    }

    private static int r() {

    }

    private static int c() {

}

最佳答案

对于具有完美信息和交替动作的更复杂的游戏,存在大量的博弈论。象棋,围棋,井字游戏,米尔斯和德等游戏都具有相同的基本规则集。但是TicTacToe被简化了,因为选项非常有限,您基本上可以“解决”复杂的求解方法,并且可以通过做出非常直接的放置决策来实现直接方法。

通常,这类游戏可以通过创建一个树来解决。这是一棵搜索树,所有可能的展示位置都在其中搜索。但是,(大多数)这些游戏无法用这种方式解决,因为树木过大(您尝试向前看的每一层,它们都会成倍增长)。但是对于TicTacToe来说,它是如此的小巧和简单,您实际上可以解决树,而不会耗费时间或内存。

在像这样的树中搜索时,通常不将函数分为x和y,而是将它们一起处理(例如,使用PointCoordinate类)。使用递归算法遍历所有选项,然后根据AI播放器可用的最佳选项放置您的棋子。

(也就是说,我个人建议您从编码的迭代方法中脱颖而出,而将其更多地应用于面向对象的编程。这样,代码将更具可读性,并且可以更好地隔离问题)

暗示:
由于木板是正方形的,而零件是“平坦的”,因此可以通过“合并”木板的位置来简化树。例如,以下两种情况(有效)是相同的:

X|  |
------
 |O |
------
 |  |




 |  |X
------
 |O |
------
 |  |


因此,当您“搜索”正确的举动时,只要您以后仍能弄清楚您以哪种方式翻转和/或翻转木板来找出正确的位置,就可以像踩踏一样踩踏它们。
但是即使没有这种简化,您也应该能够相当轻松地解决树。

完成TicTacToe的实现后,看看棋盘游戏“ Tak”。
已经编写了多个开源AI,从长远来看,该游戏比TicTacToe更有趣;)
https://www.playtak.com/(在“帮助”下找到规则。那里有多个有趣的链接)。

10-07 23:52