我在MazeUI类中有一些代码,它在JavaFX中创建了几个字段,用于输入要生成的迷宫的高度和宽度以及按钮和按钮的事件。单击Generate Maze时,代码应生成随机迷宫。
现在这很好用。但是在使用gc.clearRect(x,y,z,a)首次绘制迷宫之后清除画布的线似乎不起作用,并且在随后的点击中将迷宫重新绘制在彼此之上:
package dojo.maze.ui;
import dojo.maze.generator.MazeGenerator;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.effect.BoxBlur;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.shape.StrokeLineJoin;
import javafx.stage.Stage;
public class MazeUI extends Application {
private MazeGenerator generator;
private Integer height = 15;
private Integer width = 15;
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Dojo: Solving a Maze");
Group root = new Group();
drawMazeView(root);
primaryStage.setScene(new Scene(root, Color.WHITE));
primaryStage.show();
}
private GraphicsContext initialiseGraphicsContext(Canvas canvas) {
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.BLACK);
gc.fillRect(0,0,600,600);
gc.setStroke(Color.GREEN);
gc.setLineCap( StrokeLineCap.ROUND );
gc.setLineJoin( StrokeLineJoin.ROUND );
gc.setLineWidth(3);
BoxBlur blur = new BoxBlur();
blur.setWidth(1);
blur.setHeight(1);
blur.setIterations(1);
gc.setEffect(blur);
return gc;
}
private void drawMazeView(Group root) {
Canvas canvas = new Canvas(800, 800);
GraphicsContext gc = initialiseGraphicsContext(canvas);
GridPane.setConstraints(canvas, 0, 6);
GridPane grid = new GridPane();
grid.setPadding(new Insets(10, 10, 10, 10));
grid.setVgap(5);
grid.setHgap(5);
Label heightLabel = new Label("Height:");
final TextField heightTextField = new TextField();
HBox hbHeight = new HBox();
hbHeight.getChildren().addAll(heightLabel, heightTextField);
hbHeight.setSpacing(10);
GridPane.setConstraints(hbHeight, 0, 0);
Label widthLabel = new Label("Label:");
final TextField widthTextField = new TextField();
HBox hbWidth = new HBox();
hbWidth.getChildren().addAll(widthLabel, widthTextField);
hbWidth.setSpacing(10);
GridPane.setConstraints(hbWidth, 0, 2);
VBox fieldsBox = new VBox();
fieldsBox.getChildren().addAll(hbHeight, hbWidth);
// Create button that allows you to generate a new maze
Button btn = new Button();
btn.setText("Generate Random Maze");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Button clicked!");
height = Integer.valueOf(heightTextField.getText());
width = Integer.valueOf(widthTextField.getText());
// clear old maze
gc.clearRect(0, 0,
canvas.getHeight(),
canvas.getWidth());
generator = new MazeGenerator(height, width);
drawMaze(gc);
}
});
GridPane.setConstraints(btn, 0, 4);
grid.getChildren().addAll(fieldsBox, btn, canvas);
root.getChildren().add(grid);
}
void drawMaze(GraphicsContext gc) {
int[][] maze = generator.maze();
int xPos = 20,
yPos = 20,
length = 40,
gap = 10;
for (int i = 0; i < width; i++) {
xPos = 20;
// draw the north edge
for (int j = 0; j < height; j++) {
if ((maze[j][i] & 1) == 0) {
gc.strokeLine(xPos, yPos, xPos + length, yPos); // horizontal
}
xPos += length + gap;
System.out.print((maze[j][i] & 1) == 0 ? "+---" : "+ ");
}
System.out.println("+");
xPos = 20;
// draw the west edge
for (int j = 0; j < height; j++) {
if ((maze[j][i] & 8) == 0) {
gc.strokeLine(xPos, yPos, xPos, yPos + length); // vertical
}
xPos += length + gap;
System.out.print((maze[j][i] & 8) == 0 ? "| " : " ");
}
gc.strokeLine(xPos, yPos, xPos, yPos + length); // vertical
System.out.println("|");
yPos += length + gap;
}
// draw the bottom line
xPos = 20; // reset x pos to western edge
for (int j = 0; j < height; j++) {
gc.strokeLine(xPos, yPos, xPos + length, yPos); // horizontal
System.out.print("+---");
xPos += length + gap;
}
System.out.println("+");
}
public static void main(String[] args) {
launch(args);
}
}
MazeGenerator代码:
package dojo.maze.generator;
import java.util.Arrays;
import java.util.Collections;
/*
* recursive backtracking algorithm
* shamelessly borrowed from the ruby at
* http://weblog.jamisbuck.org/2010/12/27/maze-generation-recursive-backtracking
*/
public class MazeGenerator {
private final int x;
private final int y;
private final int[][] maze;
public static final int[][] mazeProblemOne = new int[][] {{2,5,2,3,7,3,1,6,7,3,3,5,6,3,5},{4,10,3,5,12,6,3,9,10,3,5,12,8,6,13},{12,6,5,12,12,14,3,1,6,3,9,10,3,9,12},{12,12,12,12,12,12,6,3,9,4,6,7,1,6,9},{14,9,10,9,12,12,12,6,5,12,12,10,5,12,4},{12,2,7,5,12,12,10,9,12,10,13,4,10,9,12},{12,6,9,12,12,12,2,5,10,5,10,11,3,3,13},{12,10,5,12,10,11,3,13,4,10,5,6,3,1,12},{12,6,9,10,5,4,6,9,12,6,9,12,6,3,9},{10,9,6,1,12,10,11,3,9,12,6,13,12,2,5},{6,7,9,6,9,6,3,3,3,9,8,12,12,6,13},{8,12,6,9,6,13,6,3,7,3,3,13,12,12,12},{6,9,10,5,12,12,12,4,10,3,5,8,12,12,8},{14,3,5,12,8,12,10,11,3,5,10,5,12,10,5},{10,1,10,11,3,9,2,3,3,11,1,10,11,3,9}};
public static final int[][] mazeProblemTwo = new int[][] {{2,5,6,5,6,3,1,6,3,3,7,5,2,3,5},{4,10,9,12,14,3,3,9,6,5,12,10,3,3,9},{14,3,3,9,8,6,3,5,12,12,10,3,3,3,5},{12,6,3,3,5,12,4,10,9,10,3,3,3,3,13},{12,12,6,5,12,12,10,3,3,3,5,6,3,3,9},{12,10,9,12,10,9,6,5,6,3,13,10,3,3,5},{10,3,5,12,6,5,12,10,9,4,14,3,3,1,12},{4,6,9,12,12,10,9,6,3,11,13,6,3,3,9},{12,12,2,13,14,3,5,8,6,5,8,10,3,3,5},{12,10,3,9,12,4,12,6,9,12,6,5,6,3,9},{14,7,3,1,10,13,12,12,4,12,12,10,9,6,1},{12,10,3,7,1,12,10,11,9,12,12,2,3,11,5},{12,2,5,12,6,9,2,5,6,9,10,3,3,5,12},{10,5,12,12,12,6,3,13,12,6,7,1,6,9,12},{2,11,9,10,11,9,2,9,10,9,10,3,11,3,9}};
public static final int[][] mazeProblemThree = new int[][] {{2,5,2,3,7,3,3,3,5,6,3,1,6,7,1},{4,10,3,5,12,2,5,6,9,10,3,3,9,14,5},{10,7,5,12,10,5,14,9,6,5,6,3,5,12,12},{6,9,8,10,3,9,12,6,13,12,10,5,12,12,12},{12,6,3,7,1,6,9,12,12,10,3,9,12,8,12},{12,12,4,10,5,10,5,8,14,3,5,2,11,3,13},{12,10,13,4,10,5,10,5,10,5,10,5,6,5,12},{14,1,12,10,5,14,1,12,6,9,4,10,9,12,12},{14,5,10,5,12,10,5,12,12,2,15,3,1,12,12},{8,12,6,9,10,5,12,12,10,3,9,6,3,9,12},{6,9,14,3,3,9,12,10,3,3,3,9,4,6,9},{10,5,12,6,3,3,13,6,3,3,1,6,11,9,4},{6,9,12,10,5,6,11,9,6,3,3,9,6,3,13},{14,5,12,4,12,10,1,6,9,6,5,2,13,4,12},{8,10,11,9,10,3,3,11,3,9,10,3,9,10,9}};
public static final int[][] mazeProblemFour = new int[][] {{2,3,3,5,4,6,7,3,3,5,6,5,6,3,5},{6,3,1,12,12,12,10,3,5,10,9,12,10,5,12},{12,6,3,9,14,9,4,6,9,2,3,11,1,12,12},{14,9,2,3,11,5,12,10,3,5,6,3,3,9,12},{10,5,6,5,2,11,11,5,4,12,12,6,7,1,12},{4,10,9,10,3,5,6,9,12,10,9,8,12,6,13},{14,5,4,6,3,9,12,6,11,5,6,3,9,12,8},{12,10,9,12,4,6,9,10,5,12,14,3,5,10,5},{12,6,5,12,12,12,6,3,9,12,8,6,13,4,12},{14,9,10,9,12,12,10,3,5,10,5,12,10,13,12},{12,2,7,5,10,11,3,3,9,6,9,12,2,9,12},{10,3,9,10,3,3,5,4,6,11,3,9,6,3,13},{6,5,6,7,3,5,12,10,9,6,3,3,9,6,9},{12,10,9,10,5,8,12,6,5,10,5,6,5,10,5},{10,3,3,1,10,3,11,9,10,3,9,8,10,3,9}};
public static final int[][] mazeProblemFive = new int[][] {{2,3,5,6,3,3,7,5,6,3,3,3,7,3,5},{6,5,12,12,6,3,9,8,10,5,4,6,9,4,12},{12,12,12,12,10,3,5,6,5,10,13,10,5,14,9},{12,10,9,10,5,4,10,9,14,1,12,4,12,10,5},{10,5,6,5,10,15,3,1,14,5,14,9,10,5,8},{6,9,12,10,5,8,6,5,8,10,9,6,5,14,5},{10,3,9,4,12,6,9,10,3,3,3,9,12,8,12},{6,3,7,13,12,10,7,5,2,7,7,1,10,3,13},{14,1,12,8,10,5,12,12,6,9,12,6,3,3,9},{8,6,13,6,3,9,12,12,12,2,13,12,6,3,5},{6,9,8,12,4,6,9,12,14,5,8,10,9,4,12},{12,6,3,9,10,9,6,9,8,10,7,5,6,11,9},{12,10,3,3,3,5,14,3,3,5,12,12,10,5,4},{14,1,6,5,6,9,10,3,1,12,12,10,1,10,13},{10,3,9,10,11,3,3,3,3,9,10,3,3,3,9}};
public MazeGenerator(int x, int y) {
this.x = x;
this.y = y;
maze = new int[this.x][this.y];
generateMaze(0, 0);
}
public void display() {
for (int i = 0; i < y; i++) {
// draw the bbc.north edge
for (int j = 0; j < x; j++) {
System.out.print((maze[j][i] & 1) == 0 ? "+---" : "+ ");
}
System.out.println("+");
// draw the west edge
for (int j = 0; j < x; j++) {
System.out.print((maze[j][i] & 8) == 0 ? "| " : " ");
}
System.out.println("|");
}
// draw the bottom line
for (int j = 0; j < x; j++) {
System.out.print("+---");
}
System.out.println("+");
}
private void generateMaze(int cx, int cy) {
DIR[] dirs = DIR.values();
Collections.shuffle(Arrays.asList(dirs));
for (DIR dir : dirs) {
int nx = cx + dir.dx;
int ny = cy + dir.dy;
if (between(nx, x) && between(ny, y)
&& (maze[nx][ny] == 0)) {
maze[cx][cy] |= dir.bit;
maze[nx][ny] |= dir.opposite.bit;
generateMaze(nx, ny);
}
}
}
private static boolean between(int v, int upper) {
return (v >= 0) && (v < upper);
}
public int[][] maze() {
return maze;
}
private enum DIR {
N(1, 0, -1), S(2, 0, 1), E(4, 1, 0), W(8, -1, 0);
private final int bit;
private final int dx;
private final int dy;
private DIR opposite;
// use the static initializer to resolve forward references
static {
N.opposite = S;
S.opposite = N;
E.opposite = W;
W.opposite = E;
}
private DIR(int bit, int dx, int dy) {
this.bit = bit;
this.dx = dx;
this.dy = dy;
}
};
public static void main(String[] args) {
int x = args.length >= 1 ? (Integer.parseInt(args[0])) : 8;
int y = args.length == 2 ? (Integer.parseInt(args[1])) : 8;
MazeGenerator maze = new MazeGenerator(x, y);
maze.display();
}
}
如何修复代码,以便在每次点击按钮后正确清除迷宫?我错过了什么吗?
答案 0 :(得分:1)
在清除画布之前删除BoxBlur效果,然后重新应用它。清除画布只需涂上透明色。所以BoxBlur效果也会影响到它。
jewelsea说的是什么。如果您只将代码减少到最低限度,您就可以自己找到它; - )
答案 1 :(得分:0)
对于正在寻找答案的人们,它可能无法正常工作的另一个原因是,如果您将GraphicsContext.globalBlendMode
设置为BlendMode.SCREEN
之类的话。
由于clearRect()
用透明像素绘制画布,所以透明像素在该BlendMode中将无效。
在致电gc.globalBlendMode = BlendMode.SRC_OVER
之前设置clearRect()