package Recursive;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
public class Exercise18_26 extends Application {
private ArrayList<Point2D> list = new ArrayList<>(); //存放坐标列表
private Pane[][] panes = new Pane[8][8]; //坐标点面板
private Button findPath = new Button("Find Path"); //按钮
private Button clearPath = new Button("Clear Path");
private Timeline animation; //动画
private String orientation = ""; //开始方向(左上角-右下角)
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
GridPane gridPane = getCenterPane();
HBox hBox = new HBox(10, findPath, clearPath);
hBox.setAlignment(Pos.CENTER);
findPath.setCursor(Cursor.HAND); //按钮设置手势指针
clearPath.setCursor(Cursor.HAND);
findPath.setOnAction(event -> { //按钮注册动作事件
animation = new Timeline(new KeyFrame(Duration.millis(100), event1 -> animationPath())); //创建动画
animation.setCycleCount(Timeline.INDEFINITE); //无限循环次数
animation.play(); //动画播放
});
clearPath.setOnAction(event -> {
list.clear(); //清空存放坐标列表
orientation = ""; //重置开始方向
if (animation != null) //停止动画
animation.stop();
for (Node node : gridPane.getChildren()) //坐标点面板重新添加矩形
if (node instanceof Pane) { //如果结点是Pane的实例
((Pane)node).getChildren().clear(); //清空面板
Rectangle rectangle = new Rectangle(50, 50); //创建矩形并加入面板
rectangle.setStyle("-fx-stroke: lightgrey; -fx-fill: white;"); //矩形设置样式(浅灰色画线,白色填充)
((Pane)node).getChildren().add(rectangle);
}
});
BorderPane pane = new BorderPane(gridPane);
pane.setTop(new StackPane(new Label("path found")));
pane.setBottom(hBox);
pane.getCenter().setStyle("-fx-padding: 2px 0 5px 0;");
Scene scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.setTitle("Exercise18_26");
primaryStage.show();
}
/** 返回网格面板 */
private GridPane getCenterPane() {
GridPane gridPane = new GridPane();
gridPane.setGridLinesVisible(true); //设置网格线可见
//网格面板添加坐标点面板
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
Rectangle rectangle = new Rectangle(50, 50);
rectangle.setStyle("-fx-stroke: lightgrey; -fx-fill: white;");
Pane pane = new Pane(rectangle);
pane.setPrefSize(50, 50);
pane.setCursor(Cursor.HAND);
pane.setOnMouseClicked(event -> { //坐标点面板注册鼠标点击事件(添加x线进入面板)
Line line1 = new Line(0, 0, 0, 0);
Line line2 = new Line(0, 0, 0, 0);
line1.endYProperty().bind(pane.heightProperty());
line1.endXProperty().bind(pane.widthProperty());
line2.startXProperty().bind(pane.widthProperty());
line2.endYProperty().bind(pane.heightProperty());
pane.getChildren().addAll(line1, line2);
});
panes[i][j] = pane;
gridPane.add(pane, j, i);
}
}
return gridPane;
}
/** 点在存放坐标列表中? */
private boolean isInList(ArrayList<Point2D> list, Point2D point2D) {
for (Point2D p : list)
if (p.equals(point2D))
return true;
return false;
}
/** 设置随机开始方向 */
private void setRandomOrientation() {
if (orientation.equals(""))
orientation = (Math.random() > 0.4) ? "rightDown" : "leftUp";
}
/** 动画关键帧处理器 */
private void animationPath() {
int x, y; //x, y坐标
setRandomOrientation(); //设置开始方向
if (orientation.equals("leftUp")) { //从左上角开始
if (list.size() == 0) { //第一个点
list.add(new Point2D(0, 0));
for (Node node : panes[0][0].getChildren()) //设置矩形颜色为灰色
if (node instanceof Rectangle) {
((Rectangle)node).setFill(Color.GREY);
break;
}
} else { //除第一个点外的点
Point2D lastPoint = list.get(list.size() - 1); //获取上个移动坐标点
if (Math.random() > 0.4) { //垂直方向变化
x = (Math.random() > 0.4) ? (int)lastPoint.getX()+1 : (int)lastPoint.getX()-1;
y = (int)lastPoint.getY();
} else { //水平方向变化
x = (int)lastPoint.getX();
y = (Math.random() > 0.4) ? (int)lastPoint.getY()+1 : (int)lastPoint.getY();
}
if ((0 <= x && x <= 7) && (0 <= y && y <= 7)) //如果坐标在范围内
if (!isInList(list, new Point2D(x, y)) && panes[x][y].getChildren().size() == 1) { //如果坐标不在坐标列表中且坐标面板未放标志
for (Node node : panes[x][y].getChildren())
if (node instanceof Rectangle) { //设置矩形颜色
((Rectangle)node).setFill(Color.GREY);
break;
}
list.add(new Point2D(x, y));
if (x == panes.length-1 && y == panes.length-1)
animation.stop(); //到达右下角时停止动画
}
}
} else { //从右下角开始
if (list.size() == 0) {
list.add(new Point2D(panes.length-1, panes.length-1));
for (Node node : panes[7][7].getChildren())
if (node instanceof Rectangle) {
((Rectangle)node).setFill(Color.GREY);
break;
}
} else {
Point2D lastPoint = list.get(list.size() - 1);
if (Math.random() > 0.4) {
x = (Math.random() > 0.4) ? (int)lastPoint.getX()+1 : (int)lastPoint.getX()-1;
y = (int)lastPoint.getY();
} else {
x = (int)lastPoint.getX();
y = (Math.random() > 0.4) ? (int)lastPoint.getY()-1 : (int)lastPoint.getY();
}
if ((0 <= x && x <= 7) && (0 <= y && y <= 7))
if (!isInList(list, new Point2D(x, y)) && panes[x][y].getChildren().size() == 1) {
for (Node node : panes[x][y].getChildren())
if (node instanceof Rectangle) {
((Rectangle)node).setFill(Color.GREY);
break;
}
list.add(new Point2D(x, y));
if (x == 0 && y == 0)
animation.stop();
}
}
}
}
}
JavaFX、创建一个迷宫
这是一个使用JavaFX编写的程序,展示了从左上角到右下角或从右下角到左上角的随机路径搜索动画。程序包含一个8x8的网格,每个格子是一个可点击的 Pane 对象,点击后会添加线条作为路径标记。用户可以点击 'FindPath' 按钮开始动画,'ClearPath' 按钮则清除路径。动画过程中,矩形格子会根据路径变化颜色,模拟路径搜索过程。
摘要由CSDN通过智能技术生成