我有一些代码可以自我避免随机游走:
package event_handling;
import java.util.ArrayList;
import java.util.Random;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class SelfAvoidingRandomWalk extends Application {
int latticeSize;
int scale;
double initialX, initialY;
double currentX, currentY;
ArrayList<Line> lines;
ArrayList<String> moveDirections;
String chosenDirection;
Pane pane;
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Random random = new Random();
pane = new Pane();
Button start = new Button("Start");
latticeSize = 16;
scale = 30;
initialX = latticeSize * scale / 2;
initialY = latticeSize * scale / 2;
currentX = initialX;
currentY = initialY;
lines = new ArrayList<>();
moveDirections = new ArrayList<>();
chosenDirection = "";
Line[] horizontalGridLines = new Line[latticeSize + 1];
Line[] verticalGridLines = new Line[latticeSize + 1];
//Draw gridlines
for (int a = 0; a < latticeSize + 1; a++) {
Line l = new Line(0, a * scale, latticeSize * scale, a * scale);
l.setStroke(Color.LIGHTGRAY);
horizontalGridLines[a] = l;
}
for (int a = 0; a < latticeSize + 1; a++) {
Line l = new Line(a * scale, 0, a * scale, latticeSize * scale);
l.setStroke(Color.LIGHTGRAY);
verticalGridLines[a] = l;
}
pane.getChildren().addAll(horizontalGridLines);
pane.getChildren().addAll(verticalGridLines);
BorderPane bPane = new BorderPane();
bPane.setCenter(pane);
bPane.setBottom(start);
BorderPane.setAlignment(start, Pos.CENTER);
start.setOnMouseClicked(e -> {
pane.getChildren().removeAll(lines);
lines.clear();
initialX = latticeSize * scale / 2;
initialY = latticeSize * scale / 2;
currentX = initialX;
currentY = initialY;
while (noNodeTouchesBorders() && validMoveExists()) {
//Check which directions are empty
buildValidMovesList();
//Choose from the available directions
chosenDirection = moveDirections.get(random.nextInt(moveDirections.size()));
//Make the move
makeMove();
//Reset list of possible moves
moveDirections = new ArrayList<>();
}
System.out.println("Finished walk.");
if (noNodeTouchesBorders()) {
System.out.println("Dead end.");
} else {
System.out.println("Reached exit.");
}
});
Scene scene = new Scene(bPane, latticeSize * scale, latticeSize * scale + 30);
primaryStage.setTitle("Self-avoiding Random Walk");
primaryStage.setScene(scene);
primaryStage.show();
}
private boolean noNodeTouchesBorders() {
if (currentX == 0 || currentY == 0 || currentX == latticeSize * scale || currentY == latticeSize * scale) {
return false;
}
return true;
}
private boolean validMoveExists() {
//We have coordinates, and need to check if there are existing lines in the relevant ArrayList with the same endpoint/startpoint.
boolean blocksUp = false;
boolean blocksDown = false;
boolean blocksLeft = false;
boolean blocksRight = false;
//For each line,
for (Line l : lines) {
//Check if this line blocks in some direction
if (blocksUp(l)) {
blocksUp = true;
}
if (blocksDown(l)) {
blocksDown = true;
}
if (blocksLeft(l)) {
blocksLeft = true;
}
if (blocksRight(l)) {
blocksRight = true;
}
}
if (blocksUp && blocksDown && blocksLeft && blocksRight) {
return false;
}
return true;
}
private boolean blocksUp(Line l) {
if ((l.getStartX() == currentX && l.getStartY() == currentY - scale) || (l.getEndX() == currentX && l.getEndY() == currentY - scale)) {
return true;
}
return false;
}
private boolean blocksDown(Line l) {
if ((l.getStartX() == currentX && l.getStartY() == currentY + scale) || (l.getEndX() == currentX && l.getEndY() == currentY + scale)) {
return true;
}
return false;
}
private boolean blocksLeft(Line l) {
if ((l.getStartX() == currentX - scale && l.getStartY() == currentY) || (l.getEndX() == currentX - scale && l.getEndY() == currentY)) {
return true;
}
return false;
}
private boolean blocksRight(Line l) {
if ((l.getStartX() == currentX + scale && l.getStartY() == currentY) || (l.getEndX() == currentX + scale && l.getEndY() == currentY)) {
return true;
}
return false;
}
private void buildValidMovesList() {
moveDirections.add("Up");
moveDirections.add("Down");
moveDirections.add("Left");
moveDirections.add("Right");
for (Line l : lines) {
if (blocksUp(l)) {
moveDirections.remove("Up");
}
if (blocksDown(l)) {
moveDirections.remove("Down");
}
if (blocksLeft(l)) {
moveDirections.remove("Left");
}
if (blocksRight(l)) {
moveDirections.remove("Right");
}
}
}
private void makeMove() {
switch (chosenDirection) {
case "Up" : moveUp(); break;
case "Down" : moveDown(); break;
case "Left" : moveLeft(); break;
case "Right" : moveRight(); break;
}
}
private void moveUp() {
//Create new line
Line l = new Line(currentX, currentY, currentX, currentY - scale);
//Add a new line to the lines ArrayList
lines.add(l);
//Add the new line to the pane
pane.getChildren().add(l);
//Set new currentY
currentY = currentY - scale;
System.out.println("Went up.");
}
private void moveDown() {
//Create new line
Line l = new Line(currentX, currentY, currentX, currentY + scale);
//Add a new line to the lines ArrayList
lines.add(l);
//Add the new line to the pane
pane.getChildren().add(l);
//Set new currentY
currentY = currentY + scale;
System.out.println("Went down.");
}
private void moveLeft() {
//Create new line
Line l = new Line(currentX, currentY, currentX - scale, currentY);
//Add a new line to the lines ArrayList
lines.add(l);
//Add the new line to the pane
pane.getChildren().add(l);
//Set new currentX
currentX = currentX - scale;
System.out.println("Went left.");
}
private void moveRight() {
//Create new line
Line l = new Line(currentX, currentY, currentX + scale, currentY);
//Add a new line to the lines ArrayList
lines.add(l);
//Add the new line to the pane
pane.getChildren().add(l);
//Set new currentX
currentX = currentX + scale;
System.out.println("Went right.");
}
}
目前,每次单击“开始”按钮时,都会进行一次模拟。一个完整的程序运行,可以这么说。
我的任务是为该程序制作动画。所以我想在自己的框架中显示每条画线。
我不确定该怎么做。我试过并搞砸了代码。我知道我应该使用KeyFrames和事件处理程序......不知何故。 (之前我做过简单的动画,但代码并不复杂。没有必要踩踏,或者我正在使用现有的转换。)
我认为我的代码有点弱,因为逻辑与UI一起。实现动画时不确定这是否重要。
你能指导我如何解决这个问题吗?