跟踪在 for 循环中生成的 JButton
Keeping track of JButtons generated in a for loop
我正在开发 Java 井字游戏,但我无法跟踪我的 JButton,因为我使用 for 循环创建 9 个按钮:
for(int i=0;i<button.length;i++){
button[i] = new JButton();
button[i].setText(Integer.toString(i+1));
frame.add(button[i]);
button[i].addActionListener(this);
}
我想检查我的按钮文本是否匹配(rows/columns/diagonal),如果匹配,显示您赢了。
这是我的全部代码:
public class TicTacToe extends Board implements ActionListener{
JButton button[] = new JButton[9];
boolean win = false;
int count = 0;
String letter = "";
public TicTacToe(){
//create + add JButtons to JFrame
for(int i=0;i<button.length;i++){
button[i] = new JButton();
button[i].setText(Integer.toString(i+1));
frame.add(button[i]);
button[i].addActionListener(this);
}
}
public void actionPerformed(ActionEvent e) {
for(int i=0;i<button.length;i++){
if(i%2 == 0){
letter = "X";
}else{
letter = "O";
}
if(e.getSource() == button[i]){
button[i].setText(letter);
button[i].setEnabled(false);
count = i+1;
}
//check win
if(){ //<---------------NEED HELP HERE. THANK YOU
win = true;
JOptionPane.showMessageDialog(null, "YOU WIN");
}
}
}
}
如何跟踪动态创建的 JButton?
井字游戏的获胜条件是:
X - - - X - - - X
X - - or - X - or - - X
X - - - X - - - X
private boolean colWinner() {
for (int i = 0; i < 3; i++) {
String mark = button[i].getText();
if (mark.equals(button[i+3].getText()) &&
mark.equals(button[i+6].getText()) {
return true;
}
}
return false;
}
或
X X X - - - - - -
- - - or X X X or - - -
- - - - - - X X X
private boolean rowWinner() {
for (int i = 0; i < 3; i++) {
String mark = button[3*i].getText();
if (mark.equals(button[3*i+1].getText()) &&
mark.equals(button[3*i+2].getText()) {
return true;
}
}
return false;
}
或
X - - - - X
- X - or - X -
- - X X - -
private boolean diagWinner() {
String mark = button[4].getText();
return
(mark.equals(button[0].getText()) && mark.equals(button[8].getText()) ||
(mark.equals(button[2].getText()) && mark.equals(button[6].getText());
}
这种幼稚的方法会检查所有可能的获胜条件,如果您要在每回合后检查获胜情况,则实际上没有必要这样做。您只需要检查以下条件:
- 新标记所在的行
- 制作新标记的栏目
- 如果标记在角上则一条对角线,如果标记在中心则两条对角线。
我会留给你解决这个问题。
首先我会回答你的问题,但根据你的代码(或缺乏代码)判断,我会解决一些我认为你作为使用图形用户界面的 Java 程序员应该知道的事情(GUI)和 Java Swing。
第 1 部分:答案
有两种方法我可以想到解决这个问题。
下面的代码使用二维数组来表示JButtons 的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;
}
}
这可以重复七次以实现我们的目标。然而,这是很多重复代码,聪明的程序员会尽可能避免这种情况。
但是,在井字游戏中也有平局或"cat's game"的情况,我们该如何解决这个?好吧,如果没有获胜案例 AND 棋盘上满是棋子,那么我们就会陷入僵局。
方法 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" class,您必须自己编写,因为 Java 没有这样的 class。
作为 Java Swing GUI 程序员,您应该注意以下事项。
一个。 Java 秋千
您似乎对 Java Swing 没有很好的掌握,所以这里是 an introductory tutorial 开始。
乙。布局管理器
在尝试配置 GUI 布局时,布局管理器可以是您的朋友,也可以是您的敌人。 a good resource 供您探索。
摄氏度。模型-视图-控制器 (MVC)
解耦依赖关系是未来管理大型代码库的关键。 MVC 是一种流行的软件架构模式,有助于减少处理用户界面时的依赖性。 Check this out.
D.我的实现
你启发了我自己的工作Java 井字游戏的 Swing 实现。 Here it is!
干杯,编码愉快!
我正在开发 Java 井字游戏,但我无法跟踪我的 JButton,因为我使用 for 循环创建 9 个按钮:
for(int i=0;i<button.length;i++){
button[i] = new JButton();
button[i].setText(Integer.toString(i+1));
frame.add(button[i]);
button[i].addActionListener(this);
}
我想检查我的按钮文本是否匹配(rows/columns/diagonal),如果匹配,显示您赢了。
这是我的全部代码:
public class TicTacToe extends Board implements ActionListener{
JButton button[] = new JButton[9];
boolean win = false;
int count = 0;
String letter = "";
public TicTacToe(){
//create + add JButtons to JFrame
for(int i=0;i<button.length;i++){
button[i] = new JButton();
button[i].setText(Integer.toString(i+1));
frame.add(button[i]);
button[i].addActionListener(this);
}
}
public void actionPerformed(ActionEvent e) {
for(int i=0;i<button.length;i++){
if(i%2 == 0){
letter = "X";
}else{
letter = "O";
}
if(e.getSource() == button[i]){
button[i].setText(letter);
button[i].setEnabled(false);
count = i+1;
}
//check win
if(){ //<---------------NEED HELP HERE. THANK YOU
win = true;
JOptionPane.showMessageDialog(null, "YOU WIN");
}
}
}
}
如何跟踪动态创建的 JButton?
井字游戏的获胜条件是:
X - - - X - - - X
X - - or - X - or - - X
X - - - X - - - X
private boolean colWinner() {
for (int i = 0; i < 3; i++) {
String mark = button[i].getText();
if (mark.equals(button[i+3].getText()) &&
mark.equals(button[i+6].getText()) {
return true;
}
}
return false;
}
或
X X X - - - - - -
- - - or X X X or - - -
- - - - - - X X X
private boolean rowWinner() {
for (int i = 0; i < 3; i++) {
String mark = button[3*i].getText();
if (mark.equals(button[3*i+1].getText()) &&
mark.equals(button[3*i+2].getText()) {
return true;
}
}
return false;
}
或
X - - - - X
- X - or - X -
- - X X - -
private boolean diagWinner() {
String mark = button[4].getText();
return
(mark.equals(button[0].getText()) && mark.equals(button[8].getText()) ||
(mark.equals(button[2].getText()) && mark.equals(button[6].getText());
}
这种幼稚的方法会检查所有可能的获胜条件,如果您要在每回合后检查获胜情况,则实际上没有必要这样做。您只需要检查以下条件:
- 新标记所在的行
- 制作新标记的栏目
- 如果标记在角上则一条对角线,如果标记在中心则两条对角线。
我会留给你解决这个问题。
首先我会回答你的问题,但根据你的代码(或缺乏代码)判断,我会解决一些我认为你作为使用图形用户界面的 Java 程序员应该知道的事情(GUI)和 Java Swing。
第 1 部分:答案
有两种方法我可以想到解决这个问题。
下面的代码使用二维数组来表示JButtons 的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;
}
}
这可以重复七次以实现我们的目标。然而,这是很多重复代码,聪明的程序员会尽可能避免这种情况。
但是,在井字游戏中也有平局或"cat's game"的情况,我们该如何解决这个?好吧,如果没有获胜案例 AND 棋盘上满是棋子,那么我们就会陷入僵局。
方法 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" class,您必须自己编写,因为 Java 没有这样的 class。
作为 Java Swing GUI 程序员,您应该注意以下事项。
一个。 Java 秋千
您似乎对 Java Swing 没有很好的掌握,所以这里是 an introductory tutorial 开始。
乙。布局管理器
在尝试配置 GUI 布局时,布局管理器可以是您的朋友,也可以是您的敌人。 a good resource 供您探索。
摄氏度。模型-视图-控制器 (MVC)
解耦依赖关系是未来管理大型代码库的关键。 MVC 是一种流行的软件架构模式,有助于减少处理用户界面时的依赖性。 Check this out.
D.我的实现
你启发了我自己的工作Java 井字游戏的 Swing 实现。 Here it is!
干杯,编码愉快!