我创建了一个游戏,但输赢和平局的计数器不工作
I created a game, but the counter for wins, losses and draws isn't working
有人会认为这是最简单的事情(应该是正确的),但我的 JLabel 值没有更新以反映游戏是平局、输还是赢。我启动了 3 个变量(numLosses、numDraws 和 numWins),然后在每次输、赢或平局时递增它们。但是我的计数器仍然为 0?为什么?这是代码?
NewTicTacToe.java:
package newtictactoe;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class NewTicTacToe
extends JFrame
{
public static void main(String [] args)
{
new NewTicTacToe();
}
private JButton btnA1, btnA2, btnA3, btnB1, btnB2, btnB3, btnC1, btnC2, btnC3;
private JLabel lblWins, lblLosses, lblDraws;
private TicTacToeBoard board;
private int numWins, numDraws, numLosses;
public NewTicTacToe()
{
// Set up the grid
this.numDraws = 0;
this.numWins = 0;
this.numLosses = 0;
this.setSize(800,450);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Tic-Tac-Toe");
JPanel panel1 = new JPanel();
panel1.setSize(650,450); //resolution of panel1 set to 650 by 325
panel1.setLayout(new GridLayout(3,3));
btnA1 = createButton("A1");
btnA2 = createButton("A2");
btnA3 = createButton("A3");
btnB1 = createButton("B1");
btnB2 = createButton("B2");
btnB3 = createButton("B3");
btnC1 = createButton("C1");
btnC2 = createButton("C2");
btnC3 = createButton("C3");
panel1.add(btnA1);
panel1.add(btnA2);
panel1.add(btnA3);
panel1.add(btnB1);
panel1.add(btnB2);
panel1.add(btnB3);
panel1.add(btnC1);
panel1.add(btnC2);
panel1.add(btnC3);
JPanel panel2 = new JPanel();
panel2.setLayout(new BorderLayout());
lblWins = new JLabel("Wins: " + numWins);
lblLosses = new JLabel("Losses: " + numLosses);
lblDraws = new JLabel("Draws: " + numDraws);
panel2.add(lblWins);
panel2.add(lblLosses);
panel2.add(lblDraws);
lblWins.setLocation(670, 20);
lblLosses.setLocation(670, 50);
lblDraws.setLocation(670, 80);
lblWins.setSize(100, 20);
lblLosses.setSize(100, 20);
lblDraws.setSize(100, 20);
panel2.setLayout(null);
this.add(panel1);
this.add(panel2);
this.setVisible(true);
// Start the game and create new instance of TicTacToeBoard
board = new TicTacToeBoard();
}
private JButton createButton(String square)
{
JButton btn = new JButton();
btn.setPreferredSize(new Dimension(50, 50));
Font f = new Font("Dialog", Font.PLAIN, 72);
btn.setFont(f);
btn.addActionListener(e -> btnClick(e, square));
return btn;
}
private void btnClick(ActionEvent e, String square)
{
if (board.getSquare(square) != 0)
return;
JButton btn = (JButton)e.getSource();
btn.setText("X");
board.playAt(square, 1);
if (board.isGameOver() == 3)
{
JOptionPane.showMessageDialog(null,
"It's a draw!", "Game Over",
JOptionPane.INFORMATION_MESSAGE);
numDraws++;
resetGame();
return;
}
if (board.isGameOver() == 1)
{
JOptionPane.showMessageDialog(null,
"You Win n00b!", "Game Over",
JOptionPane.INFORMATION_MESSAGE);
numWins++;
resetGame();
return;
}
String computerMove = board.getNextMove();
board.playAt(computerMove,2);
switch (computerMove)
{
case "A1":
btnA1.setText("O");
break;
case "A2":
btnA2.setText("O");
break;
case "A3":
btnA3.setText("O");
break;
case "B1":
btnB1.setText("O");
break;
case "B2":
btnB2.setText("O");
break;
case "B3":
btnB3.setText("O");
break;
case "C1":
btnC1.setText("O");
break;
case "C2":
btnC2.setText("O");
break;
case "C3":
btnC3.setText("O");
break;
}
if (board.isGameOver() == 2)
{
JOptionPane.showMessageDialog(null,
"Computer wins you big n00b!", "Game Over",
JOptionPane.INFORMATION_MESSAGE);
numLosses++;
resetGame();
return;
}
}
private void resetGame()
{
board.reset();
btnA1.setText("");
btnA2.setText("");
btnA3.setText("");
btnB1.setText("");
btnB2.setText("");
btnB3.setText("");
btnC1.setText("");
btnC2.setText("");
btnC3.setText("");
}
}
TicTacToeBoard.java:
package newtictactoe;
public class TicTacToeBoard
{
int numWins = 0;
int numLosses = 0;
int numDraws = 0;
private int board [];
private int vectors [] [] =
{
{0, 1, 2}, // Row 1
{3, 4, 5}, // Row 2
{6, 7, 8}, // Row 3
{0, 3, 6}, // Column 1
{1, 4, 7}, // Column 2
{2, 5, 8}, // Column 3
{0, 4, 8}, // Diagonal 1
{2, 4, 6} // Diagonal 2
};
public TicTacToeBoard()
{
this.reset();
}
public void reset()
{
board = new int[] {2, 2, 2, 2, 2, 2, 2, 2, 2};
}
private int getSquare(int index)
{
if (index < 0 | index > 8)
throw new IllegalArgumentException("index must be 0-9");
return board[index];
}
public int getSquare(String square)
{
int index = mapSquareToIndex(square);
if (index == -1)
throw new IllegalArgumentException("Invalid square");
switch (getSquare(index))
{
case 3:
return 1;
case 5:
return 2;
default:
return 0;
}
}
private int mapSquareToIndex(String square)
{
switch (square)
{
case "A1":
return 0;
case "A2":
return 1;
case "A3":
return 2;
case "B1":
return 3;
case "B2":
return 4;
case "B3":
return 5;
case "C1":
return 6;
case "C2":
return 7;
case "C3":
return 8;
default:
return -1;
}
}
private String mapIndexToSquare(int index)
{
switch (index)
{
case 0:
return "A1";
case 1:
return "A2";
case 2:
return "A3";
case 3:
return "B1";
case 4:
return "B2";
case 5:
return "B3";
case 6:
return "C1";
case 7:
return "C2";
case 8:
return "C3";
default:
return "";
}
}
public void playAt(String square, int player)
{
int index = mapSquareToIndex(square);
if (index == -1)
throw new IllegalArgumentException("Invalid square");
this.playAt(index, player);
}
private void playAt(int index, int player)
{
if (index < 0 | index > 8)
throw new IllegalArgumentException("Square must be 0-8");
if (player <1 | player > 2)
throw new IllegalArgumentException("Player must be 1 or 2");
if (board[index] != 2)
throw new IllegalArgumentException("Square is not empty.");
if (player == 1)
board[index] = 3;
else
board[index] = 5;
}
public int isGameOver()
{
// check for win
for (int v = 0; v < 8; v++)
{
int p = getVectorProduct(v);
if (p == 27) {
numWins++;
return 1;
} // Player 1 has won
if (p == 125) {
numLosses++;
return 2;
// Player 2 has won
}
}
// check for draw
int blankCount = 0;
for (int i = 0; i < 9; i++)
if (board[i] == 2)
blankCount++;
if (blankCount == 0) {
numDraws++;
return 3; // Game is a draw
}
return 0; // Game is not over
}
public String canPlayerWin(int player)
{
if (player <1 | player > 2)
throw new IllegalArgumentException("player must be 1 or 2");
boolean playerCanWin = false;
for (int v = 0; v < 8; v++)
{
int p = getVectorProduct(v);
if ( (player == 1 & p == 18)
| (player == 2 & p == 50) )
{
if (board[vectors[v][0]] == 2)
return mapIndexToSquare(vectors[v][0]);
if (board[vectors[v][1]] == 2)
return mapIndexToSquare(vectors[v][1]);
if (board[vectors[v][2]] == 2)
return mapIndexToSquare(vectors[v][2]);
}
}
return "";
}
private int getVectorProduct(int vector)
{
return board[vectors[vector][0]] *
board[vectors[vector][1]] *
board[vectors[vector][2]];
}
public String getNextMove()
{
String bestMove;
// Win if possible
bestMove = this.canPlayerWin(2);
if (bestMove != "")
return bestMove;
// Block if necessary
bestMove = this.canPlayerWin(1);
if (bestMove != "")
return bestMove;
// Center if it is open
if (board[4] == 2)
return "B2";
// First open corner
if (board[0] == 2)
return "A1";
if (board[2] == 2)
return "A3";
if (board[6] == 2)
return "C1";
if (board[8] == 2)
return "C3";
// First open edge
if (board[1] == 2)
return "A2";
if (board[3] == 2)
return "B1";
if (board[5] == 2)
return "B3";
if (board[7] == 2)
return "C2";
return ""; // The board is full
}
public String toString()
{
return " " +
getMark(board[0]) + " | " +
getMark(board[1]) + " | " +
getMark(board[2]) +
"\n-----------\n" +
" " +
getMark(board[3]) + " | " +
getMark(board[4]) + " | " +
getMark(board[5]) +
"\n-----------\n" +
" " +
getMark(board[6]) + " | " +
getMark(board[7]) + " | " +
getMark(board[8]);
}
private String getMark(int status)
{
if (status == 3)
return "X";
if (status == 5)
return "O";
return " ";
}
}
在更新 numLosses、numDraws 和 numWins 之后,您永远不会更新 JLabel。使用
执行此操作
lblWins.setText(Integer.toString(numWins));
lblLosses.setText(Integer.toString(numLosses));
lblDraws.setText(Integer.toString(numDraws));
在适当的地方
在文件 newTicTacToe.java 中,每场比赛结束后,您都会更新变量 numWins
、numDraws
和 numLosses
.
中的计数
您也需要更新 JLabels lblWins、lblDraws 和 lblLosses。
在您的重置功能中,还添加:
lblWins.setText("Wins: " + numWins);
lblLosses.setText("Losses: " + numLosses);
lblDraws.setText("Draws: " + numDraws);
这应该可以解决您的问题。
我看到您只更新了 int 变量,numWins
、numDraws
、numLosses
。
更改变量值不会更改标签的文本。计算机如何知道您的标签 "linked" 带有变量?
正如您所说,解决方法很简单。每当您更改变量的值时,您只需要设置标签的文本。
numWins++;
lblWins.setText(Integer.toString(numWins));
"But I will forget to do this sometimes!"你喊了。这就是为什么你应该添加像这样的 "setter" 方法:
private void setNumWins(int value) {
numWins = value;
lblWins.setText(Integer.toString(value));
}
现在,您只需调用 setNumWins
,标签也会更新:
setNumWins(numWins + 1);
是不是太棒了?
有人会认为这是最简单的事情(应该是正确的),但我的 JLabel 值没有更新以反映游戏是平局、输还是赢。我启动了 3 个变量(numLosses、numDraws 和 numWins),然后在每次输、赢或平局时递增它们。但是我的计数器仍然为 0?为什么?这是代码?
NewTicTacToe.java:
package newtictactoe;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class NewTicTacToe
extends JFrame
{
public static void main(String [] args)
{
new NewTicTacToe();
}
private JButton btnA1, btnA2, btnA3, btnB1, btnB2, btnB3, btnC1, btnC2, btnC3;
private JLabel lblWins, lblLosses, lblDraws;
private TicTacToeBoard board;
private int numWins, numDraws, numLosses;
public NewTicTacToe()
{
// Set up the grid
this.numDraws = 0;
this.numWins = 0;
this.numLosses = 0;
this.setSize(800,450);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Tic-Tac-Toe");
JPanel panel1 = new JPanel();
panel1.setSize(650,450); //resolution of panel1 set to 650 by 325
panel1.setLayout(new GridLayout(3,3));
btnA1 = createButton("A1");
btnA2 = createButton("A2");
btnA3 = createButton("A3");
btnB1 = createButton("B1");
btnB2 = createButton("B2");
btnB3 = createButton("B3");
btnC1 = createButton("C1");
btnC2 = createButton("C2");
btnC3 = createButton("C3");
panel1.add(btnA1);
panel1.add(btnA2);
panel1.add(btnA3);
panel1.add(btnB1);
panel1.add(btnB2);
panel1.add(btnB3);
panel1.add(btnC1);
panel1.add(btnC2);
panel1.add(btnC3);
JPanel panel2 = new JPanel();
panel2.setLayout(new BorderLayout());
lblWins = new JLabel("Wins: " + numWins);
lblLosses = new JLabel("Losses: " + numLosses);
lblDraws = new JLabel("Draws: " + numDraws);
panel2.add(lblWins);
panel2.add(lblLosses);
panel2.add(lblDraws);
lblWins.setLocation(670, 20);
lblLosses.setLocation(670, 50);
lblDraws.setLocation(670, 80);
lblWins.setSize(100, 20);
lblLosses.setSize(100, 20);
lblDraws.setSize(100, 20);
panel2.setLayout(null);
this.add(panel1);
this.add(panel2);
this.setVisible(true);
// Start the game and create new instance of TicTacToeBoard
board = new TicTacToeBoard();
}
private JButton createButton(String square)
{
JButton btn = new JButton();
btn.setPreferredSize(new Dimension(50, 50));
Font f = new Font("Dialog", Font.PLAIN, 72);
btn.setFont(f);
btn.addActionListener(e -> btnClick(e, square));
return btn;
}
private void btnClick(ActionEvent e, String square)
{
if (board.getSquare(square) != 0)
return;
JButton btn = (JButton)e.getSource();
btn.setText("X");
board.playAt(square, 1);
if (board.isGameOver() == 3)
{
JOptionPane.showMessageDialog(null,
"It's a draw!", "Game Over",
JOptionPane.INFORMATION_MESSAGE);
numDraws++;
resetGame();
return;
}
if (board.isGameOver() == 1)
{
JOptionPane.showMessageDialog(null,
"You Win n00b!", "Game Over",
JOptionPane.INFORMATION_MESSAGE);
numWins++;
resetGame();
return;
}
String computerMove = board.getNextMove();
board.playAt(computerMove,2);
switch (computerMove)
{
case "A1":
btnA1.setText("O");
break;
case "A2":
btnA2.setText("O");
break;
case "A3":
btnA3.setText("O");
break;
case "B1":
btnB1.setText("O");
break;
case "B2":
btnB2.setText("O");
break;
case "B3":
btnB3.setText("O");
break;
case "C1":
btnC1.setText("O");
break;
case "C2":
btnC2.setText("O");
break;
case "C3":
btnC3.setText("O");
break;
}
if (board.isGameOver() == 2)
{
JOptionPane.showMessageDialog(null,
"Computer wins you big n00b!", "Game Over",
JOptionPane.INFORMATION_MESSAGE);
numLosses++;
resetGame();
return;
}
}
private void resetGame()
{
board.reset();
btnA1.setText("");
btnA2.setText("");
btnA3.setText("");
btnB1.setText("");
btnB2.setText("");
btnB3.setText("");
btnC1.setText("");
btnC2.setText("");
btnC3.setText("");
}
}
TicTacToeBoard.java:
package newtictactoe;
public class TicTacToeBoard
{
int numWins = 0;
int numLosses = 0;
int numDraws = 0;
private int board [];
private int vectors [] [] =
{
{0, 1, 2}, // Row 1
{3, 4, 5}, // Row 2
{6, 7, 8}, // Row 3
{0, 3, 6}, // Column 1
{1, 4, 7}, // Column 2
{2, 5, 8}, // Column 3
{0, 4, 8}, // Diagonal 1
{2, 4, 6} // Diagonal 2
};
public TicTacToeBoard()
{
this.reset();
}
public void reset()
{
board = new int[] {2, 2, 2, 2, 2, 2, 2, 2, 2};
}
private int getSquare(int index)
{
if (index < 0 | index > 8)
throw new IllegalArgumentException("index must be 0-9");
return board[index];
}
public int getSquare(String square)
{
int index = mapSquareToIndex(square);
if (index == -1)
throw new IllegalArgumentException("Invalid square");
switch (getSquare(index))
{
case 3:
return 1;
case 5:
return 2;
default:
return 0;
}
}
private int mapSquareToIndex(String square)
{
switch (square)
{
case "A1":
return 0;
case "A2":
return 1;
case "A3":
return 2;
case "B1":
return 3;
case "B2":
return 4;
case "B3":
return 5;
case "C1":
return 6;
case "C2":
return 7;
case "C3":
return 8;
default:
return -1;
}
}
private String mapIndexToSquare(int index)
{
switch (index)
{
case 0:
return "A1";
case 1:
return "A2";
case 2:
return "A3";
case 3:
return "B1";
case 4:
return "B2";
case 5:
return "B3";
case 6:
return "C1";
case 7:
return "C2";
case 8:
return "C3";
default:
return "";
}
}
public void playAt(String square, int player)
{
int index = mapSquareToIndex(square);
if (index == -1)
throw new IllegalArgumentException("Invalid square");
this.playAt(index, player);
}
private void playAt(int index, int player)
{
if (index < 0 | index > 8)
throw new IllegalArgumentException("Square must be 0-8");
if (player <1 | player > 2)
throw new IllegalArgumentException("Player must be 1 or 2");
if (board[index] != 2)
throw new IllegalArgumentException("Square is not empty.");
if (player == 1)
board[index] = 3;
else
board[index] = 5;
}
public int isGameOver()
{
// check for win
for (int v = 0; v < 8; v++)
{
int p = getVectorProduct(v);
if (p == 27) {
numWins++;
return 1;
} // Player 1 has won
if (p == 125) {
numLosses++;
return 2;
// Player 2 has won
}
}
// check for draw
int blankCount = 0;
for (int i = 0; i < 9; i++)
if (board[i] == 2)
blankCount++;
if (blankCount == 0) {
numDraws++;
return 3; // Game is a draw
}
return 0; // Game is not over
}
public String canPlayerWin(int player)
{
if (player <1 | player > 2)
throw new IllegalArgumentException("player must be 1 or 2");
boolean playerCanWin = false;
for (int v = 0; v < 8; v++)
{
int p = getVectorProduct(v);
if ( (player == 1 & p == 18)
| (player == 2 & p == 50) )
{
if (board[vectors[v][0]] == 2)
return mapIndexToSquare(vectors[v][0]);
if (board[vectors[v][1]] == 2)
return mapIndexToSquare(vectors[v][1]);
if (board[vectors[v][2]] == 2)
return mapIndexToSquare(vectors[v][2]);
}
}
return "";
}
private int getVectorProduct(int vector)
{
return board[vectors[vector][0]] *
board[vectors[vector][1]] *
board[vectors[vector][2]];
}
public String getNextMove()
{
String bestMove;
// Win if possible
bestMove = this.canPlayerWin(2);
if (bestMove != "")
return bestMove;
// Block if necessary
bestMove = this.canPlayerWin(1);
if (bestMove != "")
return bestMove;
// Center if it is open
if (board[4] == 2)
return "B2";
// First open corner
if (board[0] == 2)
return "A1";
if (board[2] == 2)
return "A3";
if (board[6] == 2)
return "C1";
if (board[8] == 2)
return "C3";
// First open edge
if (board[1] == 2)
return "A2";
if (board[3] == 2)
return "B1";
if (board[5] == 2)
return "B3";
if (board[7] == 2)
return "C2";
return ""; // The board is full
}
public String toString()
{
return " " +
getMark(board[0]) + " | " +
getMark(board[1]) + " | " +
getMark(board[2]) +
"\n-----------\n" +
" " +
getMark(board[3]) + " | " +
getMark(board[4]) + " | " +
getMark(board[5]) +
"\n-----------\n" +
" " +
getMark(board[6]) + " | " +
getMark(board[7]) + " | " +
getMark(board[8]);
}
private String getMark(int status)
{
if (status == 3)
return "X";
if (status == 5)
return "O";
return " ";
}
}
在更新 numLosses、numDraws 和 numWins 之后,您永远不会更新 JLabel。使用
执行此操作lblWins.setText(Integer.toString(numWins));
lblLosses.setText(Integer.toString(numLosses));
lblDraws.setText(Integer.toString(numDraws));
在适当的地方
在文件 newTicTacToe.java 中,每场比赛结束后,您都会更新变量 numWins
、numDraws
和 numLosses
.
您也需要更新 JLabels lblWins、lblDraws 和 lblLosses。
在您的重置功能中,还添加:
lblWins.setText("Wins: " + numWins);
lblLosses.setText("Losses: " + numLosses);
lblDraws.setText("Draws: " + numDraws);
这应该可以解决您的问题。
我看到您只更新了 int 变量,numWins
、numDraws
、numLosses
。
更改变量值不会更改标签的文本。计算机如何知道您的标签 "linked" 带有变量?
正如您所说,解决方法很简单。每当您更改变量的值时,您只需要设置标签的文本。
numWins++;
lblWins.setText(Integer.toString(numWins));
"But I will forget to do this sometimes!"你喊了。这就是为什么你应该添加像这样的 "setter" 方法:
private void setNumWins(int value) {
numWins = value;
lblWins.setText(Integer.toString(value));
}
现在,您只需调用 setNumWins
,标签也会更新:
setNumWins(numWins + 1);
是不是太棒了?