Java语言程序设计基础篇_编程练习题**18.37 (希尔伯特曲线)

news2024/9/29 13:45:33

目录

题目:**18.37 (希尔伯特曲线)

代码示例

代码逻辑解释

1. 初始化与布局

2. 绘制逻辑

3. 绘制过程

输出结果


题目:**18.37 (希尔伯特曲线)

希尔伯特曲线,由德国数学家希尔伯特于1891年第一个给出描述,是一种空间填充曲线,以 2 x 2, 4 x 4, 8 x 8, 16 x 16, 或者任何其他 2 的幂的大小来访问一个方格网的每个点。编写程序,以给定的阶数显示希尔伯特曲线,如图 18-19 所示。

  • 代码示例

编程练习题18_37HilbertCurve.java

package chapter_18;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class 编程练习题18_37HilbertCurve extends Application {

    private static final int WIDTH = 700;
    private static final int HEIGHT = 700;
    private static final int MARGIN = 10;
    private double segX, segY;
    private int[] EXP = new int[10];

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        // Initialize EXP array
        EXP[0] = 1;
        for (int i = 1; i < 10; i++) {
            EXP[i] = EXP[i - 1] * 2;
        }

        // Create UI components
        Label lblOrder = new Label("Enter the order: ");
        TextField txtOrder = new TextField();
        Canvas canvas = new Canvas(WIDTH, HEIGHT);
        GraphicsContext gc = canvas.getGraphicsContext2D();

        // Layout
        HBox hBox = new HBox(lblOrder, txtOrder);
        hBox.setAlignment(Pos.CENTER);
        VBox vBox = new VBox(canvas,hBox);

        // Event handler for the button
        txtOrder.setOnKeyPressed(event -> {
        	if(event.getCode() == KeyCode.ENTER&&event.getText() != "") {
        		try {
            		int order = Integer.parseInt(txtOrder.getText());
            		if (order > 0 && order < 10) {
            			gc.clearRect(0, 0, WIDTH, HEIGHT);
            			segX = (WIDTH - 2 * MARGIN) / (EXP[order] - 1.0);
            			segY = (HEIGHT - 2 * MARGIN) / (EXP[order] - 1.0);
            			showOrder(0, 0, 1, order, gc);
            		}
        		} catch (NumberFormatException e) {
        			//System.out.println("Please enter a valid integer.");
        			System.out.println(e);
        		}
        	}
        });

        // Scene and stage setup
        Scene scene = new Scene(vBox);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void showOrder(int startX, int startY, int shape, int order, GraphicsContext gc) {
        if (order == 1) {
            switch (shape) {
                case 1:
                    drawLine(gc, startX, startY, startX, startY + 1);
                    drawLine(gc, startX, startY + 1, startX + 1, startY + 1);
                    drawLine(gc, startX + 1, startY + 1, startX + 1, startY);
                    break;
                case 2:
                    drawLine(gc, startX, startY, startX + 1, startY);
                    drawLine(gc, startX + 1, startY, startX + 1, startY + 1);
                    drawLine(gc, startX + 1, startY + 1, startX, startY + 1);
                    break;
                case 3:
                    drawLine(gc, startX, startY + 1, startX, startY);
                    drawLine(gc, startX, startY, startX + 1, startY);
                    drawLine(gc, startX + 1, startY, startX + 1, startY + 1);
                    break;
                case 4:
                    drawLine(gc, startX + 1, startY, startX, startY);
                    drawLine(gc, startX, startY, startX, startY + 1);
                    drawLine(gc, startX, startY + 1, startX + 1, startY + 1);
                    break;
            }
        } else {
            switch (shape) {
                case 1:
                    showOrder(startX, startY, 2, order - 1, gc);
                    drawLine(gc, startX, startY + EXP[order - 1] - 1, startX, startY + EXP[order - 1]);
                    showOrder(startX, startY + EXP[order - 1], 1, order - 1, gc);
                    drawLine(gc, startX + EXP[order - 1] - 1, startY + EXP[order - 1], startX + EXP[order - 1], startY + EXP[order - 1]);
                    showOrder(startX + EXP[order - 1], startY + EXP[order - 1], 1, order - 1, gc);
                    drawLine(gc, startX + EXP[order] - 1, startY + EXP[order - 1], startX + EXP[order] - 1, startY + EXP[order - 1] - 1);
                    showOrder(startX + EXP[order - 1], startY, 4, order - 1, gc);
                    break;
                case 2:
                    showOrder(startX, startY, 1, order - 1, gc);
                    drawLine(gc, startX + EXP[order - 1] - 1, startY, startX + EXP[order - 1], startY);
                    showOrder(startX + EXP[order - 1], startY, 2, order - 1, gc);
                    drawLine(gc, startX + EXP[order - 1], startY + EXP[order - 1] - 1, startX + EXP[order - 1], startY + EXP[order - 1]);
                    showOrder(startX + EXP[order - 1], startY + EXP[order - 1], 2, order - 1, gc);
                    drawLine(gc, startX + EXP[order - 1] - 1, startY + EXP[order] - 1, startX + EXP[order - 1], startY + EXP[order] - 1);
                    showOrder(startX, startY + EXP[order - 1], 3, order - 1, gc);
                    break;
                case 3:
                    showOrder(startX, startY + EXP[order - 1], 2, order - 1, gc);
                    drawLine(gc, startX, startY + EXP[order - 1], startX, startY + EXP[order - 1] - 1);
                    showOrder(startX, startY, 3, order - 1, gc);
                    drawLine(gc, startX + EXP[order - 1] - 1, startY + EXP[order - 1] - 1, startX + EXP[order - 1], startY + EXP[order - 1] - 1);
                    showOrder(startX + EXP[order - 1], startY, 3, order - 1, gc);
                    drawLine(gc, startX + EXP[order] - 1, startY + EXP[order - 1] - 1, startX + EXP[order] - 1, startY + EXP[order - 1]);
                    showOrder(startX + EXP[order - 1], startY + EXP[order - 1], 4, order - 1, gc);
                    break;
                case 4:
                    showOrder(startX + EXP[order - 1], startY, 1, order - 1, gc);
                    drawLine(gc, startX + EXP[order - 1], startY, startX + EXP[order - 1] - 1, startY);
                    showOrder(startX, startY, 4, order - 1, gc);
                    drawLine(gc, startX + EXP[order - 1] - 1, startY + EXP[order - 1] - 1, startX + EXP[order - 1] - 1, startY + EXP[order - 1]);
                    showOrder(startX, startY + EXP[order - 1], 4, order - 1, gc);
                    drawLine(gc, startX + EXP[order - 1] - 1, startY + EXP[order] - 1, startX + EXP[order - 1], startY + EXP[order] - 1);
                    showOrder(startX + EXP[order - 1], startY + EXP[order - 1], 3, order - 1, gc);
                    break;
            }
        }
    }

    private void drawLine(GraphicsContext gc, int x1, int y1, int x2, int y2) {
        gc.strokeLine(MARGIN + x1 * segX, MARGIN + y1 * segY, MARGIN + x2 * segX, MARGIN + y2 * segY);
    }
}
  • 代码逻辑解释

1. 初始化与布局
  • 变量初始化:定义了一些常量(如窗口的宽度和高度、边距等)和数组EXP,用于存储2的幂次方值,方便后续计算。
  • UI组件创建:创建了一个文本输入框(TextField)用于输入阶数,一个标签(Label)用于提示用户输入,一个画布(Canvas)用于绘制曲线,以及相关的布局组件(HBoxVBox)。
  • 事件处理:为文本输入框设置了一个键盘事件监听器,当用户按下回车键并且输入的内容是有效的整数时,会根据输入的阶数来绘制希尔伯特曲线。
2. 绘制逻辑
  • showOrder方法:这是绘制希尔伯特曲线的核心方法,它根据阶数(order)和当前绘制的形状(shape,用1到4表示四种不同的递归方向)来递归地绘制曲线。当阶数为1时,直接绘制基础的四段直线;当阶数大于1时,根据递归规则和当前形状来决定下一步的绘制方向和位置。

  • 递归规则:对于每个阶数大于1的情况,showOrder方法会根据当前的shape值选择一种递归模式,每种模式都会先递归绘制子曲线,然后绘制连接子曲线的线段,最后继续递归绘制其他子曲线。这种递归模式确保了曲线能够填充整个二维空间,并且保持了曲线的连续性。

  • drawLine方法:这是一个辅助方法,用于在画布上绘制线段。它接收线段的起点和终点坐标,然后考虑到边距和当前阶数的线段长度(segXsegY),计算出实际绘制时的坐标,并使用GraphicsContext对象的strokeLine方法来绘制线段。

3. 绘制过程
  • 当用户输入阶数并按下回车键时,程序会首先验证输入的有效性,然后根据输入的阶数初始化线段长度(segXsegY),这两个值用于计算实际绘制时线段的像素长度。
  • 接着,程序会调用showOrder方法来开始绘制曲线。在绘制过程中,会根据递归规则和当前形状逐步绘制出整个希尔伯特曲线。
  • 每次递归调用都会将画布上的已绘制内容缩小到当前子曲线的范围,并通过调整坐标来确保子曲线能够正确地绘制在父曲线的指定位置。

  • 输出结果

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

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

相关文章

0108 Spring Boot启动过程

Spring Boot 的启动过程可以分为以下几个关键步骤&#xff1a; 1. SpringApplication 初始化 Spring Boot 应用的启动是通过调用 SpringApplication.run() 方法完成的。在这个过程中&#xff0c;Spring Boot 会通过 SpringApplication 类对应用进行初始化&#xff0c;包括设置…

ERP系统委外工单管理

1. 委外工单管理概念 1.1 定义与目的 委外工单管理是ERP系统中的一个关键组成部分&#xff0c;它涉及到将企业内部无法或不宜自行完成的生产任务&#xff0c;通过工单的形式委托给外部供应商进行加工、制造或服务的过程。委外工单管理的目的在于优化资源配置、降低生产成本、…

【Qt+Python项目构建】- 01-首次配置 Qt Creator 14.01 for Python

前言&#xff1a; 如何用QT实现Python的配置的交互界面。本文从0开始&#xff0c;进行实践的介绍。 在上一节里面&#xff0c;我们做了社区版本的配置&#xff1a; https://blog.csdn.net/yellow_hill/article/details/142597007?spm1001.2014.3001.5501 这一节&#xff0…

Android开发仿抖音底部加载进度条

Android开发仿抖音底部加载进度条 仿抖音底部加载进度条&#xff0c;从中间向两头伸的动画 一、思路&#xff1a; 自定义VideoLoadingBar控件 二、效果图&#xff1a; 三、关键代码&#xff1a; // 联系&#xff1a;893151960 public class VideoLoadingBar extends View …

阿布量化:基于 Python 的量化交易框架

阿布量化&#xff08;AbuQuant&#xff09; 是一个开源的量化交易框架&#xff0c;专为金融领域的研究者和交易者设计。它基于 Python 语言开发&#xff0c;提供了一整套从数据获取、策略开发、回测分析到交易执行的解决方案。阿布量化不仅能够帮助用户快速实现量化策略的设计与…

IDEA:Picked up _JAVA_OPTIONS: -Xmx512M

_JAVA_OPTIONS 是一个环境变量&#xff0c;它可以用来设置 Java 虚拟机的启动参数 如果要取消它在idea中显示&#xff0c;如图所示将其删除即可

C# 游戏引擎中的协程

前言 书接上回&#xff0c;我谈到了Unity中的协程的重要性&#xff0c;虽然协程不是游戏开发“必要的”&#xff0c;但是它可以在很多地方发挥优势。 为了在Godot找回熟悉的Unity协程开发手感&#xff0c;不得不自己做一个协程系统&#xff0c;幸运的是&#xff0c;有了Unity的…

MongoDB 工具包安装(mongodb-database-tools)

首先到官网下载工具包&#xff0c;进入下面页面&#xff0c;复制连接地址&#xff0c;使用wget下载 cd /usr/local/mongodb5.0.14/wget https://fastdl.mongodb.org/tools/db/mongodb-database-tools-rhel70-x86_64-100.6.1.tgz 安装 tar -zxvf mongodb-database-tools-rhel70-…

26个用好AI大模型的提示词技巧

如果你已深入探索过ChatGPT、Microsoft Copilot、风变AI等前沿的生成式AI工具&#xff0c;那么你对“prompt”&#xff08;提示词&#xff09;这一核心概念一定有自己的认知。 作为连接你与AI创意源泉的桥梁&#xff0c;“prompt”不仅是触发无限想象的钥匙&#xff0c;更是塑…

基于SSM的校园自助洗衣系统【附源码】

基于SSM的校园自助洗衣系统&#xff08;源码L文说明文档&#xff09; 目录 4 系统设计 4.1 设计原则 4.2 功能结构设计 4.3 数据库设计 4.3.1 数据库概念设计 4.3.2 数据库物理设计 第5章 系统实现 5.1 管理员功能实现 5.1.1 洗衣机管理…

远程服务器安装anaconda并创建虚拟环境

1、承接上文新用户zrcs&#xff0c;在服务器的zrcs文件夹下直接下载anaconda&#xff08;很慢&#xff09;&#xff1a; wget https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh 或者选择本地下载&#xff0c;清华大学开源软件镜像站&#xff1a;https:/…

ACDsee简体中文版网盘资源下载(含教程)

如大家所熟悉的&#xff0c;ACDSee是一款集看图、编辑和管理于一体的软件&#xff0c;其凭借着打开速度快、管理功能强、操作界面友好简单等等优势&#xff0c;广受用户的喜欢。目前最新为ACDSee 2024版本。 一、文件管理 ACDSee数据库在文件管理方面表现出色。它可以帮助用户…

vscode编辑区看不清光标

打开 “控制面板”-“鼠标”-“指针”-“自定义”-“文本选择” 在浏览中选择“beam_r.cur”&#xff0c;打开后确认应用

GIS开发工程师岗位职责、技术要求和常见面试题

GIS 开发工程师负责运用地理信息系统专业知识和编程技能&#xff0c;进行 GIS 软件设计、开发、数据处理与管理&#xff0c;以实现高效的地理空间信息系统应用。 一、岗位职责 系统开发与设计 负责地理信息系统&#xff08;GIS&#xff09;相关软件的设计、开发、测试和维护工…

智能绘画,体现非凡想象力以文生图功能简单操作

智能绘画&#xff0c;体现非凡想象力以文生图功能简单操作 智能绘画技术突破了人类自身的极限&#xff0c;让绘画分析进入到一个更为广泛的视野中。通过输入描述性的文字&#xff0c;便可生成便可生成同一主题、不同风格的画作&#xff0c;体现出非凡的想象力&#xff0c;象征未…

【网络安全 白帽子】用技术合法挖漏洞,一个月能拿多少钱

现在很多白帽子&#xff08;网安工程师/渗透测试工程师&#xff09;都会在下班之后利用业余时间去补天之类的漏洞赏金平台挖漏洞&#xff0c;用技术合法给企业找出威胁存在&#xff0c;拿到漏洞赏金。 那么现在&#xff0c;一般人用网安技术挖漏洞一个月能拿多少钱&#xff1f…

【Mybatis Plus】分页插件

1.配置分页插件 Configuration public class MyBatisConfig {Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor new MybatisPlusInterceptor();//1.创建分页插件PaginationInnerInterceptor paginationInnerInterceptor new…

Unity实战案例全解析:RTS游戏的框选和阵型功能(2) 生成选择框

前篇&#xff1a;Unity实战案例全解析&#xff1a;RTS游戏的框选和阵型功能&#xff08;1&#xff09; 基础要素-CSDN博客 本案例来源于unity唐老狮&#xff0c;有兴趣的小伙伴可以去泰克在线观看该课程 【唐老狮】Unity实现 即时战略游戏 阵型功能 - 泰课在线 -- 志存高远&…

深刻理解Redis集群(上):RDB快照和AOF日志

RDB快照 save同步阻塞 客户端 服务端 .conf配置文件 # The filename where to dump the DB dbfilename dump.rdb# rdb-del-sync-files是Redis配置文件中的一个选项&#xff0c;它的作用是在主节点上执行BGSAVE或AOF持久化操作时&#xff0c;删除同步锁文件&#xff0c;以释放磁…

结婚证识别-离婚证识别接口-结婚证识别API应用场景

在信息化与智能化高速发展的今天&#xff0c;证件的自动识别技术逐渐成为了各行各业数字化转型的关键工具&#xff0c;而结婚证识别接口、离婚证识别接口正在悄然改变着传统的民政工作方式。 结婚证识别与离婚证识别接口是基于光学字符识别&#xff08;OCR&#xff09;技术的智…