import java.util.ArrayList;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Exercise18_33 extends Application {
private static final int SIZE = 8;
private int startX = 0;
private int startY = 0;
private ArrayList<Point2D> moveHistory = null;
@Override // Override the start method in the Application class
public void start(Stage primaryStage) {
BorderPane pane = new BorderPane();
ChessBoard board = new ChessBoard();
pane.setCenter(board);
Button btSolve = new Button("Solve");
pane.setBottom(btSolve);
BorderPane.setAlignment(btSolve, Pos.CENTER);
// Create a scene and place it in the stage
Scene scene = new Scene(pane, 250, 250);
primaryStage.setTitle("Exercise18_33"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
board.paint();
btSolve.setOnAction(e -> {
boolean[][] moves = new boolean[SIZE][SIZE];
moves[startX][startY] = true;
resetMoveHistory();
addMoveHistory(startX, startY);
solvePuzzle(moves, 1, startX, startY);
board.startAnimation();;
});
scene.widthProperty().addListener(ov -> board.paint());
scene.heightProperty().addListener(ov -> board.paint());
}
// This method does the bulk of the work.
// I'm not *thrilled* with this solution as
// it has more redundant code than I'd prefer
// but it gets the job done and done efficiently.
// Uses Warnsdorf's heuristic discovered in 1823
// that says the best move is the one with the
// fewest next moves. I found it necessary to
// back up in only one case (3,0) and choose to
// try the second best move which worked well.
private boolean solvePuzzle(boolean[][] moves, int numMoves, int x, int y) {
int nextX = 0;
int nextY = 0;
int bestMoveX = 0;
int bestMoveY = 0;
int bestMoveX2 = 0;
int bestMoveY2 = 0;
int minMoveCount = SIZE; // Knight has max of 8 moves
int moveCount = 0;
for (int i = 2; i >= -2; i += -4) {
for (int j = 1; j >= -1; j += -2) {
nextX = x + i;
nextY = y + j;
if (nextX >= 0 && nextX <= SIZE - 1 && nextY >= 0 && nextY <= SIZE - 1
&& !moves[nextX][nextY]) {
moveCount = lookAheadCount(moves, nextX, nextY);
if (moveCount <= minMoveCount) {
minMoveCount = moveCount;
bestMoveX2 = bestMoveX;
bestMoveY2 = bestMoveY;
bestMoveX = nextX;
bestMoveY = nextY;
}
}
nextX = x + j;
nextY = y + i;
if (nextX >= 0 && nextX <= SIZE - 1 && nextY >= 0 && nextY <= SIZE - 1
&& !moves[nextX][nextY]) {
moveCount = lookAheadCount(moves, nextX, nextY);
if (moveCount <= minMoveCount) {
minMoveCount = moveCount;
bestMoveX2 = bestMoveX;
bestMoveY2 = bestMoveY;
bestMoveX = nextX;
bestMoveY = nextY;
}
}
}
}
moves[bestMoveX][bestMoveY] = true;
addMoveHistory(bestMoveX, bestMoveY);
numMoves++;
if (numMoves == (SIZE * SIZE))
return true;
if (moveCount > 0 && solvePuzzle(moves, numMoves, bestMoveX, bestMoveY)) {
return true;
}
moves[bestMoveX][bestMoveY] = false;
moves[bestMoveX2][bestMoveY2] = true;
removeLastMoveHistory();
addMoveHistory(bestMoveX2, bestMoveY2);
if (moveCount > 1 && solvePuzzle(moves, numMoves, bestMoveX2, bestMoveY2)) {
return true;
}
moves[bestMoveX2][bestMoveY2] = false;
removeLastMoveHistory();
numMoves--;
return false;
}
private int lookAheadCount(boolean[][] moves, int x, int y) {
int maxCount = 0;
for (int i = -2; i <= 2; i += 4) {
for (int j = -1; j <= 1; j += 2) {
int nextX = x + i;
int nextY = y + j;
if (nextX >= 0 && nextX <= SIZE - 1 && nextY >= 0 && nextY <= SIZE - 1
&& !moves[nextX][nextY]) {
maxCount++;
}
nextX = x + j;
nextY = y + i;
if (nextX >= 0 && nextX <= SIZE - 1 && nextY >= 0 && nextY <= SIZE - 1
&& !moves[nextX][nextY]) {
maxCount++;
}
}
}
return maxCount;
}
public void resetMoveHistory() {
moveHistory = new ArrayList(63);
}
public void addMoveHistory(int x, int y) {
moveHistory.add(new Point2D(x, y));
}
public void removeLastMoveHistory() {
moveHistory.remove(moveHistory.size() - 1);
}
private class ChessBoard extends Pane {
private ImageView knightImageView = new ImageView("image/knight.jpg");
private Timeline animation;
private int index = 0;
ChessBoard() {
this.setOnMouseClicked(e -> {
startX = (int)(e.getX() / (getWidth() / SIZE));
startY = (int)(e.getY() / (getHeight() / SIZE));
resetMoveHistory();
paint();
});
animation = new Timeline(
new KeyFrame(Duration.millis(1000), e -> controlPaint()));
animation.setCycleCount(Timeline.INDEFINITE);
}
private void controlPaint() {
index++;
paint();
if (index == moveHistory.size())
animation.stop();
}
public void startAnimation() {
index = 0;
animation.play();
}
private void paint() {
// Clear previous drawing
this.getChildren().clear();
// Add the Knight image
this.getChildren().add(knightImageView);
knightImageView.setX(startX * getWidth() / SIZE);
knightImageView.setY(startY * getHeight() / SIZE);
knightImageView.setFitWidth(getWidth() / SIZE);
knightImageView.setFitHeight(getHeight() / SIZE);
// Draw the lines
for (int i = 1; i <= SIZE; i++) {
this.getChildren().add(
new Line(0, i * getHeight() / SIZE, getWidth(), i * getHeight() / SIZE));
this.getChildren().add(
new Line(i * getWidth() / SIZE, 0, i * getWidth() / SIZE, getHeight()));
}
// Draw the moves
if (moveHistory != null && moveHistory.size() > 0) {
for (int i = 1; i < index; i++) {
Point2D p1 = moveHistory.get(i - 1);
Point2D p2 = moveHistory.get(i);
this.getChildren().add(
new Line(p1.getX() * (getWidth() / SIZE) + getWidth() / SIZE / 2,
p1.getY() * (getHeight() / SIZE) + (getHeight() / SIZE / 2),
p2.getX() * (getWidth() / SIZE) + getWidth() / SIZE / 2,
p2.getY() * (getHeight() / SIZE) + getHeight() / SIZE / 2));
}
// Add the Knight image
if (moveHistory.size() > 0) {
// Add the Knight image
ImageView knightImageView1 = new ImageView("image/knight.jpg");
this.getChildren().add(knightImageView1);
Point2D p = moveHistory.get(index - 1);
knightImageView1.setX(p.getX() * getWidth() / SIZE);
knightImageView1.setY(p.getY() * getHeight() / SIZE);
knightImageView1.setFitWidth(getWidth() / SIZE);
knightImageView1.setFitHeight(getHeight() / SIZE);
}
}
}
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
没有合适的资源?快使用搜索试试~ 我知道了~
Java语言程序设计与数据结构(基础篇)第18章课后习题代码chapter18.rar
共39个文件
java:39个
11 下载量 117 浏览量
2019-07-04
20:25:52
上传
评论
收藏 28KB RAR 举报
温馨提示
Java语言程序设计与数据结构(基础篇)第18章课后习题代码
资源推荐
资源详情
资源评论
收起资源包目录
chapter18.rar (39个子文件)
chapter18
Exercise18_17.java 481B
Exercise18_01.java 560B
Exercise18_09.java 477B
Exercise18_05.java 290B
Exercise18_37.java 4KB
Exercise18_07.java 785B
Exercise18_32.java 7KB
Exercise18_26.java 6KB
Exercise18_24.java 846B
Exercise18_35.java 3KB
Exercise18_22.java 689B
Exercise18_16.java 465B
Exercise18_15.java 769B
Exercise18_04.java 270B
Exercise18_39.java 3KB
Exercise18_08.java 436B
Exercise18_33.java 8KB
Exercise18_11.java 479B
Exercise18_18.java 1KB
Exercise18_14.java 647B
Exercise18_12.java 549B
Exercise18_03.java 657B
Exercise18_30.java 1KB
Exercise18_23.java 709B
Exercise18_20.java 1KB
Exercise18_29.java 820B
Exercise18_13.java 646B
Exercise18_31.java 1KB
Exercise18_10.java 665B
Exercise18_21.java 489B
Exercise18_34.java 3KB
Exercise18_25.java 653B
Exercise18_36.java 3KB
Exercise18_19.java 3KB
Exercise18_27.java 4KB
Exercise18_28.java 3KB
Exercise18_02.java 477B
Exercise18_06.java 286B
Exercise18_38.java 3KB
共 39 条
- 1
资源评论
南哲风
- 粉丝: 46
- 资源: 45
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功