对井字游戏获胜者的二维数组进行排序
Posted
技术标签:
【中文标题】对井字游戏获胜者的二维数组进行排序【英文标题】:Sorting through 2D array for Tic Tac Toe winner 【发布时间】:2022-01-15 08:15:19 【问题描述】:我用这种非常令人讨厌的方式在井字游戏中找到获胜者,我只是想知道是否有更简单的方法来做到这一点。 这是我目前使用的方法,正如您所见,它非常多余和重复。任何缩小范围的技巧都会很棒。我在想也许嵌套的 for 循环可能会起作用,但不完全确定如何在其中进行设置。
public static boolean isGameOver(char[][] gameBoard)
//Testing for Horizontal Win
if(gameBoard[0][0] == 'X' && gameBoard[0][2] == 'X' && gameBoard [0][4] == 'X')
System.out.println("Player Wins!\n");
playerScore++;
return true;
if(gameBoard[0][0] == 'O' && gameBoard[0][2] == 'O' && gameBoard [0][4] == 'O')
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
if(gameBoard[2][0] == 'X' && gameBoard[2][2] == 'X' && gameBoard [2][4] == 'X')
System.out.println("Player Wins!\n");
playerScore++;
return true;
if(gameBoard[2][0] == 'O' && gameBoard[2][2] == 'O' && gameBoard [2][4] == 'O')
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
if(gameBoard[4][0] == 'X' && gameBoard[4][2] == 'X' && gameBoard [4][4] == 'X')
System.out.println("Player Wins!\n");
playerScore++;
return true;
if(gameBoard[4][0] == 'O' && gameBoard[4][2] == 'O' && gameBoard [4][4] == 'O')
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
//Testing for Vertical Win
if(gameBoard[0][0] == 'X' && gameBoard[2][0] == 'X' && gameBoard [4][0] == 'X')
System.out.println("Player Wins!\n");
playerScore++;
return true;
if(gameBoard[0][0] == 'O' && gameBoard[2][0] == 'O' && gameBoard [4][0] == 'O')
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
if(gameBoard[0][2] == 'X' && gameBoard[2][2] == 'X' && gameBoard [4][2] == 'X')
System.out.println("Player Wins!\n");
playerScore++;
return true;
if(gameBoard[0][2] == 'O' && gameBoard[2][2] == 'O' && gameBoard [4][2] == 'O')
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
if(gameBoard[0][4] == 'X' && gameBoard[2][4] == 'X' && gameBoard [4][4] == 'X')
System.out.println("Player Wins!\n");
playerScore++;
return true;
if(gameBoard[0][4] == 'O' && gameBoard[2][4] == 'O' && gameBoard [4][4] == 'O')
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
//Testing for Diagonal Win
if(gameBoard[0][0] == 'X' && gameBoard[2][2] == 'X' && gameBoard [4][4] == 'X')
System.out.println("Player Wins!\n");
playerScore++;
return true;
if(gameBoard[0][0] == 'O' && gameBoard[2][2] == 'O' && gameBoard [4][4] == 'O')
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
if(gameBoard[4][0] == 'X' && gameBoard[2][2] == 'X' && gameBoard [0][4] == 'X')
System.out.println("Player Wins!\n");
playerScore++;
return true;
if(gameBoard[4][0] == 'O' && gameBoard[2][2] == 'O' && gameBoard [0][4] == 'O')
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
//Testing for Tie
if(gameBoard[0][0] != ' ' && gameBoard[0][2] != ' ' && gameBoard[0][4] != ' ' &&
gameBoard[2][0] != ' ' && gameBoard[2][2] != ' ' && gameBoard[2][4] != ' ' &&
gameBoard[4][0] != ' ' && gameBoard[4][2] != ' ' && gameBoard[4][4] != ' ')
System.out.println("It's a tie!!!\n");
numOfTies++;
return true;
return false;
【问题讨论】:
【参考方案1】:好吧,我有点得意忘形了。但也许你可以使用这里提出的一些想法。我的主要目标是做到这一点,这样每次移动后都不需要检查整个棋盘。这是在程序设计阶段最好考虑的问题类型。
我创建了一个TriGroup
类(它本质上是一个用于保存连续移动的可变字符串。
然后使用地图来保存所有具有共同坐标的分组。
进行移动时,这些分组会附加当前玩家。
并检查该玩家是否获胜。
此程序将使用随机动作自行运行,从而产生胜利或平局。
有些边境案件可能被忽略了。
public class TicTacToeCheck
int moveCount = 0;
static int MAX_MOVES = 27;
class TriGroup
public String group = "";
@Override
public String toString()
return group;
TriGroup row1 = new TriGroup();
TriGroup row2 = new TriGroup();
TriGroup row3 = new TriGroup();
TriGroup col1 = new TriGroup();
TriGroup col2 = new TriGroup();
TriGroup col3 = new TriGroup();
TriGroup diag1 = new TriGroup();
TriGroup diag2 = new TriGroup();
Map<String, List<TriGroup>> commonGroupings = new HashMap<>();
commonGroupings.put("00", List.of(row1, col1, diag1));
commonGroupings.put("02", List.of(row1, col2));
commonGroupings.put("04", List.of(row1, col3));
commonGroupings.put("20", List.of(row2, col1));
commonGroupings.put("22", List.of(row2, col2, diag1, diag2));
commonGroupings.put("24", List.of(row2, col3));
commonGroupings.put("40", List.of(row3, col1, diag1));
commonGroupings.put("42", List.of(row3, col2));
commonGroupings.put("44", List.of(row3, col3));
public static void main(String[] args)
new TicTacToeCheck().start();
public void start()
char player = 'X';
Random r = new Random();
outer: while (moveCount < MAX_MOVES)
commonGroupings.entrySet().forEach(System.out::println);
System.out.println();
int row = r.nextInt(3) * 2;
int col = r.nextInt(3) * 2;
System.out.println("Move: " + row + ", " + col);
player = player == 'X' ? 'O' : 'X';
char val;
switch (val = recordMove(row, col, player))
case 'X' ->
System.out.println("X wins!");
break outer;
case 'O' ->
System.out.println("O wins!");
break outer;
case 0 ->
System.out.println("Tie!");
break outer;
default ->
commonGroupings.entrySet().forEach(System.out::println);
public char recordMove(int row, int col, char c)
moveCount++;
for (TriGroup tri : commonGroupings.get(row + "" + col))
if (tri.group.length() > 2)
// just ignore the row/col and try the next
continue;
// update group
tri.group += c;
if (tri.group.equals(c + "" + c + "" + c))
return c;
if (moveCount == MAX_MOVES)
return 0;
return '#';
【讨论】:
我真的很喜欢这种方法(你有一个目标,你成功了;而且代码很漂亮)。但是,我认为作为对 OP 问题的回答,这太过分了。简单就是好的,特别是在游泳池的浅水区。【参考方案2】:此版本使用 2 个辅助的私有方法来减少代码重复性,而不会改变调用 isGameOver
的行为。主要观察结果是,通过O
检查是否获胜或通过X
检查获胜之间几乎没有区别——只有一个字符。这样就变成了checkWins
。下一个观察结果是,检查棋盘上相邻的 3 个位置涉及大量重复。如果你给我expect
的字符,从哪里开始,接下来看哪里(dcol
和drow
),就变成了allEqual
。
您的代码跳过了棋盘的不均匀位置;我的代码没有。我觉得将展示(“你如何向用户展示东西”)与模型(“你如何在内部展示东西”)混为一谈是错误的;所以我的代码目前不是你的替代品,但可以通过调整 checkWins
中的值快速修复为这样的替代品(对角线向下将是 0, 0, 2, 2
,依此类推)。
请注意,就效率而言,您的代码可能更快。但我发现这个版本更短、更易读,因此更易于调试和维护。
private static boolean allEqual(char expected, char[][] b,
int row, int col, int drow, int dcol)
for (int i=0; i<b[0].length; i++)
if (b[row][col] != expected) return false;
row += drow;
col += dcol;
return true;
private static boolean checkWins(char playerChar, char[][]b)
boolean win = allEqual(playerChar, b, 0, 0, 0, 1) // 1st row
|| allEqual(playerChar, b, 1, 0, 0, 1)
|| allEqual(playerChar, b, 2, 0, 0, 1) // 3rd row
|| allEqual(playerChar, b, 0, 0, 1, 0) // 1st col
|| allEqual(playerChar, b, 0, 1, 1, 0)
|| allEqual(playerChar, b, 0, 2, 1, 0) // 3rd col
|| allEqual(playerChar, b, 0, 0, 1, 1) // diagonal down
|| allEqual(playerChar, b, 2, 0, 1,-1); // diagonal up
return win;
public static boolean isGameOver(char[][] gameBoard)
if (checkWins('X', gameBoard))
System.out.println("Player Wins!\n");
playerScore ++;
return true;
else if (checkWins('O', gameBoard))
System.out.println("CPU Wins!\n");
cpuScore ++;
return true;
else
return false;
【讨论】:
【参考方案3】:看看这个: https://www.geeksforgeeks.org/tic-tac-toe-game-in-java/
添加gameBoard[x][y]
的字符串并在switch 语句中检查它们。
如果复合字符串等于XXX
或OOO
,则可以返回获胜者。
对于您的代码,如下所示:
for (int a = 0; a < 8; a++)
String line = null;
switch (a)
case 0:
line = gameBoard[0][0] + gameBoard[0][1] + gameBoard[0][2];
break;
case 1:
line = gameBoard[1][0] + gameBoard[1][1] + gameBoard[1][2];
break;
case 2:
line = gameBoard[2][0] + gameBoard[2][1] + gameBoard[2][2];
break;
case 3:
line = gameBoard[0][0] + gameBoard[1][0] + gameBoard[2][0];
break;
case 4:
line = gameBoard[0][1] + gameBoard[1][1] + gameBoard[2][1];
break;
case 5:
line = gameBoard[0][2] + gameBoard[1][2] + gameBoard[2][2];
break;
case 6:
line = gameBoard[0][0] + gameBoard[1][1] + gameBoard[2][2];
break;
case 7:
line = gameBoard[0][2] + gameBoard[1][1] + gameBoard[2][0];
break;
//For X winner
if (line.equals("XXX"))
return "X";
// For O winner
else if (line.equals("OOO"))
return "O";
【讨论】:
以上是关于对井字游戏获胜者的二维数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章