Java 开发实例(第3篇),绘制迷宫1 生成迷宫地图

article/2025/3/11 9:23:59

开发环境:
操作系统Win10。
1.下载Java 15,提取码:soft
2.下载软件 Eclipse 2020-12,提取码:soft

下载本博客的实例工程代码,提取码:soft

        前天2月9日在逛B站App时,意外看到一个很有意思的视频,Up“暗流啊暗流”通过视频讲了一个迷宫算法,看得手痒难耐,就花了一些时间写了这么一个迷宫算法最基本应用—即生成迷宫。
        简单来讲,生成迷宫就是一个砸墙的过程,砸墙规则可以归纳为以下三点:
         1,只有当隔壁房间没去过的时候,墙才可以砸
         2,无墙可砸的时候,就传送到一个去过的房间里
         3,每一个房间都要到达
        有想了解迷宫算法更多应用的,可以到这里去看视频,从迷宫生成算法到创意编程

代码实现粗糙,水平有限,如果有更好的实装方案,可以精简代码,或更加灵巧可扩展,等等,欢迎批评指正,提建议。

文章目录

  • 1. 工程目录结构
  • 2. 代码内容
    • 2.1 主启动类 StartFrame.java
    • 2.2 迷宫类 Maze.java
    • 2.3 迷宫房间类 MazeMember.java
  • 3. 运行效果

1. 工程目录结构

在这里插入图片描述

2. 代码内容

2.1 主启动类 StartFrame.java

package maze.view;import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;/*** 用迷宫算法,随机生成迷宫* 思想:生成迷宫的过程就是一个在小方格里砸墙的过程* 迷宫算法规则:*     1,只有当隔壁房间没去过的时候,墙才可以砸*     2, 无墙可砸的时候,就传送到一个去过的房间里*     3, 每一个房间都要到达* @author 见瑞彬**/
public class StartFrame extends JFrame implements ActionListener {/** 序列ID */private static final long serialVersionUID = 1L;private int frameX = 0;private int frameY = 0;private int frameW = 800;private int frameH = 700;/** 迷宫类 */private Maze mazeObject;/** 迷宫区域 */private Rectangle mazeArea;/** 按钮<<重新生成迷宫>> */private JButton remakeMazeButton;private JTextField rowCountField;private JTextField colCountField;private JLabel rowCountLabel;// 居中{Dimension clientSize = Toolkit.getDefaultToolkit().getScreenSize();frameX = (int) ((clientSize.getWidth() - frameW) / 2);frameY = (int) ((clientSize.getHeight() - frameH) / 2);// 设定迷宫mazeObject = new Maze();// 设定迷宫区域mazeArea = new Rectangle(20, 80, 600, 600);}public StartFrame() {// 设定布局FlowLayout flow = new FlowLayout();flow.setAlignment(FlowLayout.LEFT);this.setLayout(flow);// 添加按钮remakeMazeButton = new JButton("重新生成迷宫");remakeMazeButton.addActionListener(this);this.add(remakeMazeButton);// 设定水平垂直的方格数rowCountLabel = new JLabel("水平方格数");this.add(rowCountLabel);rowCountField = new JTextField(6);this.add(rowCountField);// 窗体属性this.setBounds(frameX, frameY, frameW, frameH);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);this.validate();}/*** 重绘窗体*/@Overridepublic void paint(Graphics g) {super.paint(g);drawMaze(g);}/*** 画迷宫* * @param g*/private void drawMaze(Graphics g) {// 迷宫线颜色g.setColor(Color.RED);// 画迷宫区域边线g.drawRect(mazeArea.x, mazeArea.y, mazeArea.width, mazeArea.height);// 取得每个方格宽度和高度int width = mazeArea.width / mazeObject.getRowCount();int height = mazeArea.height / mazeObject.getColCount();// 绘制迷宫元素MazeMember[][] mazeTable = mazeObject.create();// 设定左上角方格为起点mazeTable[0][0].setMazeMemberId(MazeMember.ID.VISITOR);// 设定右下角方格为终点mazeTable[mazeObject.getRowCount() - 1][mazeObject.getColCount() - 1].setMazeMemberId(MazeMember.ID.TARGET);// 遍历迷宫区域的所有方格for (int i = 0; i < mazeObject.getRowCount(); i++) {for (int j = 0; j < mazeObject.getColCount(); j++) {// 迷宫水平坐标int x = mazeArea.x + width * j;// 迷宫垂直坐标int y = mazeArea.y + height * i;// 获得迷宫方格对象MazeMember mazeMember = mazeTable[i][j];// 绘制方格中表示的边,隐藏不表示的边。mazeMember.drawMazeMember(g, x, y, width, height);}}}public static void main(String[] args) {// TODO Auto-generated method stubStartFrame mf = new StartFrame();}@Overridepublic void actionPerformed(ActionEvent e) {if (e.getSource() == this.remakeMazeButton) {// 修改迷宫的水平或垂直方格数量try {mazeObject.setColCount(Integer.parseInt(rowCountField.getText()));mazeObject.setRowCount(Integer.parseInt(rowCountField.getText()));} catch (Exception e1) {if(mazeObject.getColCount() == 0) {mazeObject.setColCount(10);mazeObject.setRowCount(10);}}// 重绘迷宫this.repaint();}}}

2.2 迷宫类 Maze.java

package maze.view;import java.util.ArrayList;
import java.util.List;/*** 迷宫对象* * @author 见瑞彬**/
public class Maze {/** 迷宫成员对象数组 */private MazeMember[][] mazeTable;/** 迷宫成员对象水平数量 */private int rowCount;/** 迷宫成员对象垂直数量 */private int colCount;/** 迷宫访问者垂直方向坐标 */private int visitorVertical = 0;/** 迷宫访问者水平方向坐标 */private int visitorHorizontal = 0;public Maze() {// 初始化方格数量 5*5rowCount = 5;colCount = 5;}/*** 创建迷宫* * @return*/public MazeMember[][] create() {// 初始化迷宫的每一个成员对象mazeTable = new MazeMember[rowCount][colCount];for (int i = 0; i < rowCount; i++) {for (int j = 0; j < colCount; j++) {mazeTable[i][j] = new MazeMember();mazeTable[i][j].setTopLineShow(true);mazeTable[i][j].setBottomLineShow(true);mazeTable[i][j].setLeftLineShow(true);mazeTable[i][j].setRightLineShow(true);}}// 初始化迷宫访问者位置(0,0)visitorVertical = 0;visitorHorizontal = 0;mazeTable[0][0].setVisited(true);// 遍历所有迷宫成员对象,并进行迷宫成员对象的推墙操作while (!hasFinishMazeTable()) {// 迷宫访问者前进到下一步boolean visitorMoveSuccess = moveToNextStep(visitorVertical, visitorHorizontal);// 迷宫访问者前进失败场合if (!visitorMoveSuccess) {// 重新定位迷宫访问者的位置// 跳跃到曾经访问过的迷宫成员对象的位置updateVisitorPoint();}}// 迷宫成员对象数组return mazeTable;}/*** 迷宫访问者是否访问完所有迷宫成员对象* * @return*/private boolean hasFinishMazeTable() {for (int i = 0; i < rowCount; i++) {for (int j = 0; j < colCount; j++) {if (!mazeTable[i][j].isVisited()) {return false;}}}return true;}/*** 抹去相邻的没有访问过的成员边界,并更新访问者位置* * @param nowLocation* @return*/private boolean moveToNextStep(int vertical, int horizontal) {// 存储当前迷宫访问者位置的周围的上下左右四个位置// 避免随机到重复的位置List<Integer> locationLib = new ArrayList<>();// 遍历周围while (true) {// 所有相邻位置已经遍历完成,该成员不存在未访问过的相邻成员,终止遍历if (locationLib.size() == 4) {return false;}// 随机生成一个迷宫成员的上下左右相邻成员的序号// 0上 1下 2左 3右int locIndex = (int) (Math.random() * 4);// 下一个相邻位置if (!locationLib.contains(locIndex)) {locationLib.add(locIndex);// 上if (locIndex == 0) {// 移动到上面一个位置if (moveTop(vertical, horizontal)) {return true;}// 下} else if (locIndex == 1) {// 移动到下面一个位置if (moveBottom(vertical, horizontal)) {return true;}// 左} else if (locIndex == 2) {// 移动到左面一个位置if (moveLeft(vertical, horizontal)) {return true;}// 右} else {// 移动到右面一个位置if (moveRight(vertical, horizontal)) {return true;}}}}}/*** 防止迷宫访问者出界* * @param vertical* @param horizontal* @return*/private boolean isRightPoint(int vertical, int horizontal) {if (vertical >= 0 && vertical < rowCount && horizontal >= 0 && horizontal < colCount) {// 不出界,返回truereturn true;}// 出界返回falsereturn false;}/*** 向上移动* * @param vertical* @param horizontal* @return*/private boolean moveTop(int vertical, int horizontal) {int nextVertical = vertical - 1;int nextHorizontal = horizontal;if (isRightPoint(nextVertical, nextHorizontal)) {// 未访问过场合if (!mazeTable[nextVertical][nextHorizontal].isVisited()) {// 上面的边隐藏mazeTable[vertical][horizontal].setTopLineShow(false);// 相邻成员对象,下面的边隐藏mazeTable[nextVertical][nextHorizontal].setBottomLineShow(false);// 相邻成员对象,标记为已访问mazeTable[nextVertical][nextHorizontal].setVisited(true);// 更新迷宫访问者位置visitorVertical = nextVertical;visitorHorizontal = nextHorizontal;return true;}}return false;}/*** 向下移动* * @param vertical* @param horizontal* @return*/private boolean moveBottom(int vertical, int horizontal) {int nextVertical = vertical + 1;int nextHorizontal = horizontal;if (isRightPoint(nextVertical, nextHorizontal)) {// 未访问过场合if (!mazeTable[nextVertical][nextHorizontal].isVisited()) {// 下面的边隐藏mazeTable[vertical][horizontal].setBottomLineShow(false);// 相邻成员对象,上面的边隐藏mazeTable[nextVertical][nextHorizontal].setTopLineShow(false);// 相邻成员对象,标记为已访问mazeTable[nextVertical][nextHorizontal].setVisited(true);// 更新迷宫访问者位置visitorVertical = nextVertical;visitorHorizontal = nextHorizontal;return true;}}return false;}/*** 向左移动* * @param vertical* @param horizontal* @return*/private boolean moveLeft(int vertical, int horizontal) {int nextVertical = vertical;int nextHorizontal = horizontal - 1;if (isRightPoint(nextVertical, nextHorizontal)) {// 未访问过场合if (!mazeTable[nextVertical][nextHorizontal].isVisited()) {// 左面的边隐藏mazeTable[vertical][horizontal].setLeftLineShow(false);// 相邻成员对象,右面的边隐藏mazeTable[nextVertical][nextHorizontal].setRightLineShow(false);// 相邻成员对象,标记为已访问mazeTable[nextVertical][nextHorizontal].setVisited(true);// 更新迷宫访问者位置visitorVertical = nextVertical;visitorHorizontal = nextHorizontal;return true;}}return false;}/*** 向左移动* * @param vertical* @param horizontal* @return*/private boolean moveRight(int vertical, int horizontal) {int nextVertical = vertical;int nextHorizontal = horizontal + 1;if (isRightPoint(nextVertical, nextHorizontal)) {// 未访问过场合if (!mazeTable[nextVertical][nextHorizontal].isVisited()) {// 右面的边隐藏mazeTable[vertical][horizontal].setRightLineShow(false);// 相邻成员对象,左面的边隐藏mazeTable[nextVertical][nextHorizontal].setLeftLineShow(false);// 相邻成员对象,标记为已访问mazeTable[nextVertical][nextHorizontal].setVisited(true);// 更新迷宫访问者位置visitorVertical = nextVertical;visitorHorizontal = nextHorizontal;return true;}}return false;}/*** 迷宫访问者的位置,随机更新到曾经访问过的成员对象的位置* * @return*/private void updateVisitorPoint() {while (true) {int visitorVertical = (int) (Math.random() * rowCount);int visitorHorizontal = (int) (Math.random() * colCount);// 已访问if (mazeTable[visitorVertical][visitorHorizontal].isVisited()) {// 更新位置this.visitorVertical = visitorVertical;this.visitorHorizontal = visitorHorizontal;// 标记已访问mazeTable[visitorVertical][visitorHorizontal].setVisited(true);break;}}}/*** 取得垂直数量* * @return 垂直数量*/public int getRowCount() {return rowCount;}/*** 修改垂直数量* * @param 垂直数量*/public void setRowCount(int rowCount) {this.rowCount = rowCount;}/*** 取得水平数量* * @return 水平数量*/public int getColCount() {return colCount;}/*** 修改水平数量* * @param 水平数量*/public void setColCount(int colCount) {this.colCount = colCount;}}

2.3 迷宫房间类 MazeMember.java

package maze.view;import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;public class MazeMember {public static enum ID {// 一般NORMAL,// 起点访问者VISITOR,// 终点目标TARGET};/** 是否访问过 */private boolean visited;/** 是否显示上面的边 */private boolean topLineShow;/** 是否显示下面的边 */private boolean bottomLineShow;/** 是否显示左面的边 */private boolean leftLineShow;/** 是否显示右面的边 */private boolean rightLineShow;/** 定义成员的身份 */private ID mazeMemberId;public MazeMember() {// 默认所有成员为一般mazeMemberId = ID.NORMAL;}public void drawMazeMember(Graphics g, int x, int y, int width, int height) {// 绘画上面的边if (topLineShow) {g.drawLine(x, y, x + width, y);}// 绘画下面的边if (bottomLineShow) {g.drawLine(x, y + height, x + width, y + height);}// 绘画左面的边if (leftLineShow) {g.drawLine(x, y, x, y + height);}// 绘画右面的边if (rightLineShow) {g.drawLine(x + width, y, x + width, y + height);}// 设定字体Font font = g.getFont();g.setFont(new Font(font.getFamily(), font.getStyle(), 20));// 绘画起点图案if (this.getMazeMemberId() == ID.VISITOR) {Color c = g.getColor();g.setColor(Color.GREEN);g.fillRect(x, y, width, height);g.setColor(c);}// 绘画终点图案if (this.getMazeMemberId() == ID.TARGET) {Color c = g.getColor();g.setColor(Color.MAGENTA);g.fillRect(x, y, width, height);g.setColor(c);}// 还原字体g.setFont(font);}/*** @return the mazeMemberId*/public ID getMazeMemberId() {return mazeMemberId;}/*** @param mazeMemberId the mazeMemberId to set*/public void setMazeMemberId(ID mazeMemberId) {this.mazeMemberId = mazeMemberId;}/*** @return the visited*/public boolean isVisited() {return visited;}/*** @param visited the visited to set*/public void setVisited(boolean visited) {this.visited = visited;}/*** @param topLineShow the topLineShow to set*/public void setTopLineShow(boolean topLineShow) {this.topLineShow = topLineShow;}/*** @param bottomLineShow the bottomLineShow to set*/public void setBottomLineShow(boolean bottomLineShow) {this.bottomLineShow = bottomLineShow;}/*** @param leftLineShow the leftLineShow to set*/public void setLeftLineShow(boolean leftLineShow) {this.leftLineShow = leftLineShow;}/*** @param rightLineShow the rightLineShow to set*/public void setRightLineShow(boolean rightLineShow) {this.rightLineShow = rightLineShow;}}

3. 运行效果

运行 StartFrame.java,启动画面
在这里插入图片描述
更改水平方格数至更多,并点击“重新生成迷宫”按钮,效果如下
在这里插入图片描述


http://chatgpt.dhexx.cn/article/yHHhttPZ.shtml

相关文章

Python 打印迷宫地图小游戏

在实现玩转小迷宫这个游戏时&#xff0c;分别使用了input()输入函数、print()输出函数、if…elif…else语句、二维列表、while循环、for循环 下面对这些用法再一次重温 1.input()输入函数 在 Python 中&#xff0c;使用内置函数 input() 可以接收用户的键盘输入。input() 函数…

html5的canvas绘制迷宫地图

canvas标签一直是html5的亮点,用它可以实现很多东西。我想用它来绘画像迷宫那样的地图。借助到的工具有瓦片地图编辑器tiled(点击跳转到下载链接)。 如图:如果你想要画像这样的迷宫地图,如果不用canvas,可以通过dom操作拼接一个一个div,以达成这个效果。那样是不是很不合…

深度优先,Kruskal,Prim几种方式生成迷宫地图

小时候玩过一款3D版迷宫&#xff0c;那时还是功能机时代&#xff0c;黑白界面拼凑的伪3D效果还是给我带来了很多快乐。后来出现了智能机&#xff0c;却再也没找到过那样纯粹的迷宫游戏。总算自己找时间做一个出来。 本文主要介绍一下深度优先&#xff0c;Kruskal,Prim几种方式生…

二维数组随机生成地图迷宫_经验分享:三套简单的迷宫地图生成方案

文/兔四 概述:文章基于一种基础的地图,来讨论三套不同的地图生成方案。 文章不会出现跟代码相关的内容,会以较为通俗的语句和不少简单的示意图来表示迷宫的生成方案。其中不少方法来自于游戏界前辈,我根据自己的基础地图做了不少修正(毕竟迷宫和地图的形式多种多样,适合自…

算法自动生成迷宫地图

文章目录 前言一、什么是&#xff08;DFS&#xff09;深度优先算法&#xff1f;深度优先算法实现步骤1.引入库2.初始化参数3.Turtle画方格函数4.开始生成数组并调用Turtle画图 二、什么是&#xff08;BFS&#xff09;广度优先算法&#xff1f;广度优先算法实现步骤1.引入库2.初…

【工具篇】Unity迷宫地图生成器MazeSpawner随机迷宫信手拈来

目录 一.迷宫生成效果 二.使用流程 三.使用场景 四.源码地址 一.迷宫生成效果 二.使用流程 1.导入后结构目录如下,打开prefab文件夹找到MazeSpawner放进场景里面

C++实现随机生成迷宫地图自动完成寻径

#include<iostream> #include<stack> #include<vector> using namespace std;template<class T> class Maze { public:Maze( //默认参数值pair<int, int> initSize make_pair(15, 17),pair<string, string> initStyle m…

Python 制作迷宫游戏(一)——地图

Python 制作迷宫游戏&#xff08;一&#xff09;——地图 序 作为一个迷宫类的游戏&#xff0c;其最重要的是什么&#xff1f;当然是它的地图啦♪(∇*) 那么我们又该如何制作一张迷宫地图呢⊙(・◇・)&#xff1f; 很显然&#xff0c;我们不可能一张张自己画吧 网络上常见的迷…

三套简单的迷宫地图生成方案

地图基础 地图的形式很多&#xff0c;这里我使用的地图是以tile块为单位分割的地图&#xff0c;地图上的tile块形式很多&#xff0c;但主要分成三种&#xff1a; A&#xff1a;陆地&#xff0c;可以在上面分布一些角色啦物件啦&#xff1b; B&#xff1a;过渡&#xff0c;根据物…

SenticNet情感词典介绍

在进行情感分析时&#xff0c;一个好的情感词典能够让我们的工作事半功倍&#xff0c;较为出名的情感词典有SentiWordNet&#xff0c;General Inquirer等&#xff0c;这篇博客将介绍另外一个出色情感词典&#xff0c;SenticNet。 简介 当谈论SenticNet时&#xff0c;我们正在…

中文金融领域情感词典构建

2019年10月4日-6日 Python爬虫与文本分析工作坊 & 课题申报高级研修班 这篇文章是公众号关注者郝童鞋今早发给我的&#xff0c;在此谢谢郝童鞋。 文章基于简单算法和人工判断&#xff0c;使用多阶段剔除法&#xff0c;构建了 中文金融情感词典CFSD&#xff08;ChineseFinan…

《学术小白的学习之路 02》情感分析02 之基于大连理工情感词典的情感分析和情绪计算

本文主要是学习参考杨秀璋老师的博客,笔记总结。 原文链接 文章目录 书山有路勤为径&#xff0c;学海无涯苦作舟原文链接一.大连理工情感词典二、七种情绪的计算2.1 pandas读取数据2.2 导入大连理工大学中文情感词典2.3 统计七种情绪的分布情况2.4 增加中文分词词典和自定义的停…

中文情感词典的构建

首先&#xff0c;国外英文的情感分析已经取得了很好的效果&#xff0c;得益于英文单词自身分析的便捷性与英文大量的数据集 WordNet。但由于中文的多变性&#xff0c;语义的多重性与数据集的缺乏&#xff0c;使得国内的情感分析暂落后于国外。本文将记录博主在项目中构建情感词…

基于情感词典的网络文本情感倾向分类模型

目录 前言一、模型构建1.归类2.判定3.输出 二、代码实现三、结果展示 前言 文本情感倾向性分析&#xff08;也称为意见挖掘&#xff09;是指识别和提取原素材中的主观信息&#xff0c;并对带有感情色彩的文本进行分析处理和归纳推理的过程。主要用于实时社交媒体的内容&#xf…

使用SO-PMI算法构建行业/专业情感词典

文章目录 1. 情感词典内容2. 情感倾向点互信息算法&#xff08;SO-PMI&#xff09;算法点互信息算法 PMI情感倾向点互信息算法 SO-PMI 3. 构建情感词典1. 导入项目2. 构建情感种子词3. 使用TF-IDF方便构建情感种子词4. 构建专业词典的效果与使用方法5. 其他说明 1. 情感词典内容…

在微雕中使用的电脑设计

需求是我们要在铜器上复刻很小的凹印,可以选用的技术方案还是很多:激光雕刻,篆刻、钢印。 激光雕刻有利有弊,前期复制是最方便的,激光雕刻有专门的设计软件,可以很轻松的把自己的图案运用到机器上去。制作和时间的成本都非常的低,但是激光对金属的雕刻有一个大大的缺点…

闲人闲谈PS之四十二——顾问的“禁忌之地”—制造能力计划

惯例闲话&#xff1a;上个月有幸成为乐老师乐谈IT系列培训课程的讲师&#xff0c;分享主题是&#xff0c;PS在装备制造和工程行业的应用。虽然培训规模不是很大&#xff0c;但是闲人很有信心&#xff0c;至少在小范围之内&#xff0c;参与培训的听友人来说&#xff0c;PS一直以…

ibm x201 怎么清理内部_ThinkPad X201拆解,联想Thinkpad X201拆机图解

1.jpg (25.79 KB, 下载次数: 2552) 2010-6-1 20:13 上传 ThinkPad X201掌托&#xff0c;没有防滚架&#xff0c;这个掌托就显得很软。电磁屏蔽做得很用心。 2.jpg (39.16 KB, 下载次数: 2556) 2010-6-1 20:13 上传 ThinkPad X201掌托特写&#xff0c;可以看到掌托塑料件是MITSU…

学习opencv:PS滤镜—浮雕

实现浮雕效果的算子有很多&#xff0c;效果大同小异&#xff0c;不同算子的处理结果在细节上会有所差异。事实上&#xff0c;任何一阶差分算子都可用于实现浮雕效果&#xff0c;简单起见&#xff0c;这里使用算子[-1,1]。 代码如下 #include<iostream> #include <…

ps给图片加钢印方法

给图片加一个钢印其实很简单 这样的效果只能类似钢印 简单可以按照下面的方法 准备资料 &#xff1a;一个要加钢印的图片 一个透明印章即可实现 方法&#xff1a;斜面和浮雕 一、打开图片 二、打开透明印章 三、将透明印章移动到图片中 四、进行图层设置 右击印章图层---混合…