【发布时间】:2020-06-15 10:42:14
【问题描述】:
我会尽力解释我的问题。我总是很高兴找到可以帮助我改善和摆脱困境的有耐心的人。 基本上我正在尝试构建一个 javafx tic-tac-toe 游戏,因为我觉得即使是这样简单的事情我也可以学习。
所以我有一个主 App.java 文件来启动程序,并有一些方法可以正确设置我想要使用的 fxml 文件并对其进行更改。这样,如果将来我想为玩家添加个人资料或在本地玩单人 vs AI 或两个玩家的可能性,我可以轻松创建另一个 fxml 文件来处理其他场景。
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
/**
* JavaFX App
*/
public class App extends Application {
private static Scene scene;
@Override
public void start(Stage stage) throws IOException {
scene = new Scene(loadFXML("primary"));
stage.setScene(scene);
stage.show();
}
static void setRoot(String fxml) throws IOException {
scene.setRoot(loadFXML(fxml));
}
private static Parent loadFXML(String fxml) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml"));
return fxmlLoader.load();
}
public static void main(String[] args) {
launch();
}
}
然后我有一个 PrimaryController.java 文件,它基本上想用来用节点填充场景。该结构是一个内部带有 GridPane 的 AnchorPane,我通过代码填充 GridPane,方法是向其中添加 MyPanes 元素,这些元素是 StackPanes 的一些修改。 这里是控制器:
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.GridPane;
public class PrimaryController implements Initializable {
@FXML
public GridPane grid;
@Override
public void initialize(URL location, ResourceBundle resources) {
for (int i = 0; i<3; i++){
for (int j = 0; j <3;j++){
MyTiles tile = new MyTiles();
grid.add(tile,j,i);
}
}
}
}
这里是 MyTile 类
import javafx.geometry.Pos;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
public class MyTiles extends StackPane {
private static boolean turnOne = true;
private Text text = new Text(" ");
public MyTiles(){
setPrefSize(200,200);
Rectangle rectangle = new Rectangle(200,200);
rectangle.setFill(null);
rectangle.setStroke(Color.BLACK);
text.setFont(Font.font(72));
setAlignment(Pos.CENTER);
getChildren().addAll(rectangle,text);
setOnMouseClicked(event -> {
if (text.getText().equals(" ")){
if (turnOne){
drawX(text);
turnOne = false;
}else if (!turnOne){
drawY(text);
turnOne = true;
}
}else{
return;
}
});
}
public String getTheText(){
return text.getText();
}
private void drawX(Text text){
text.setStroke(Color.BLUE);
text.setFill(Color.LIGHTBLUE);
text.setText("x");
}
private void drawY(Text text){
text.setStroke(Color.RED);
text.setFill(Color.PINK);
text.setText("o");
}
}
现在的问题是:你知道我可以检查是否获胜的方法吗?我的意思是我知道当一名球员获胜时背后的逻辑,但在我的脑海中我必须: - 访问 GridPane 中的所有 MyTiles 对象 - 检查他们的文字是什么 - 检查是否有获胜组合。
我不知道如何做到这一点,有人能给我一些提示、建议、示例吗?
也许在单独的文件中做事的策略不是最好的,但我想试试是否有办法不把所有东西都放在主 App.java 文件中。
非常感谢任何帮助。我希望这个问题足够清楚! 再次感谢!
【问题讨论】:
-
一般来说,您将 buiness-logic 从您的视图中分离出来。您需要编写一个类,它允许您在没有 gui 的情况下自行玩游戏。 gui 只是内部游戏状态的表示。在您的游戏类中,例如使用 2D 数组。编写然后检查获胜状态的代码很容易。将功能检查分开,例如一个检查列,一个检查行,一个检查对角线。
-
我不明白的是:我基本上每次用户点击时都会更改磁贴内的文本。我不知道如何将这些文本放在一个数组中,这样我就可以检查获胜的罢工。我可以毫无问题地做命令行中的事情,当涉及 gui 元素时我会遇到麻烦。
-
作为一个快速破解,您可以将
MyTiles对象(顺便说一下,类的名称实际上应该是MyTile,因为每个实例代表一个图块)存储在控制器的数组中班级。但是,正如@Westranger 所建议的那样,使用 MVC 方法会更好,并将游戏的状态移动到一个单独的类中。 -
感谢两位的帮助。我真的很感激
标签: java javafx tic-tac-toe