gpt4 book ai didi

Java TicTacToe 程序在非获胜组合时触发

转载 作者:行者123 更新时间:2023-12-02 12:09:34 26 4
gpt4 key购买 nike

我几年前制作了一个 GUI TicTacToe 游戏,并想重做它,因为我现在有了更多的编程技能。我能够将代码从 600 行缩减到大约 150 行。

当我使用相同的方案时,我遇到了一些我无法解决的问题,所以请帮助我。

程序由两个类组成,主类TTTMain:

public class TTTMain {

public static void main(String[] args) {
TTTFrame tttf = new TTTFrame(0,0);

/*Tic Tac Toe Field:
* 0 1 2
* 3 4 5
* 6 7 8
*/

}}

TTTFrame:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TTTFrame extends JFrame implements ActionListener {

private Button[] btnPlayButton;
private Button btnRestart;
private int buttonCounter;
private int xScore;
private int oScore;
private Label Olabel, Xlabel;

TTTFrame(int xScore, int oScore) {

this.xScore = xScore;
this.oScore = oScore;

btnPlayButton = new Button[9];
for (int i = 0; i < 9; i++) {
btnPlayButton[i] = new Button("" + i);
btnPlayButton[i].setBackground(Color.white);
btnPlayButton[i].setForeground(Color.white);
btnPlayButton[i].addActionListener(this);
this.add(btnPlayButton[i]);
}

Xlabel = new Label("X: " + this.xScore);
Xlabel.setFont(new Font("Arial", Font.BOLD, 24));
Xlabel.setForeground(Color.white);
Xlabel.setBackground(Color.black);
this.add(Xlabel);

btnRestart = new Button("Restart");
btnRestart.setActionCommand("Restart");
btnRestart.setFont(new Font("Arial", Font.PLAIN, 18));
btnRestart.addActionListener(this);
this.add(btnRestart);

Olabel = new Label("O: " + this.oScore);
Olabel.setFont(new Font("Arial", Font.BOLD, 24));
Olabel.setForeground(Color.white);
Olabel.setBackground(Color.black);
this.add(Olabel);

this.setLayout(new GridLayout(4, 3));
this.pack();
this.setResizable(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Tic Tac Toe");
this.setSize(300, 400);
this.getContentPane().setBackground(Color.black);
this.setVisible(true);
}

@Override
public void actionPerformed(ActionEvent e) {

if (e.getActionCommand().equals("Restart")) {
System.out.println("Restarted");
for (int i = 0; i < 9; i++) {

btnPlayButton[i].setLabel("" + i);
btnPlayButton[i].setForeground(Color.white);
btnPlayButton[i].setBackground(Color.white);
btnPlayButton[i].addActionListener(this);

this.buttonCounter = 0;
}
} else {

((Button) e.getSource()).setFont(new Font("Arial", Font.BOLD, 48));
((Button) e.getSource()).setForeground(Color.black);
System.out.println(buttonCounter);
if (buttonCounter % 2 == 0) {
((Button) e.getSource()).setLabel("X");
((Button) e.getSource()).removeActionListener(this);
} else {
((Button) e.getSource()).setLabel("O");
((Button) e.getSource()).removeActionListener(this);
}
buttonCounter++;
CheckField();
}

}

private void CheckField() {

if (ButtonsWithIdenticalLabels(0, 1, 2)) {

Deactivatebuttons();
}
if (ButtonsWithIdenticalLabels(3, 4, 5)) {

Deactivatebuttons();
}
if (ButtonsWithIdenticalLabels(6, 7, 8)) {

Deactivatebuttons();
}
if (ButtonsWithIdenticalLabels(0, 3, 6)) {

Deactivatebuttons();
}
if (ButtonsWithIdenticalLabels(1, 4, 7)) {

Deactivatebuttons();
}
if (ButtonsWithIdenticalLabels(2, 5, 8)) {

Deactivatebuttons();
}
if (ButtonsWithIdenticalLabels(0, 4, 8)) {

Deactivatebuttons();
}
if (ButtonsWithIdenticalLabels(2, 4, 6)) {

Deactivatebuttons();
}
}

private boolean ButtonsWithIdenticalLabels(int i, int j, int k) {
if (btnPlayButton[i].getLabel() == btnPlayButton[j].getLabel()
&& btnPlayButton[j].getLabel() == btnPlayButton[k].getLabel()) {

btnPlayButton[i].setBackground(Color.red);
btnPlayButton[j].setBackground(Color.red);
btnPlayButton[k].setBackground(Color.red);

if (btnPlayButton[i].getLabel().equals("X")) {
xScore++;
Xlabel.setText("X: " + xScore);
} else {
oScore++;
Olabel.setText("O: " + oScore);
}

return true;
} else {
return false;
}
}

private void Deactivatebuttons() {
for (int i = 0; i < 9; i++) {
btnPlayButton[i].removeActionListener(this);
}
}
}

现在让我解释一下该程序是如何工作的。 3x3 比赛 field 由 ButtonArray btnPlayButton 组成。这些按钮通过其标签进行比较,因此为了在游戏开始时没有匹配的标签,按钮在创建时就被标记为 1 到 9。这里:

for (int i = 0; i < 9; i++) {
btnPlayButton[i] = new Button("" + i); // Right here
btnPlayButton[i].setBackground(Color.white);
btnPlayButton[i].setForeground(Color.white);
btnPlayButton[i].addActionListener(this);
this.add(btnPlayButton[i]);
}

每当您单击 btnPlayButton 时,程序都会跳转到 actionPerformed 方法。由于 btnPlayButtons 没有 ActionCommand ,它会直接跳转到该方法的 else 部分。这里,int buttonCounter 增加了 1。无论 buttonCounter 是偶数还是奇数,被点击的 btnPlayButton 都会被重新标记为“X”或“O”。由于每次点击 buttonCounter 都会+1,因此 X 和 Os 是交替的。

这里是所说的部分:

else {

((Button) e.getSource()).setFont(new Font("Arial", Font.BOLD, 48));
((Button) e.getSource()).setForeground(Color.black);
System.out.println(buttonCounter);
if (buttonCounter % 2 == 0) {
((Button) e.getSource()).setLabel("X");
((Button) e.getSource()).removeActionListener(this);
} else {
((Button) e.getSource()).setLabel("O");
((Button) e.getSource()).removeActionListener(this);
}
buttonCounter++;
CheckField();
}

被点击按钮的ActionListener被删除以防止作弊。每按一次按钮,就会检查比赛 field 是否有获胜组合。这发生在 CheckField() 中。

CheckField() 中,或者更准确地说,在 ButtonsWithIdenticalLabels(x, y, z) 中,btnPlayButtons[x] 的标签、btnPlayButtons[y]btnPlayButtons[z] 被获取并比较,如果它们相同则返回 true。

由于 btnPlayButton 的顺序如下:

0 1 2
3 4 5
6 7 8

获胜组合是:012,345,678,036,147,258,045和246

例如,当 btnPlayButton[0]btnPlayButton[1]btnPlayButton[2] 都具有相同的标签时。 ButtonsWithIdenticalLabels 为 true,程序跳转到 Deactivatebuttons(),其中所有 btnPlayButton 都被禁用,这意味着找到了获胜组合,游戏结束。如果 btnPlayButton[1] 的标签是“X”,则 int xScore 会添加 1。此外,为了美观,btnPlayButton[0]btnPlayButton[1]btnPlayButton[2] 被漆成红色。

使用“重新启动”按钮,您会跳入 for 循环,再次重新标记 btnPlayButton 并将它们添加到 TTTFrame 中实现的 ActionListener 中。 buttonCounter 也被重置为 0。重新标记与类开头的标记相同:

if (e.getActionCommand().equals("Restart")) {
System.out.println("Restarted");
for (int i = 0; i < 9; i++) {

btnPlayButton[i].setLabel("" + i);
btnPlayButton[i].setForeground(Color.white);
btnPlayButton[i].setBackground(Color.white);
btnPlayButton[i].addActionListener(this);

this.buttonCounter = 0;
}

现在的问题是,在几次重新启动后,X 和 O 的标签不再交替。有时连续 3 个 O,有时甚至像这样的 Field 也被认为是胜利

Picture

如果有人知道如何修复这个错误,我会非常高兴。

提前致谢,

菲赫迪

最佳答案

这里的问题是:当您重新启动游戏时,一个新的 ActionListener 会添加到每个按钮。但是,只有当您单击它或有人赢得游戏时,它才会被删除。这意味着当您在任何人获胜之前重新启动游戏时,每个未单击的按钮都会获得第二个 ActionListener,因此单击将被注册两次并出现此错误。在重置面板之前尝试调用 DeactivateButtons()

关于Java TicTacToe 程序在非获胜组合时触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46642721/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com