目录
题目:**18.26 (创建一个迷宫)
习题思路
代码示例
输出结果
题目:**18.26 (创建一个迷宫)
编写一个程序,在迷宫中寻找一条路径,如图18-13a所示。该迷宫由一个8 x 8 的棋盘表示。路径必须满足下列条件:
- 路径在迷宫的左上角单元和右下角单元之间。
- 程序允许用户在一个单元格中放入或移走一个标志。路径由相邻的未放标志的单元格组成。如果两个单元格在水平方向或垂直方向相邻,但在对角线方向上不相邻,那么就称它们是相邻的。
- 路径不包含能形成一个正方形的单元格。例如,在图18-13b中的路径就不满足这个条件。( 这个条件使得面板上的路径很容易识别。)
-
习题思路
- 创建一个单元格类(cell),继承自StackPane类。
- 创建几个私有变量,分别表示是否被访问,是否被标记,是否被阻塞,并创建相应的方法。
- 创建一个Rectangle,在构造方法被调用时添加到面板中。
- 创建两条直线,在单元格上组成一个叉号,但暂时不放置在面板上。
- 当单元格被点击时,如果单元格未被标记,那么将单元格设置为已标记(调用方法将两条直线放置在面板上,标记变量设置为true)。已被标记则设置为不标记(调用方法从面板上删除直线标记变量设置为false)。
- (start方法内部)
- 创建私有变量单元格列表( cells[8][8]),创建私有变量Label
- 在start方法中定义一个GridPane,使用循环示例化cells并添加到面板中
- 创建两个HBox,分别放置一个Label和两个按钮
- 创建一个BorderPane,将GridPane放置在中心,两个HBox分别放置在顶部和底部。
- 为两个按钮注册事件,find按钮对应③的findPath方法;clear按钮对应④的clear方法。
- 创建私有变量单元格列表( cells[8][8]),创建私有变量Label
- (findPath)方法,传入坐标参数,返回值boolean
- 如果传入的坐标是7*7,即终点坐标,则返回true。
- 如果上方单元格(
row-1, col
)是可访问的(即未标记、未阻塞且未访问过),则尝试从那里继续搜索,在递归调用findPath
之前,调用block(row, col)。
- 尝试向下、向左、向右移动,与向上移动的逻辑类似,但分别针对下方、左方和右方单元格进行尝试。
- (clear)方法
- 使用循环为cells中的元素逐个调用unSelect方法()。
- 其他自行查看代码
-
代码示例
编程练习题18_26labyrinth.java
package chapter_18;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class 编程练习题18_26labyrinth extends Application{
private cell[][] cells = new cell[8][8];
private double WIDTH = 400;
private double HEIGHT = 400;
private Label lbPathInfo;
@Override
public void start(Stage primaryStage) throws Exception {
// TODO Auto-generated method stub
GridPane gridPane = new GridPane();
gridPane.setStyle("-fx-background-color: gray");
gridPane.setHgap(2);
gridPane.setVgap(2);
for(int i = 0;i < 8;i++) {
for(int j = 0;j < 8;j++) {
gridPane.add(cells[i][j] = new cell(), i, j);
}
}
lbPathInfo = new Label("INFO");
HBox hBox = new HBox(lbPathInfo);
hBox.setAlignment(Pos.CENTER);
Button btFind = new Button("Find Path");
Button btClear = new Button("Clear Path");
btClear.setOnAction(e -> clear());
btFind.setOnAction(e -> findPath());
HBox hBox2 = new HBox(btFind,btClear);
hBox2.setAlignment(Pos.CENTER);
BorderPane borderPane = new BorderPane();
borderPane.setCenter(gridPane);
borderPane.setTop(hBox);
borderPane.setBottom(hBox2);
Scene scene = new Scene(borderPane);
primaryStage.setTitle("编程练习题18_26labyrinth");
primaryStage.setScene(scene);
primaryStage.show();
}
public void clear() {
for(cell[] c:cells) {
for(cell cel:c) {
cel.unSelect();
}
}
}
public void findPath() {
if(findPath(0,0)) {
lbPathInfo.setText("Path found");
}else {
lbPathInfo.setText("No legal path exists");
}
}
public boolean findPath(int row,int col) {
cells[row][col].visit();
if((row==7)&&(col==7)) {
cells[row][col].select();
return true;
}
if((row>0)&&!cells[row-1][col].isMark()&&
!cells[row-1][col].blocked()&&!cells[row-1][col].visited) {
block(row, col);
if(findPath(row-1, col)) {
cells[row][col].select();
return true;
}
unblock(row, col);
}
if((row < 7)&&!cells[row+1][col].isMark()&&
!cells[row+1][col].blocked()&&!cells[row+1][col].visited()) {
block(row, col);
if(findPath(row + 1,col)) {
cells[row][col].select();
return true;
}
unblock(row, col);
}
if((col > 0)&&!cells[row][col-1].isMark()&&
!cells[row][col-1].blocked()&&!cells[row][col-1].visited()) {
block(row, col);
if(findPath(row, col - 1)) {
cells[row][col].select();
return true;
}
unblock(row, col);
}
if((col < 7)&&!cells[row][col+1].isMark()&&
!cells[row][col+1].blocked()&&!cells[row][col+1].visited()) {
block(row, col);
if(findPath(row,col+1)) {
cells[row][col].select();
return true;
}
unblock(row, col);
}
return false;
}
public void block(int row,int col) {
if(row > 0)
cells[row - 1][col].block();
if(row < 7)
cells[row+1][col].block();
if(col > 0)
cells[row][col-1].block();
if(col < 7)
cells[row][col+1].block();
}
public void unblock(int row,int col) {
if(row > 0)
cells[row-1][col].unblock();
if(row < 7)
cells[row+1][col].unblock();
if(col > 0)
cells[row][col-1].unblock();
if(col < 7)
cells[row][col+1].unblock();
}
public static void main(String[] args) {
Application.launch(args);
}
class cell extends StackPane{
private boolean selected = false;
private boolean visited = false;
private boolean blocked = false;
private Rectangle r = new Rectangle(WIDTH/8,HEIGHT/8);
Line l1 = new Line(0, 0, WIDTH/8, HEIGHT/8);
Line l2 = new Line(WIDTH/8, 0, 0, HEIGHT/8);
public cell() {
getChildren().add(r);
r.setFill(Color.WHITE);
r.setStroke(Color.BLACK);
this.setOnMouseClicked(e ->{
if(selected) {
unMark();
}else {
mark();
}
});
}
public boolean blocked() {
return blocked;
}
public void block() {
blocked = true;
}
public void unblock() {
blocked = false;
}
public void visit() {
visited = true;
}
public boolean visited() {
return visited;
}
public boolean isMark() {
return selected;
}
public void mark() {
selected = true;
this.getChildren().addAll(l1,l2);
}
public void unMark() {
selected = false;
this.getChildren().remove(l1);
this.getChildren().remove(l2);
}
public void select() {
r.setFill(Color.RED);
}
public void unSelect() {
unblock();
r.setFill(Color.WHITE);
visited = false;
}
}
}