Java语言程序设计基础篇_编程练习题***18.32 (游戏:骑士的旅途)

news2024/12/26 0:16:29

目录

题目:***18.32 (游戏:骑士的旅途)

习题思路

代码示例

 输出结果


题目:***18.32 (游戏:骑士的旅途)

骑士的旅途是一个古老的谜题,它的目的是使骑从棋盘上的任意一个正方 形开始移动,经过其他的每个正方形一次,如图18-15a 所示。注意,骑士只能做L形的移动(两个空格在一个方向上而一个空格在垂直的方向上)。如图18-15b 所示,骑士可以移动到八个正方形的位置。编写一个程序,显示骑士的移动,如图 18-15C 所示。当单击一个单元格的时候,骑士被放置在该单元格中。该单元格作为骑士的起始点。单击Solve按钮显示作为解答的路径。

  • 习题思路
  1. 界面设置
    • 使用BorderPane作为主布局,中心放置一个Board(自定义的Pane),用于绘制棋盘和骑士的移动路径。
    • 在底部添加一个按钮btSolve,用于触发求解过程。
    • 舞台(Stage)和场景(Scene)的设置,包括尺寸和标题。
  2. 棋盘和骑士的初始化
    • Board类中,通过draw方法绘制棋盘(网格线)和初始位置的骑士(红色圆圈)。
    • 骑士的初始位置(startXstartY)默认为(0, 0),但可通过鼠标点击棋盘上的任意格子来设置新的起始位置。
  3. 求解逻辑
    • 使用一个二维布尔数组moves来记录棋盘上的格子是否已被访问过。
    • solvePuzzle方法是一个递归函数,用于尝试不同的移动路径,直到找到一种能够遍历所有格子并返回起点的解决方案。
    • 在每一步尝试中,通过lookAheadCount方法评估每个可能的下一步移动,并选择看起来最有前景的(即下一步后能够访问最多新格子的)移动。
    • 使用回溯法,如果当前路径无法找到解决方案,则撤销上一步的选择,尝试其他可能的移动。
  4. 用户交互
    • 点击棋盘上的格子设置新的起始位置,并清空之前的移动历史。
    • 点击“Solve”按钮触发求解过程,并在找到解决方案后重新绘制棋盘,显示骑士的移动路径。
  5. 移动历史记录
    • 使用ArrayList<Point2D>来记录骑士的移动历史,以便在求解过程中回溯和重新绘制路径。
    • 提供resetMovesaddMoveremoveLastMoveHistory方法来管理移动历史记录。
  6. 棋盘绘制
    • Board类的draw方法中,除了绘制棋盘网格和骑士外,还根据移动历史记录绘制骑士的移动路径。
  • 代码示例

编程练习题18_32TheKnightJourney.java

package chapter_18;  
  
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.geometry.Point2D;
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.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;  
  
public class 编程练习题18_32TheKnightJourney extends Application {  
	private static final int SIZE = 8;
	private int startX = 0;
	private int startY = 0;
	private ArrayList<Point2D> moves = null;
	public static void main(String[] args) {  
		Application.launch(args);  
	}  
    @Override  
    public void start(Stage primaryStage) throws Exception {
    	BorderPane pane = new BorderPane();
    	Board board = new Board();
    	pane.setCenter(board);
    	Button btSolve = new Button("Solve");
    	pane.setBottom(btSolve);
    	BorderPane.setAlignment(btSolve, Pos.CENTER);
    	
    	Scene scene = new Scene(pane,400,400);
    	primaryStage.setTitle("");
    	primaryStage.setScene(scene);
    	primaryStage.show();
    	
    	board.draw();
    	
    	btSolve.setOnAction(e -> {
    		boolean[][] moves = new boolean[SIZE][SIZE];
    		moves[startX][startY] = true;
    		resetMoves();
    		addMove(startX,startY);
    		solvePuzzle(moves,1,startX,startY);
    		board.draw();
    	});
    }
    
    private boolean solvePuzzle(boolean[][] moves,int numberMoves,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;
    	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;
    	addMove(bestMoveX,bestMoveY);
    	numberMoves++;
    	if(numberMoves == (SIZE * SIZE))
    		return true;
    	if(moveCount > 0&&solvePuzzle(moves, numberMoves, bestMoveX, bestMoveY))
    		return true;
    	moves[bestMoveX][bestMoveY] = false;
    	moves[bestMoveX2][bestMoveY2] = true;
    	removeLastMoveHistory();
    	addMove(bestMoveX2,bestMoveY2);
    	if(moveCount > 1&&solvePuzzle(moves, numberMoves, bestMoveX2, bestMoveY2)) {
    		return true;
    	}
    	moves[bestMoveX2][bestMoveY2] = false;
    	removeLastMoveHistory();
    	numberMoves--;
    	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 resetMoves() {
    	moves = new ArrayList(63);
    }
    public void addMove(int x,int y) {
    	moves.add(new Point2D(x, y));
    }
    public void removeLastMoveHistory() {
    	moves.remove(moves.size()-1);
    }
    private class Board extends Pane{
    	Circle theKnight = new Circle();
    	Board(){
    		this.setOnMouseClicked(e ->{
    			startX = (int)(e.getX()/(getWidth()/SIZE));
    			startY = (int)(e.getY()/(getHeight()/SIZE));
    			resetMoves();
    			draw();
    		});
    	}
    	protected void draw() {
    		this.getChildren().clear();
    		this.getChildren().add(theKnight);
    		theKnight.setCenterX(startX * getWidth()/SIZE +15);
    		theKnight.setCenterY(startY * getHeight()/SIZE + 15);
    		theKnight.setRadius(5);
    		theKnight.setFill(Color.RED);
    		
    		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()));
    		}
    		if(moves != null) {
    			for(int i = 1;i < moves.size();i++) {
    				Point2D p1 = moves.get(i - 1);
    				Point2D p2 = moves.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)
    				));
    			}
    		}
    	}
    }
}
  •  输出结果

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2151505.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

R18 5G网络中 AI/ML技术特性及其在5GS和NG-RAN中的应用

随着5G技术的发展&#xff0c;人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;在网络中的应用越来越广泛。本文将介绍R18 5G网络中AI/ML的新特性&#xff0c;包括在5G系统&#xff08;5GS&#xff09;中的应用、在新一代无线接入网&#xff08;NG-RAN…

AD中PCB元器件常用的对齐用法

1.shift 选中要对齐的元器件 2.按右键&#xff0c;选择对齐&#xff0c;或者按A&#xff0c;弹出对齐对菜单&#xff1b;&#xff08;切记不要选择多余的元器件或者线条&#xff0c;要不然也会根据它的位置来做对齐&#xff0c;按shift一个一个元器件选择&#xff09; 常用如下…

基于SpringBoot+Vue的在线学习平台

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…

出现conda不是内部或外部命令,也不是可运行的程序或批处理文件。的解决办法

发现是我的环境变量不对&#xff0c;需要改成conda.exe所在的目录下 如果不知道自己conda.exe在哪的 可以下载个everything这个软件 找东西很快 找到后 点击环境变量-系统变量-Path-新建-&#xff08;你的conda.exe所在目录&#xff1a;绝对路径&#xff09; 完成上述操作…

【English】语法的整体结构

目录 &#x1f4cc;词类——"英语的本质是词与词之间的修饰关系" 名词( Noun ) 形容词( Adjective ) 动词( Verb ) 副词( Adverbs ) 修饰关系——"理解词与词之间的修饰关系与规则" &#x1f4cc;句子结构 句子的基本成分 五种基本句型和三种句子类型 关于…

ROC和AUC也不是评估机器学习性能的金标准

对于不平衡数据集&#xff0c;AUC值是分类器效果评估的常用标准。但如果在解释时不仔细&#xff0c;它也会有一些误导。以Davis and Goadrich (2006)中的模型为例。如图所示&#xff0c;左侧展示的是两个模型的ROC曲线&#xff0c;右侧展示的是precision-recall曲线 (PRC)。 Pr…

前端univer创建、编辑excel

前端univer创建、编辑excel 源码在线demo&#xff1a;https://codesandbox.io/p/sandbox/univer-q87kqg?file/src/Demo.jsx univer官网地址&#xff1a;https://univer.ai/zh-CN/guides/sheet/introduction 安装univer npm install univerjs/core univerjs/design univerjs…

大模型爬虫—ScrapeGraphAI

大模型爬虫—ScrapeGraphAI 一、介绍 ScrapeGraphAI是一个网络爬虫 Python 库,使用大型语言模型和直接图逻辑为网站和本地文档(XML,HTML,JSON 等)创建爬取管道。 只需告诉库您想提取哪些信息,它将为您完成! scrapegraphai有三种主要的爬取管道可用于从网站(或本地文…

dockerfile 添加arthas 监控插件。容器添加arthas监控

1. arthas官网&#xff1a; 简介 | arthas 2. arthas下载地址&#xff1a; Releases alibaba/arthas GitHub 3. 下载版本&#xff1a; 4. 下载压缩包后&#xff0c;解压缩&#xff0c;放入Dockerfile 同级目录 5. dockerfile 命令&#xff1a; RUN mkdir -p /opt/arthas…

HarmonyOS鸿蒙开发实战(5.0)自定义全局弹窗实践

鸿蒙HarmonyOS开发实战往期文章必看&#xff1a; HarmonyOS NEXT应用开发性能实践总结 最新版&#xff01;“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&#xff01;&#xff08;从零基础入门到精通&#xff09; 非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&am…

【RPA私教课:UIPath】RPA 赋能科技企业,登录时验证码自动截取

在某科技型企业里&#xff0c;专门设置了一个验证码接收系统。每当用户进行登录操作时&#xff0c;都必须从这个系统中抓取最新的登录验证码&#xff0c;以确保登录的安全性。 具体需求如下&#xff1a; 客户会预先在表格中妥善保存众多的账户和密码。当 RPA 机器人在业务系统…

weblogic CVE-2017-3506 靶场攻略

漏洞描述 Weblogic的WLS Security组件对外提供了webserver服务&#xff0c;其中使⽤了XMLDecoder来解析⽤户输⼊的XML数据&#xff0c;在解析过程中出现反序列化漏洞&#xff0c;可导致任意命令执⾏。 影响版本 受影响版本&#xff1a;WebLogic 10.3.6.0, 12.1.3.0, 12.2.1.…

idea启动oom了解决

解决 Error:java: java.lang.OutOfMemoryError: WrappedJavaFileObject[org.jetbrains.jps.javac.InputFileObject[file:///D:/mingan/pb/backend/src/main/java/com/cy/backend/service/impl/StorageServiceImpl.java]]pos36199: WrappedJavaFileObject[org.jetbrains.jps.j…

提升效率的AI工具集 - 轻松实现自动化

在这个快节奏、高效率的社会中&#xff0c;我们每个人都渴望能够找到提升工作效率的捷径。幸运的是&#xff0c;随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;越来越多的AI工具涌现出来&#xff0c;为我们提供了强大的支持。这些工具不仅能够帮助我们提高…

JavaScript可视化

JavaScript 可视化通常涉及利用各种库和工具将数据转化为图形的形式&#xff0c;从而更直观地呈现信息。以下是一些流行的 JavaScript 可视化工具和库&#xff0c;以及一些关键知识点&#xff1a; 流行的 JavaScript 可视化库&#xff1a; 1. D3.js (Data-Driven Documents)&…

xtop:pt dmsa环境下如何写出timing data file

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 xtop的输入数据之一就是sta timing data,它是由各scenario的报告组成的,

MedPrompt:基于提示工程的医学诊断准确率优化方法

Medprompt&#xff1a;基于提示工程的医学诊断准确率优化方法 秒懂大纲解法拆解MedPrompt 提示词全流程分析总结创意视角 论文&#xff1a;Can Generalist Foundation Models Outcompete Special-Purpose Tuning? Case Study in Medicine 秒懂大纲 ├── 1 研究背景【描述背…

VIVADO IP核之FIR插值器多相滤波仿真

VIVADO IP核之FIR插值器多相滤波仿真&#xff08;含有与MATLAB仿真数据的对比&#xff09; 目录 前言 一、滤波器系数生成 二、用MATLAB生成仿真数据 三、VIVADO FIR插值多相滤波器使用 四、VIVADO FIR插值多相滤波器仿真 五、VIVADO工程下载 总结 前言 网络上有许多文章…

生信初学者教程(五):R语言基础

文章目录 数据类型整型逻辑型字符型日期型数值型复杂数数据结构向量矩阵数组列表因子数据框ts特殊值缺失值 (NA)无穷大 (Inf)非数字 (NaN)安装R包学习材料R语言是一种用于统计计算和图形展示的编程语言和软件环境,广泛应用于数据分析、统计建模和数据可视化。1991年:R语言的最…

webpack4 target:“electron-renderer“ 打包加速配置

背景 昨天写得一篇Electron-vue asar 局部打包优化处理方案——绕开每次npm run build 超级慢的打包问题-CSDN博客文章浏览阅读754次&#xff0c;点赞19次&#xff0c;收藏11次。因为组员对于 Electron 打包过程存在比较迷糊的状态&#xff0c;且自己也没主动探索 Electron-vu…