首先我将回答您的问题,但根据您的代码(或缺少代码)来判断,然后我将解决一些我认为作为使用图形用户界面 (GUI) 和 Java Swing 的 Java 程序员应该注意的事情.
第 1 部分:答案
我能想到两种方法来解决这个问题。
以下代码使用二维数组来表示 JButton 的 3x3 板(请注意为什么不使用二维数组,实际上很困惑为什么不使用)。此外,它假定所有 JButton 的文本最初都设置为“.”。因为这比检查文本是否是 9 个不同的字符串数字之一要容易得多。
方法 A:静态案例
由于棋盘是如此之小,因此可以简单地检查玩家赢得井字游戏的每一种情况,并验证其中一种情况是否属实。下图说明了导致玩家获胜的八种情况。
请注意,“O”可以很容易地替换下面的“X”,重要的是每个人都属于同一个玩家。此外,任何“。”标记只是占位符,因为它实际上代表板上的“X”、“O”还是“null”并不重要。
// Case 1
// if each location across the top row is not empty
if (board[0][0].getText() != "." && board[0][1].getText() != "." && board[0][2].getText() != ".") {
// if each location has the same text
if (board[0][0].getText() == board[0][1].getText() &&
board[0][0].getText() == board[0][2].getText()) {
// if the player is X then X is winner, else player is O and O is winner
if (board[0][0].player() == Player.X)
return Status.X_WINNER;
else if (board[0][0].player() == Player.O)
return Status.O_WINNER;
}
}
然后可以重复七次以实现我们的目标。但是,这是大量重复的代码,聪明的程序员会尽可能避免这种情况。
但是,井字游戏中也存在平局或“猫的游戏”,我们如何解决这个问题?好吧,如果没有获胜的案例并且棋盘上满是棋子,那么我们就陷入了僵局。
方法 B:动态检查
我承认,这种方法是一个庞然大物,我确信它可以使用一些智能重构,但它很实用,可以动态解决问题。有许多条件可以尝试通过仅在绝对必要时继续执行来提高算法的效率。
请注意,我会检查一个棋子的周围邻居,这对于正确检查对角线是否赢得比赛至关重要。
// track if game won
boolean won = false;
// constant for board width and height
int BOARD_SIZE = 3;
// track pieces on board
int numPieces = 0;
// track who won
String winner = "";
// loop through the board first time
for (int row1 = 0; row1 < board.length; row1++) {
for (int col1 = 0; col1 < board.length; col1++) {
// if piece exists here
if (board[row1][col1].getText() != ".") {
// increment number of pieces on board
numPieces++;
// check pieces around first piece
for (int row2 = row1 - 1; row2 <= row1 + 1; row2++) {
for (int col2 = col1 - 1; col2 <= col1 + 1; col2++) {
// ensure within bounds of board
if ((row2 >= 0 && row2 < BOARD_SIZE) && (col2 >= 0 && col2 < BOARD_SIZE)) {
// ignore checking with first piece (itself)
if (board[row2][col2] != board[row1][col1]) {
// if second piece equal to first piece
if (board[row2][col2].getText() == board[row1][col1].getText()) {
// check pieces around second piece
for (int row3 = row2 - 1; row3 <= row2 + 1; row3++) {
for (int col3 = col2 - 1; col3 <= col2 + 1; col3++) {
// ensure within bounds of board
if ((row3 >= 0 && row3 < BOARD_SIZE) && (col3 >= 0 && col3 < BOARD_SIZE)) {
// ignore checking pieces we already have
if (board[row3][col3] != board[row2][col2] && board[row3][col3] != board[row1][col1]) {
// if third piece equal to first piece (and so also equal to second)
if (board[row3][col3].getText() == board[row1][col1].getText()) {
// if three pieces are all on same row
if (row1 == row2 && row1 == row3) {
if (board[row1][col1].getText() == "X")
winner = "X";
else
winner = "O";
won = true;
break;
}
// else if three pieces are all on same column
else if (col1 == col2 && col1 == col3) {
if (board[row1][col1].getText() == "X")
winner = "X";
else
winner = "O";
won = true;
break;
}
// else if three pieces are all on different rows and columns (winning diagonal)
else if ((row1 != row2 && row1 != row3 && row2 != row3) && (col1 != col2 && col1 != col3 && col2 != col3)) {
if (board[row1][col1].getText() == "X")
winner = "X";
else
winner = "O";
won = true;
break;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
if (winner == "X") {
JOptionPane.showMessageDialog(null, "X wins");
}
else if (winner == "O") {
JOptionPane.showMessageDialog(null, "O wins");
}
// if board is full and hasn't resulted in any winners
if (!won && numPieces == BOARD_SIZE * BOARD_SIZE)
JOptionPane.showMessageDialog(null, "Cats game");
当然,更少的代码行数并不一定能保证更好的性能,我们再次庆幸这是一块如此小的板子。像这样在大板上循环多次(即蛮力方法)会造成灾难性的运行时间,因此这是另一个需要考虑的设计选择。
第 2 部分:更进一步
我不认为这真的是您的所有代码,因为您提供的代码无法执行without a main method。
此外,如果您要扩展“Board”类,您必须自己编写,因为 Java 不附带这样的类。
作为 Java Swing GUI 程序员,您应该了解以下几点。
A. Java 摇摆
您似乎对 Java Swing 没有深入了解,所以这里是 an introductory tutorial 让您开始。
B.布局管理器
在尝试配置 GUI 布局时,布局管理器可能是您的朋友,也可能是您的敌人。这是a good resource 供您探索。
C.模型-视图-控制器 (MVC)
解耦依赖关系是未来管理大型代码库的关键。 MVC 是一种流行的软件架构模式,有助于在处理用户界面时减少依赖关系。 Check this out.
D.我的实现
您启发了我开发自己的井字游戏 Java Swing 实现。 Here it is!
干杯,编码愉快!