【问题标题】:Finding elements in a 3x3 array在 3x3 数组中查找元素
【发布时间】:2019-01-30 17:28:20
【问题描述】:

我是编程新手,我创建了一个井字游戏。游戏完全可以,但我想给电脑加点“智能”。

传统的 3 x 3 tic tac toe board(看起来像“#”)由一个数组表示,其中所有元素(所有值)最初都设置为零。当玩家选择他/她的位置时,该值变为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() {

}

【问题讨论】:

    标签: java arrays tic-tac-toe


    【解决方案1】:

    对于具有完全信息和交替移动的更复杂的博弈,存在大量的博弈论。 Chess、Go、TicTacToe、Mills 和 Tak 等游戏都基于相同的基本规则集。但是井字游戏被简化了,因为选项非常有限,您基本上可以“解决”复杂的解决方法,并且可以通过做出非常直接的放置决策来实施直接的方法。

    通常这样的游戏是通过创建一个层树来解决的。这是一个搜索树,所有可能的展示位置都在其中运行。但是(大多数)这些游戏无法通过这种方式解决,因为树太长了(它们随着您尝试向前看的每一层而呈指数增长)。但是对于小而简单的井字游戏,你实际上可以解树,而不会耗尽时间或内存。

    在这样的树中搜索时,您通常不会将函数分开为 x 和 y,而是一起处理(例如使用 PointCoordinate 类)。使用递归算法打磨所有选项,然后根据 AI 玩家可用的最佳选项放置您的作品。

    (也就是说,我个人建议您摆脱迭代的编码方式,更多地进入面向对象的编程。这样代码变得更具可读性,您可以更好地隔离问题)

    提示: 由于棋盘是正方形的,并且棋子是“平的”,因此您可以通过“合并”棋盘位置来简化树。例如,以下两种情况(实际上)是相同的:

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

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

    因此,当您“搜索”正确的移动时,只要您以后仍能弄清楚您转动和/或翻转棋盘的方式,就可以确定正确的位置。 但即使没有这种简化,您也应该能够相当轻松地求解树。

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

    【讨论】:

      【解决方案2】:

      我将使用与您的 isTicTacToe() 方法相同的逻辑,并在您的 grid 表中查找可能的位置并将其返回,或者如果找不到这样的位置,则返回 null。例如:

      import java.awt.Point;
      // ...
      Point getPointToWin() {
          // look for wc (win condition) and return it if found, otherwise null
          for(int r=0; r<grid.length; r++) {
              for(int c=0; c<grid[0].length; c++) {
                  // skip if not X
                  if(grid[r][c]!=XPOS)
                      continue;
                  // lookup wc in top row
                  if(r==0)
                      if(c==0) {
                          if(grid[r][c+1]==XPOS)
                              return new Point(r,c+2)
                          if(grid[r+1][c+1]==XPOS)
                              return new Point(r+2,c+2)
                          if(grid[r+1][c]==XPOS)
                              return new Point(r+2,c)
                      }
                      elseif(c==1) {
                          // ... top row, center column
                      }
                      elseif(c==2) {
                          // ... top row, right column
                      }
                  elseif(r==1) {
                      // ... center row, left/center/right column
                  }
                  elseif(r==2) {
                      // ... bottom row, left/center/right column
                  }
              }
          }
          return null;
      }
      

      为了使其尽可能短,我只在右行顶列找到 X 时才编写 wc 查找逻辑。然后,您必须为 X 的其余 8 个可能位置编写逻辑。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-21
        • 2016-05-14
        • 2016-11-11
        • 2017-04-10
        相关资源
        最近更新 更多