|  | 
|  | 1 | +package ch_15; | 
|  | 2 | + | 
|  | 3 | +import javafx.application.Application; | 
|  | 4 | +import javafx.beans.property.SimpleStringProperty; | 
|  | 5 | +import javafx.beans.property.StringProperty; | 
|  | 6 | +import javafx.geometry.Pos; | 
|  | 7 | +import javafx.scene.Scene; | 
|  | 8 | +import javafx.scene.control.Button; | 
|  | 9 | +import javafx.scene.layout.BorderPane; | 
|  | 10 | +import javafx.scene.layout.Pane; | 
|  | 11 | +import javafx.scene.paint.Color; | 
|  | 12 | +import javafx.scene.shape.Line; | 
|  | 13 | +import javafx.stage.Stage; | 
|  | 14 | + | 
|  | 15 | +import java.util.ArrayList; | 
|  | 16 | +import java.util.List; | 
|  | 17 | + | 
|  | 18 | +/** | 
|  | 19 | + * ***15.35 (Animation: self-avoiding random walk) Revise the preceding exercise to display | 
|  | 20 | + * the walk step by step in an animation, as shown in Figure 15.37c and d. | 
|  | 21 | + */ | 
|  | 22 | +public class Exercise15_35 extends Application { | 
|  | 23 | + private double paneWidth = 300; | 
|  | 24 | + private double paneHeight = 250; | 
|  | 25 | + private StringProperty buttonLabel = new SimpleStringProperty("Start"); | 
|  | 26 | + | 
|  | 27 | + @Override | 
|  | 28 | + public void start(Stage primaryStage) { | 
|  | 29 | + Lattice lattice = new Lattice(); | 
|  | 30 | + BorderPane borderPane = new BorderPane(); | 
|  | 31 | + borderPane.setCenter(lattice); | 
|  | 32 | + Button btStart = new Button(); | 
|  | 33 | + btStart.textProperty().bind(buttonLabel); | 
|  | 34 | + btStart.setOnAction(e -> lattice.actionButtonPressed()); | 
|  | 35 | + borderPane.setBottom(btStart); | 
|  | 36 | + BorderPane.setAlignment(btStart, Pos.CENTER); | 
|  | 37 | + | 
|  | 38 | + Scene scene = new Scene(borderPane, paneWidth, paneHeight + 40); | 
|  | 39 | + primaryStage.setTitle(getClass().getName()); | 
|  | 40 | + primaryStage.setScene(scene); | 
|  | 41 | + primaryStage.show(); | 
|  | 42 | + } | 
|  | 43 | + | 
|  | 44 | + class Lattice extends Pane { | 
|  | 45 | + public static final int N = 16; | 
|  | 46 | + private Point[][] lattice = new Point[N + 1][N + 1]; | 
|  | 47 | + private double hGap = paneWidth / N; | 
|  | 48 | + private double vGap = paneHeight / N; | 
|  | 49 | + | 
|  | 50 | + private List<Line> steps = new ArrayList<>(); | 
|  | 51 | + private int stepIndex = 0; | 
|  | 52 | + | 
|  | 53 | + public Lattice() { | 
|  | 54 | + drawGrid(); | 
|  | 55 | + } | 
|  | 56 | + | 
|  | 57 | + /** | 
|  | 58 | + * Draw lines | 
|  | 59 | + */ | 
|  | 60 | + public void drawGrid() { | 
|  | 61 | + // Draw lattice lines | 
|  | 62 | + for (int i = 1; i < N + 1; i++) { | 
|  | 63 | + Line line1 = new Line(0, i * vGap, paneWidth, i * vGap); | 
|  | 64 | + Line line2 = new Line(i * hGap, 0, i * hGap, paneHeight); | 
|  | 65 | + this.getChildren().addAll(line1, line2); | 
|  | 66 | + line1.setStroke(Color.LIGHTGRAY); | 
|  | 67 | + line2.setStroke(Color.LIGHTGRAY); | 
|  | 68 | + } | 
|  | 69 | + } | 
|  | 70 | + | 
|  | 71 | + /** | 
|  | 72 | + * Build the steps of the path and store in a Line array | 
|  | 73 | + */ | 
|  | 74 | + public void createPathSteps() { | 
|  | 75 | + getChildren().clear(); | 
|  | 76 | + drawGrid(); | 
|  | 77 | + | 
|  | 78 | + // Start from the center point in the lattice (i, j) | 
|  | 79 | + int i = (N + 1) / 2; | 
|  | 80 | + int j = (N + 1) / 2; | 
|  | 81 | + | 
|  | 82 | + while (lattice[i][j] != null) { | 
|  | 83 | + Point p = lattice[i][j]; | 
|  | 84 | + Line line = new Line(i * hGap, j * vGap, p.x * hGap, p.y * vGap); | 
|  | 85 | + steps.add(line); | 
|  | 86 | + i = p.x; | 
|  | 87 | + j = p.y; | 
|  | 88 | + } | 
|  | 89 | + } | 
|  | 90 | + | 
|  | 91 | + void drawNextStep() { | 
|  | 92 | + if (stepIndex == 0) { | 
|  | 93 | + buttonLabel.setValue("Next"); | 
|  | 94 | + } | 
|  | 95 | + | 
|  | 96 | + if (stepIndex < steps.size()) { | 
|  | 97 | + getChildren().add(steps.get(stepIndex++)); | 
|  | 98 | + } else { | 
|  | 99 | + buttonLabel.setValue("Restart"); | 
|  | 100 | + } | 
|  | 101 | + } | 
|  | 102 | + | 
|  | 103 | + public void getAPath() { | 
|  | 104 | + // Refresh lattice | 
|  | 105 | + for (int i = 0; i < lattice.length; i++) { | 
|  | 106 | + for (int j = 0; j < lattice.length; j++) { | 
|  | 107 | + lattice[i][j] = null; | 
|  | 108 | + } | 
|  | 109 | + } | 
|  | 110 | + | 
|  | 111 | + // (i, j) is the current path point. Initially it is at the center | 
|  | 112 | + int i = (N + 1) / 2; | 
|  | 113 | + int j = (N + 1) / 2; | 
|  | 114 | + | 
|  | 115 | + while (i > 0 && i < N && j > 0 && j < N) { | 
|  | 116 | + if (lattice[i - 1][j] != null && lattice[i + 1][j] != null | 
|  | 117 | + && lattice[i][j - 1] != null && lattice[i][j + 1] != null) { | 
|  | 118 | + break; // Dead end | 
|  | 119 | + } | 
|  | 120 | + | 
|  | 121 | + double r = Math.random(); | 
|  | 122 | + if (r < .25 && lattice[i][j + 1] == null) { | 
|  | 123 | + lattice[i][j] = new Point(i, j + 1); // Right | 
|  | 124 | + j++; | 
|  | 125 | + } else if (r < .50 && lattice[i + 1][j] == null) { | 
|  | 126 | + lattice[i][j] = new Point(i + 1, j); // Down | 
|  | 127 | + i++; | 
|  | 128 | + } else if (r < .75 && lattice[i][j - 1] == null) { | 
|  | 129 | + lattice[i][j] = new Point(i, j - 1); // Left | 
|  | 130 | + j--; | 
|  | 131 | + } else if (r < 1.00 && lattice[i - 1][j] == null) { | 
|  | 132 | + lattice[i][j] = new Point(i - 1, j); // Up | 
|  | 133 | + i--; | 
|  | 134 | + } | 
|  | 135 | + } | 
|  | 136 | + | 
|  | 137 | + createPathSteps(); | 
|  | 138 | + } | 
|  | 139 | + | 
|  | 140 | + public void actionButtonPressed() { | 
|  | 141 | + if (buttonLabel.getValue().equals("Start")) { | 
|  | 142 | + getAPath(); | 
|  | 143 | + drawNextStep(); | 
|  | 144 | + } else if (buttonLabel.getValue().equals("Next")) { | 
|  | 145 | + drawNextStep(); | 
|  | 146 | + } else if (buttonLabel.getValue().equals("Restart")) { | 
|  | 147 | + getChildren().clear(); | 
|  | 148 | + steps.clear(); | 
|  | 149 | + stepIndex = 0; | 
|  | 150 | + drawGrid(); | 
|  | 151 | + buttonLabel.setValue("Start"); | 
|  | 152 | + } | 
|  | 153 | + } | 
|  | 154 | + | 
|  | 155 | + class Point { | 
|  | 156 | + int x; | 
|  | 157 | + int y; | 
|  | 158 | + | 
|  | 159 | + Point(int i, int j) { | 
|  | 160 | + this.x = i; | 
|  | 161 | + this.y = j; | 
|  | 162 | + } | 
|  | 163 | + } | 
|  | 164 | + } | 
|  | 165 | + | 
|  | 166 | +} | 
0 commit comments