***15.34 (模拟:自回避随机漫步)
在一个网格中的自回避漫步是指从一个点到另一点的过程中,不重复两次访问一个点。自回避漫步已经广泛应用在物理、化学和数学学科中。它们可以用来模拟像溶剂和聚合物这样的链状物。编写一个程序,显示一个从中心点出发到边界点结束的随机路径,如图15-37a所示,或者在一个尽头点结束(即该点被四个已经访问过的点包围),如图15- 37b所示。假设网格的大小是16×16
***15.35 (动画:自回避随机漫步)
修改上一个练习题,在一个动画中逐步地显示漫步,如图15-37c和图15-37d所示
- 习题思路
- 新建一个Pane,新建一个Rectangle表示网格的外围
- 每隔一段距离绘制一条虚线,绘制16条,横竖都画
- 设置一个Start按钮并添加到新建的HBox中,
- 新建一个BorderPane,按下时触发画线方法,把Pane设置在中心,把HBox设置在底部
- 新建一个画线方法,设置四个boolean参数代表上下左右是否都可以前进,如果都为false则退出
- (画线方法内部)随机产生一个数(0~3),按照相应的位置将线条的终点坐标进行调整,如果终点坐标到达边界则终止
- 添加动画的方式很简单,输入下面的语句并在按钮按下时调用animation.play()方法
EventHandler<ActionEvent> eventHandler = e -> DrawLine(); Timeline animation = new Timeline(new KeyFrame(Duration.millis(300),eventHandler));
代码示例:编程练习题15_35SelfAvoidanceRandomWalk.java
package chapter_15;import java.util.ArrayList;import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;public class 编程练习题15_35SelfAvoidanceRandomWalk extends Application{EventHandler<ActionEvent> eventHandler = e -> DrawLine();Timeline animation = new Timeline(new KeyFrame(Duration.millis(300),eventHandler));int startX = 160,startY = 160;int endX = 160,endY = 160;Pane pane = new Pane();ArrayList<String> point = new ArrayList<>();boolean canStart = true;@Overridepublic void start(Stage primaryStage) throws Exception {Rectangle r = new Rectangle(1, 1, 320, 320);r.setFill(Color.WHITE);r.setStroke(Color.GRAY);pane.getChildren().add(r);for(int i = 1;i < 16;i++) {Line lineH = new Line(0, i*20+1,320,i*20+1);Line lineV = new Line(i*20+1,0 ,i*20+1, 320);lineH.getStrokeDashArray().addAll(3.0, 4.0); // 设置虚线的样式,3表示实线段的长度,4表示空段的长度lineV.getStrokeDashArray().addAll(3.0, 4.0); // 设置虚线的样式,3表示实线段的长度,4表示空段的长度lineH.setStroke(Color.GRAY);lineV.setStroke(Color.GRAY);pane.getChildren().addAll(lineH,lineV);}HBox hBox = new HBox();hBox.setAlignment(Pos.CENTER);Button btStart = new Button("Start");btStart.setOnAction(e ->{if(canStart)animation.play();});hBox.getChildren().add(btStart);point.add(startX+" "+startY);animation.setCycleCount(Timeline.INDEFINITE);BorderPane borderPane = new BorderPane();borderPane.setCenter(pane);borderPane.setBottom(hBox);Scene scene = new Scene(borderPane, 320, 360);primaryStage.setTitle("编程练习题15_35SelfAvoidanceRandomWalk");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {Application.launch(args);}boolean up = true;boolean down = true;boolean left = true;boolean right = true;public void DrawLine() {if(point.contains(startX+" "+(startY-20))) {up = false;}if(point.contains(startX+" "+(startY+20))) {down = false;}if(point.contains((startX-20)+" "+startY)) {left = false;}if(point.contains((startX+20)+" "+startY)) {right = false;}if(!up&&!down&&!left&&!right) {animation.stop();canStart = false;}int random;do { random = (int) (Math.random() * 4); } while ((random == 0 && !up) || (random == 1 && !down) || (random == 2 && !left) || (random == 3 && !right));if(random == 0) {//上endY = startY-20;}else if(random == 1) {//下endY = startY+20;}else if(random == 2) {//左endX = startX-20;}else if(random == 3) {//右endX = startX+20;}Line l = new Line(startX,startY,endX,endY);l.setStroke(Color.RED);pane.getChildren().add(l);startX = endX;startY = endY;point.add(startX+" "+startY);if (endX <= 0 || endY <= 0 || endX >= 320 || endY >= 320) { animation.stop(); canStart = false;return; // 可选:如果已经停止动画,则退出方法 } }
}
15.34题可以通过35题注释部分代码得到
package chapter_15;import java.util.ArrayList;import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;public class 编程练习题15_34SelfAvoidanceRandomWalk extends Application{//EventHandler<ActionEvent> eventHandler = e -> DrawLine();//Timeline animation = new Timeline(new KeyFrame(Duration.millis(300),eventHandler));int startX = 160,startY = 160;int endX = 160,endY = 160;Pane pane = new Pane();ArrayList<String> point = new ArrayList<>();boolean canStart = true;@Overridepublic void start(Stage primaryStage) throws Exception {Rectangle r = new Rectangle(1, 1, 320, 320);r.setFill(Color.WHITE);r.setStroke(Color.GRAY);pane.getChildren().add(r);for(int i = 1;i < 16;i++) {Line lineH = new Line(0, i*20+1,320,i*20+1);Line lineV = new Line(i*20+1,0 ,i*20+1, 320);lineH.getStrokeDashArray().addAll(3.0, 4.0); // 设置虚线的样式,3表示实线段的长度,4表示空段的长度lineV.getStrokeDashArray().addAll(3.0, 4.0); // 设置虚线的样式,3表示实线段的长度,4表示空段的长度lineH.setStroke(Color.GRAY);lineV.setStroke(Color.GRAY);pane.getChildren().addAll(lineH,lineV);}HBox hBox = new HBox();hBox.setAlignment(Pos.CENTER);Button btStart = new Button("Start");btStart.setOnAction(e ->{if(canStart)DrawLine();//animation.play();});hBox.getChildren().add(btStart);point.add(startX+" "+startY);//animation.setCycleCount(Timeline.INDEFINITE);BorderPane borderPane = new BorderPane();borderPane.setCenter(pane);borderPane.setBottom(hBox);Scene scene = new Scene(borderPane, 320, 360);primaryStage.setTitle("编程练习题15_34SelfAvoidanceRandomWalk");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {Application.launch(args);}boolean up = true;boolean down = true;boolean left = true;boolean right = true;public void DrawLine() {if(point.contains(startX+" "+(startY-20))) {up = false;}if(point.contains(startX+" "+(startY+20))) {down = false;}if(point.contains((startX-20)+" "+startY)) {left = false;}if(point.contains((startX+20)+" "+startY)) {right = false;}if(!up&&!down&&!left&&!right) {canStart = false;}int random;do { random = (int) (Math.random() * 4); } while ((random == 0 && !up) || (random == 1 && !down) || (random == 2 && !left) || (random == 3 && !right));if(random == 0) {//上endY = startY-20;}else if(random == 1) {//下endY = startY+20;}else if(random == 2) {//左endX = startX-20;}else if(random == 3) {//右endX = startX+20;}Line l = new Line(startX,startY,endX,endY);l.setStroke(Color.RED);pane.getChildren().add(l);startX = endX;startY = endY;point.add(startX+" "+startY);if (endX <= 0 || endY <= 0 || endX >= 320 || endY >= 320) { //animation.stop(); canStart = false;return; // 可选:如果已经停止动画,则退出方法 } }
}
结果展示