首页 > 其他分享 > 电脑迷宫鼠----功能实现

电脑迷宫鼠----功能实现

时间:2023-07-03 16:44:56浏览次数:49  
标签:ints int 迷宫 电脑 ---- list && new

电脑迷宫鼠

功能实现

1. 迷宫的生成

  • 自动生成迷宫

    算法介绍:网上有着各种各样的迷宫生成算法,我只是用了一种迷宫的生成算法-->prim算法

    该算法并不复杂,请自行到哔哩哔哩上找讲解视频进行学习,在这里展示一下java语言的实现方式

    			// 迷宫的行数和列数
    private void prim(int row, int col){
          //成员变量
            row = row == 0 ? 59 : row;
            col = col == 0 ? 59 : col;
           // 移动的四个方向                 
            int[][] go = new int[][]{
                    {-2,0},
                    {0,2},
                    {2,0},
                    {0,-2}
            };
            // 存放待选路点
            LinkedList<int[]> list = new LinkedList<>();
        // 最后生成的迷宫,成员变量
            maze[1][1] = 0;
            for (int[] way : go) {
                int x = way[0] + 1;
                int y = way[1] + 1;
                if(x > 0 && x < row - 1 && y > 0 && y < col - 1){
                    list.add(new int[]{x,y});
                }
            }
    
            while (!list.isEmpty()){
                // 随机选择到的路点 A
                int rand = random.nextInt(list.size());
                int[] next = list.get(rand);
    
                // A 附近已经变成路点的B
                List<int[]> ran = new LinkedList<>();
                // A 附近没有变成路点的位置
                List<int[]> notRan = new LinkedList<>();
                
                for (int[] way : go) {
                    int x = way[0] + next[0];
                    int y = way[1] + next[1];
                    // 判断是否为合法位置
                    if(x > 0 && x < row - 1 && y > 0 && y < col - 1 ){
                        if(maze[x][y] == 0){
                            // 是路点
                            ran.add(new int[]{x,y});
                        }else {
                            // 不是路点
                            notRan.add(new int[]{x,y});
                        }
    
                    }
                }
                // 从B中随机选择一个路点,与A打通
                int[] B = ran.get(random.nextInt(ran.size()));
                // 将A 附近的(随机)路点 之间打通
                // A 变成 0
                maze[next[0]][next[1]] = 0;
                // 先将B 变成 0
                maze[B[0]][B[1]] = 0;
                // 将A与B之间的墙打碎
                if(next[0] == B[0]){ // 同行
                    // 中间的数字变成 0
                    int k = next[1] > B[1] ? next[1] - 1 : next[1] + 1;
                    maze[B[0]][k] = 0;
                }else {  // 同列
                    // 中间的数字变成 0
                    int k = next[0] > B[0] ? next[0] - 1 : next[0] + 1;
                    maze[k][B[1]] = 0;
                }
                // 将A 删除 并将A附近的非路点添加进来
                list.remove(rand);
                for (int[] ints : notRan) {
                    int i = 0;
                    for (; i < list.size(); i++) {
                        int[] have = list.get(i);
                        if(have[0] == ints[0] && have[1] == ints[1])break;
                    }
                    if(i == list.size()){
                        list.add(ints);
                    }
                }
    
            }
    
        }
    
  • 手动生成迷宫

    先自动生成几个,自己改变一些其中的位置即可。

    这里介绍如何将文件里的迷宫转换为二维数组

    // 形参是文件名
    private int[][] createMazeByTxt(File file) {
        // 默认迷宫的大小是59*59
            int[][] lab = new int[59][59];
            try {
                // 文件的读取有多种方式,可自行尝试
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
                // 读取一行,1,1,1,1,1,1,1,1,1,1,1,……1,1,1,1(这是在文件中的格式)
                String line = bufferedReader.readLine();
                if (line != null) {
                    for (int i = 0; i < 59; i++) {
                        String[] numbers = line.split(",");
                        for (int j = 0; j < 59; j++) {
                            // 将字符串转换为数字存储在迷宫的二维数组里
                            lab[i][j] = Integer.parseInt(numbers[j]);
                        }
                        // 继续读下一行
                        line = bufferedReader.readLine();
                    }
                }
                // 关闭资源
                bufferedReader.close();
            } catch (IOException e) {
                // 文件未找到异常
                System.out.println("文件未找到……");
            }
            return lab;
        }
    

2. 迷宫的寻路

  • 方法介绍:深度优先搜索(一条路走到黑,撞了南墙就返回,能行就收集,不行就放弃)

  • 代码展示

    // 遍历迷宫时的方向
        private int[][] ways = new int[][]{
                {-1, 0},
                {0, 1},
                {1, 0},
                {0, -1}
        };
    // 寻找到多条合适的路,从头到尾
        private void dfs(List<int[]> list, int x, int y, int ex, int ey) {
            // 走到终点了,进行结果的收集
            if (x == ex && y == ey) {
                // 将尾结点添加到集合里
                list.add(new int[]{x, y});
                List<int[]> path = new LinkedList<>(list);
                // paths是成员变量,用来收集所有结果
                paths.add(path);
                // 删除尾结点,回溯
                list.remove(list.size() - 1);
                return;
            }
    //			在当前节点的四个方向进行探索
            for (int[] ways : go) {
                int goX = ways[0] + x;
                int goY = ways[1] + y;
                // 要前往的节点是否合法
                if (goX > 0 && goX < ROW - 1 && goY > 0 && goY < COL - 1 && maze[goX][goY] == 0) {
                    //集合里添加节点
                    list.add(new int[]{x, y});
                    // 标记一下,避免下次还会进来,造成死循环
                    maze[x][y] = 2;
                    // 前往下一个节点
                    dfs(list, goX, goY, ex, ey);
                    // 回溯
                    maze[x][y] = 0;
                    list.remove(list.size() - 1);
                }
            }
        }
    
  • 注意:这里其实可以看做实现了迷宫的遍历,(毕竟找到了所有的路),如果是单一路径,可以利用随机数选一条进行展示。遍历有些许的不同。

3. 迷宫的遍历

  • 这里迷宫的遍历是按照我的理解来实现的,就是将迷宫寻路的过程可视化,即展示鼠是如何一步一步找到站点的。不难发现,老鼠找到终点的过程全部保存在了成员变量paths里面,只需要将其中的结点展示在界面上的颜色改变,既可以达到想要的效果。但问题也会随之而来,遍历结束后,界面上大约有一半被改变了颜色,非常难看,那么我想到的解决方法是将错误的位置的颜色改回来,即将回溯的过程也展示给读者。
  • 代码展示
// 这里涉及到多线程的知识,因为我也是突击学习,其中很多也并不理解,大家凑合着看
private void findSuperDfs() {
        Task<List<int[]>> task = new Task<List<int[]>>() {
            @Override
            protected List<int[]> call() throws Exception {
                // 一个私有方法,将界面的地图颜色恢复成开始的样子(黑白)
                paint();
                
                List<int[]> list = new LinkedList<>();
                // 这里是一个深度优先搜素,与上一个方法类似,只不过该方法在找到一条路径的情况下就结束了
                // 找到的路径保存在list里
                superDfs(list,1,1,ROW - 2,COL - 2);
                
                int k = 0;
                for (int[] ints : list) {
                    // 因为在遍历时maze的部分值被改为了2
                    // 将标记的坐标改回原来的值
                    maze[ints[0]][ints[1]] = 0;
                    k++;
                    //将坐标输出到控制台上
                    System.out.print(Arrays.toString(ints) + "  ");
                    // 换行
                    if((k + 1) % 10 == 0)
                        System.out.println();
                }
                System.out.println("集合的长度为:" +list.size());
                // 可视化过程
                info.clear();//info是界面的一个组件,用来展示遍历的过程
                for (int i = 0; i < list.size(); i++) {
                    int[] ints = list.get(i);
                    //info的展示内容进行定期清空
                    if (info != null && info.getText() != null &&  info.getText().length()>1000) {
                        info.clear();
                    }
                    if(i > 0){
                        // 判断第i号位置的坐标是不是已经出现过,是就返回那个坐标,不是就返回-1
                        int v = isValid(list,i);
                        if(v != -1){//有重复,
                            //在界面上输出信息
                            info.appendText("回退" + "\n");
                         
                            //将两个重复坐标间的坐标颜色进行改变(倒叙)
                            for (int j = i - 1; j >= v; j--){
                                // map集合放着坐标和坐标在list集合里的位置
                                //相同位置的坐标在map里只有一个
                                if(map.size() > 0 && map.containsKey(j)){
                                    int[] re = map.remove(j);
                                    //让当前的线程睡一觉,看起来寻路过程比较平滑
                                    Thread.sleep(35);
                                    //该方法将re[0] * COL + re[1]位置上的颜色改为Color.WHITE。
                                    reFresh(re[0] * COL + re[1],Color.WHITE);
                                }
                            }
                        }
                    }
					// map里放入当前的坐标即在list集合中的位置
                    map.put(i,ints);
                    int x = ints[0];
                    int y = ints[1];
                    //睡一觉
                    Thread.sleep(35);
                    //该方法将x * COL + y位置上的颜色改为Color.PURPLE
                    reFresh(x * COL + y,Color.PURPLE);
                    info.appendText("到达" + Arrays.toString(ints) + "\n");
                }
                System.out.println("可视化过程结束了");
                return list;
            }
        };
        Thread thread = new Thread(task,"supDfs");
        paint();
    	//开启任务
        thread.start();
    }

可以看见有许多的重复位置,说明两个重复位置之间的都是错误的位置(进行回溯了),想要将其展示在界面上的颜色改回来(倒叙)

4. 界面展示

  • 因为用到了SenceBuilder图形化工具,所以方法都写在了Controller里。

    手动创建迷宫

  • 自动创建迷宫

  • 遍历时

标签:ints,int,迷宫,电脑,----,list,&&,new
From: https://www.cnblogs.com/strind/p/17523258.html

相关文章

  • MacBook pro今天开机屏幕不亮了,其它什么都好的,键盘也亮的,声音软件都好的
    背景MacBookpro前两天从柜子上摔下来了,开机后发现屏幕不亮,其余的键盘灯,开机声音,显示器背面的logo也是亮的。自己试了很多网上的方法都不行。  相关问题有两种可能性:1.可能是屏幕排线松动引起的屏幕无法显示图像。2.可能是主板损坏,导致屏幕无法显示图像。  拿去华强......
  • 记一次.net加密神器 Eazfuscator.NET 2023.2 最新版 使用尝试
    合集-.net代码混淆加密产权保护(2) 1.记一次.net加密神器Eazfuscator.NET2023.2最新版使用尝试06-272.将SmartAssembly与单文件可执行文件一起使用(.NETCore6)06-27收起 很多人看到这个Eazfuscator.NET还不知是什么东东。。。首先介绍下。什么是Eazfu......
  • 理解ASEMI代理海矽美快恢复二极管SFP3012A的性能与应用
    编辑-Z在电子元件领域,快恢复二极管SFP3012A是一种重要的半导体器件,它在电路设计中扮演着至关重要的角色。本文将深入探讨SFP3012A的性能特点和应用领域,帮助读者更好地理解和使用这种二极管。 一、SFP3012A的性能特点 快恢复二极管SFP3012A具有许多优秀的性能特点。首先,它具......
  • ASEMI代理海矽美SFP3012, 快恢复二极管SFP3012参数
    编辑-ZSFP3012参数描述:型号:SFP3012最大反向重复峰值电压VRRM:1200V平均整流正向电流IF:30A反向恢复时间TRR:≤65nS正向峰值浪涌电流IFSM:160×2A工作接点温度TJ:-40~175℃储存温度TSTG:-40~175℃典型热阻RθJC:0.5℃/WVB:1200VIR:0.01mAVF:2.2V  SFP3012特征:超快速切换,实现......
  • oracle 中的常用exception
    1、异常的优点如果没有异常,在程序中,应当检查每个命令的成功还是失败,如BEGINSELECT...--checkfor’nodatafound’errorSELECT...--checkfor’nodatafound’errorSELECT...--checkfor’nodatafound’error这......
  • 视图中的难点:主键表 About Key-Preserved Tables
    http://wmlm.itpub.net/post/12871/278640因为在项目中大量地使用了视图,而在视图上的更新上产生了一点儿问题,所以抽时间对可更新视图进行了复习,英文看得多了,也就成了中文 测试用表CREATETABLEDept_tab(DeptnoNUMBER(4)PRIMARYKEY,DnameVARCHAR2(14),LocVARCHAR2(13));CR......
  • 目前除了站长还有哪些人在使用服务器呢?
    目前除了站长还有哪些人在使用服务器呢?站长只是网站管理人的统称。能用到服务器的人群很多也很杂,在此就大致的给大家分享下主要是这几类人群:1、个人用户。个人用户使用的服务器配置都比较低,基本上以VPS和云服务器为主。大部分都是存放个人博客网页,或者个人搭建小型网站,还一些初学程......
  • centos 关于日志文件切割logrotate的使用及示例
    (文章目录)本文简单的介绍了logrotate使用和示例。本文分为2个部分,即logrotate介绍以及以tomcat的日志为示例进行介绍。一、Logrotate介绍Logrotate程序是一个日志文件管理工具。用于分割日志文件,压缩转存、删除旧的日志文件,并创建新的日志文件logrotate一般系统会自带,不需......
  • yum是什么?(linux命令) .
    一.yum是什么yum=YellowdogUpdater,Modified主要功能是更方便的添加/删除/更新RPM包.它能自动解决包的倚赖性问题.它能便于管理大量系统的更新问题注:为什么要使用yum而不用apt,最简单的原因,Fedora自带二.yum特点*可以同时配置多个资源库(Repository)*简洁的配置文......
  • Getting Started with Eclipse and Counterclockwise
    http://dev.clojure.org/display/doc/Getting+Started+with+Eclipse+and+CounterclockwiseGotostartofmetadata InstallEclipse(IfyoudonothaveEclipseinstalled,oryouwanttomakeisolatedtestsoftheClojurepluginforEclipse)GrabtheEcli......