我是编程新手,并且创建了一个井字游戏。游戏完全可以运行,但是我想在计算机上添加一些“智能”。
传统的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() {
}
答案 0 :(得分:0)
对于具有完善信息和交替动作的更复杂的游戏,存在大量的游戏理论。象棋,围棋,井字游戏,米尔斯和德这样的游戏都具有相同的基本规则集。但是TicTacToe被简化了,因为选项非常有限,您基本上可以“解决”复杂的求解方式,并且可以通过做出非常直接的放置决策来实现直接方式。
通常,此类游戏可以通过创建一个树来解决。这是一棵搜索树,所有可能的展示位置都在其中搜索。但是,(大多数)这些游戏无法通过这种方式解决,因为树木过大(您尝试向前看的每一层,它们都会成倍增长)。但是对于TicTacToe来说,它是如此的小巧和简单,您实际上可以解决树,而不会耗费时间或内存。
在像这样的树中搜索时,通常不将函数分为x和y,而是将它们一起处理(例如,使用Point
或Coordinate
类)。使用递归算法遍历所有选项,然后根据AI播放器可用的最佳选项放置您的棋子。
(也就是说,我个人建议您从迭代的编码方式中脱颖而出,并进一步进行面向对象的编程。这样,代码将更具可读性,并且可以更好地隔离问题)
提示: 由于木板是正方形的,而零件是“平坦的”,因此可以通过“合并”木板的位置来简化树。例如,以下两种情况(有效)是相同的:
X| |
------
|O |
------
| |
和
| |X
------
|O |
------
| |
因此,当您“搜索”正确的举动时,您可以按照相同的步骤进行踩踏,只要稍后您仍可以弄清楚您以哪种方式翻转和/或翻转木板,以找出正确的位置。 但是即使没有这种简化,您也应该能够很容易地解决树。
完成TicTacToe的实现后,看看棋盘游戏“ Tak”。 已经编写了多个开源AI,从长远来看,该游戏比TicTacToe更有趣;) https://www.playtak.com/(在“帮助”下找到规则。那里有多个有趣的链接)。
答案 1 :(得分:0)
我将使用与您的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;
}
为使它尽可能短,我只写了wc查找逻辑(如果在右行,顶列中找到了X)。然后,您将不得不为X的其余8个可能位置编写逻辑。