我正在开发我的第一个JavaFX应用程序,这是一个Tic Tac Toe游戏。除按钮外,我已经完成了所有工作。单击时按钮应调用 checkTurn() 方法和 checkState() 方法。 checkTurn() 方法会显示 X 或 O ,具体取决于 X 转向与否。 checkState() 方法,检查是否有任何玩家获胜或是否为平局,此时会显示新的舞台。
但是, checkState() 方法无法正常工作。我想知道它是否无法实例化新阶段,因此,出于调试目的,我用print语句替换了实例化,这也没有用。我得出的结论是,该方法甚至不被调用。
寻找修复我偶然发现了其他一些Tic Tac Toe程序,却发现我的方法在任何方面都没有错。我似乎无法弄清楚为什么 checkState() 方法没有被调用。
这是我的代码(按类名排列):
注意:除了Main.java之外的所有类都在一个名为" model"的文件夹中,我已经放了一个大评论,显示" checkState() "方法是,在Tiles.java中。
Main.java:
package com.frixoe;
import com.frixoe.model.Window;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage window) throws Exception {
Window gameScreen = new Window();
window.setScene(new Scene(gameScreen));
window.setTitle("Tic Tac Toe");
window.setResizable(false);
window.show();
}
}
Window.java:
package com.frixoe.model;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
public class Window extends GridPane {
private final int HEIGHT = 600;
private final int WIDTH = 600;
private Tiles tiles;
public Window() {
setPrefSize(WIDTH, HEIGHT);
setAlignment(Pos.CENTER);
this.tiles = new Tiles();
placeTiles();
}
private void placeTiles() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
Button tile = this.tiles.getTiles()[i][j];
setConstraints(tile, j, i);
getChildren().add(tile);
}
}
}
}
Tiles.java:
package com.frixoe.model;
import javafx.application.Platform;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;
public class Tiles extends StackPane {
private boolean isTurnX = true;
private Button[][] tiles = new Button[3][3];
private Font helvetica = new Font("Helvetica", 70);
public Button[][] getTiles() {
generateTiles();
return this.tiles;
}
private void generateTiles() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
Button newBtn = new Button("");
newBtn.setFont(helvetica);
newBtn.setPrefSize(600 / 3, 600 / 3);
newBtn.setOnAction(event -> {
checkTurn(newBtn);
checkState(); // <================================THIS METHOD
});
this.tiles[i][j] = newBtn;
}
}
}
private void checkState() {
if (hasWon("X")) {
new AlertBox("Yay! Player X has Won!", "X Won!");
} else if (hasWon("O")) {
new AlertBox("Yay! Player O has Won!", "O Won!");
} else if (isFull()) {
new AlertBox("It's a draw!", "Draw!");
}
}
private boolean isFull() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (this.tiles[i][j].getText().equalsIgnoreCase("")) {
return false;
}
}
}
return true;
}
private boolean hasWon(String player) {
for (int i = 0; i < 3; i++) {
if (tiles[i][0].getText().equalsIgnoreCase(player)
&& tiles[i][1].getText().equalsIgnoreCase(player)
&& tiles[i][2].getText().equalsIgnoreCase(player)) {
return true;
}
}
for (int i = 0; i < 3; i++) {
if (tiles[0][i].getText().equalsIgnoreCase(player)
&& tiles[1][i].getText().equalsIgnoreCase(player)
&& tiles[2][i].getText().equalsIgnoreCase(player)) {
return true;
}
}
return tiles[0][0].getText().equalsIgnoreCase(player)
&& tiles[1][1].getText().equalsIgnoreCase(player)
&& tiles[2][2].getText().equalsIgnoreCase(player);
}
private void checkTurn(Button btn) {
if (isTurnX) {
drawO(btn);
isTurnX = false;
} else {
drawX(btn);
isTurnX = true;
}
}
private void drawX(Button btn) {
btn.setText("X");
}
private void drawO(Button btn) {
btn.setText("O");
}
}
另一个注意事项:AlertBox类是玩家获胜或抽签时显示的另一个阶段。
感谢您的帮助!
JDK:jdk1.8.0_121
系统:Windows 10 32位。
IDE:IntelliJ IDEA 2016.3.3
答案 0 :(得分:3)
请注意,每次调用getTiles
时都会重新生成磁贴,因此每个按钮有9个副本。这意味着虽然每个按钮都可以设置它自己的文本,但它们都“仅”看到最后一组九个按钮(由最后一次调用getTiles
创建)。
确保您只创建一次瓷砖 - 通过在Tiles
的构造函数中生成它们,或者在调用generateTiles
中的getTiles
之前检查它们是否已经初始化。