一 实验要求

1、迷宫随机生成

2、玩家走迷宫,留下足迹;

3、系统用A*算法寻路,输出路径

解决问题

1、如何显示迷宫的图形界面;

2、如何生成随机的迷宫;

3、怎样移动游戏中走迷宫的“玩家”;

4、用A*算法求解迷宫;

二 实验算法

1.显示迷宫路径

prime算法  :首先,生成迷宫全部都是围墙设为1表示围墙的值就是1。其次,把迷宫之外的轮廓设置为0表示边框,然后设置起点和重点的值分别为2和2.
接下来就要判断起始点下下个低方判断是否是围墙,因为防止打穿围墙或者达到之前的路上在围墙中不断的挖路从而生成迷宫。方法主要是从起点开始每一个上下左右,当发现有围墙,则往围墙移动,然后继续判断最终不断递归。

2.基于A*迷宫求解

节点放入开放列表(开始节点的F和G值都视为0);

三i. 在开放列表中查找具有最小F值的节点,并把查找到的节点作为当前节点;

ii.把当前节点从开放列表删除, 加入到封闭列表;

iii.对当前节点相邻的每一个节点依次执行以下步骤:

1.     如果该相邻节点不可通行或者该相邻节点已经在封闭列表中,则什么操作也不执行,继续检验下一个节点;

2.     如果该相邻节点不在开放列表中,则将该节点添加到开放列表中, 并将该相邻节点的父节点设为当前节点,同时保存该相邻节点的G和F值;

3.     如果该相邻节点在开放列表中, 则判断若经由当前节点到达该相邻节点的G值是否小于原来保存的G值,若小于,则将该相邻节点的父节点设为当前节点,并重新设置该相邻节点的G和F值.  循环结束条件:当终点节点被加入到开放列表作为待检验节点时, 表示路径被找到,此时应终止循环;或者当开放列表为空,表明已无可以添加的新节点,而已检验的节点中没有终点节点则意味着路径无法被找到,此时也结束循环;

3. 从终点节点开始沿父节点遍历, 并保存整个遍历到的节点坐标,遍历所得的节点就是最后得到的路径;

搜索区域(The Search Area):搜索区域被划分为简单的二维数组,数组每个元素对应一个结点。

开放列表(Open List):将寻路过程中待检测的结点存放于Open List中,而已检测过的结点则存放于Close List中。

路径排序(Path Sorting):下一步怎么移动由以下公式确定;F(n)=G+H。F(n)为估价函数,G代表的是从初始位置Start沿着已生成的路径到指定待检测结点移动开销。H表示待检测结点到目标节点B的估计移动开销。

启发函数(Heuristics  Function): H为启发函数,可以看作是一种试探,由于在找到唯一路径前,不确定在前面会出现什么障碍物,因此用了一种计算H的算法,具体可以根据实际情况决定。为了简化问题,H采用的是传统的曼哈顿距离,也就是横纵向走的距离之和。

3.此实验运用广度优先算法搜索路径

广度优先算法(BFS)
广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历算法这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。基本过程,BFS是从根节点开始,沿着树(图)的宽度遍历树(图)的节点。如果所有节点均被访问,则算法中止。一般用队列数据结构来辅助实现BFS算法。

三代码实现

生成迷宫

void MAZE::mazeInit()
{//迷宫围墙,nn*2+2是规划的迷宫地图大小for(int i=0; i<=nn*2+2; ++i)for(int j=0; j<=nn*2+2; ++j)maze[i][j] = 1;//在迷宫之外的的轮廓默认为过道for(int i=0, j=2*nn+2; i<=2*nn+2; ++i){maze[i][0] = 0;maze[i][j] = 0;}for(int i=0, j=2*nn+2; i<=2*nn+2; ++i){maze[0][i] = 0;maze[j][i] = 0;}//默认迷宫坐标第三行第一例为起点maze[2][1] = 2;//默认2*nn 行 和 2*nn+1列为终点maze[2*nn][2*nn+1] = 3;//生成无符号随机数srand((unsigned)time(NULL));//生成的随机数在 [0, nn+1]之间,生成路径searchPath(rand()%nn+1, rand()%nn+1);//将地图整体向左上方平移一个单位for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){maze[i][j] = maze[i+1][j+1];}}len_path = 0;
}int MAZE::searchPath(int x, int y)
{//往四个方向static int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};int zx = x*2;int zy = y*2;int next, turn, i;maze[zx][zy] = 0;//设置turn为[0, 4]之间的任意一个奇数turn = rand()%2 ? 1 : 3;//next=rand()%4 取值范围[0, 4),//next=(next+turn)%4 每个循环在奇数和偶数之间切换,[0, 4)遍历一遍//在迷宫地图里,随机选一个地方,开始挖路,4次循环,往4个方向挖for(i=0, next=rand()%4; i<4; ++i, next=(next+turn)%4)//搜索当前位置的第二步,如果是围墙,这将当前位置的沿着指定方向的下一步设置为路if(maze[zx+2*dir[next][0]][zy+2*dir[next][1]] == 1){maze[zx+dir[next][0]][zy+dir[next][1]] = 0;searchPath(x+dir[next][0], y+dir[next][1]);//等于searthPath(zx+2*dir[next][0]][zy+2*dir[next][1])当前位置的下一步为节点开始搜索}return 0;
}

画出迷宫地图

void MainWindow::paintEvent(QPaintEvent *)
{QPainter painter(this);int n = m->get_n();for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){//绘制迷宫围墙if(m->maze[i][j] ==1){painter.setPen(Qt::black);painter.setBrush(QBrush(Qt::black,Qt::SolidPattern));painter.drawRect(QRect(j*size,i*size,size,size));}//绘制你当前的位置else if(m->maze[i][j] == 2){painter.setPen(Qt::yellow);painter.setBrush(Qt::yellow);painter.drawRect(j*20,i*20,20,20);}//绘制迷宫终点else if(m->maze[i][j] == 3){painter.setPen(Qt::red);painter.setBrush(Qt::red);painter.drawRect(j*20,i*20,20,20);}//绘制迷宫过道else if(m->maze[i][j] == 0){painter.setPen(Qt::white);painter.setBrush(QBrush(Qt::white,Qt::SolidPattern));painter.drawRect(QRect(j*size,i*size,size,size));}//绘制最短路径提示else if(m->maze[i][j] == 6){painter.setPen(Qt::white);painter.setBrush(Qt::blue);painter.drawRect(j*20+5,i*20+5,10,10);}}}
}

键盘响应

void MainWindow::keyPressEvent(QKeyEvent *e)//键盘监听
{if(bfs_fg){m->recoverPath();bfs_fg = false;update();}int tx = X, ty = Y;int n = m->get_n();if(e->key()==Qt::Key_W)//上{if(X>0 && m->maze[X-1][Y] != 1){X=X-1;}}else if(e->key()==Qt::Key_S)//下{if(X<n-1 && m->maze[X+1][Y] != 1){X=X+1;}}else if(e->key()==Qt::Key_A)//左{if(Y>0 && m->maze[X][Y-1] != 1){Y=Y-1;}}else if(e->key()==Qt::Key_D)//右{if(Y<n-1 && m->maze[X][Y+1] != 1){Y=Y+1;}}int tmp = m->maze[X][Y];if(tmp == 3){QMessageBox::information(this,"提示","到达终点",QMessageBox::Yes);}else{m->maze[X][Y] = m->maze[tx][ty];m->maze[tx][ty] = tmp;}update();
}

搜索路径dfs

void MAZE::getPath(int pos)
{while(pos != -1){path[len_path].x = q[pos].x;path[len_path].y = q[pos].y;len_path++;pos = q[pos].pre;}
}void MAZE::bfs()//寻路
{int front, tail, sx, sy;for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)if(maze[i][j] == 2){sx = i; sy = j;}front = tail = 0;q[tail].x = sx;q[tail].y = sy;q[tail].pre = -1;tail++;int x, y, nx, ny;bool fg = false;while(front < tail){x = q[front].x;y = q[front].y;for(int i = 0; i < 4; i++){nx = x+dx[i];ny = y+dy[i];if(nx>=0&&nx<n&&ny>=0&&ny<n&&maze[nx][ny]==0)//确保头结点在路上{maze[nx][ny] = 5;//把此节点设为通路q[tail].x = nx;q[tail].y = ny;q[tail].pre = front;//加入到数组q中tail++;}if(maze[nx][ny] == 3){//起点和终点重合q[tail].x = nx;q[tail].y = ny;q[tail].pre = front;tail++;fg = true;//结束标志len_path = 0;path[len_path].x = nx;path[len_path].y = ny;len_path++;getPath(front);}}if(fg)break;//如果找到终点结束循环front++;//否则头结点到上一个节点}for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)if(maze[i][j] == 5)maze[i][j] = 0;
}

三 游戏测试

四 打包发布

实验三 基于A*迷宫的算法相关推荐

  1. 实验三 基于FPGA的数码管动态扫描电路设计 quartus/数码管/电路模块设计

    实验三 基于FPGA的数码管动态扫描电路设计 源文件的链接放在最后啦 实验目的: (1) 熟悉7段数码管显示译码电路的设计. (2) 掌握数码管显示原理及静态.动态扫描电路的设计. 实验任务: (1) ...

  2. 实验三 基于GUI的文件管理器——Java实现

    一.实验目的 运用面向对象程序设计思想,基于Java文件管理和I/O框架,实现基于图形界面的GUI文件管理器. 二.实验项目内容 1.实现文件夹创建.删除.进入. 2.实现当前文件夹下的内容罗列. 3 ...

  3. 实验三 基于A*算法的迷宫游戏

    软件实习项目三 -- Java实现基于A*算法的迷宫游戏 一.实验任务 (1)该题要求随机生成一个迷宫,并求解迷宫: (2)要求游戏支持玩家走迷宫,和系统走迷宫路径两种模式.玩家走迷宫,通过键盘方向键 ...

  4. 实验三 基于A*算法的迷宫游戏开发

    实验要求: 1.迷宫随机生成 2.玩家走迷宫,留下足迹: 3.系统用A*算法寻路,输出路径 解决问题: 1.如何显示迷宫的图形界面: 2.如何生成随机的迷宫: 3.怎样移动游戏中走迷宫的"玩 ...

  5. 【NOJ1147】【算法实验三】木乃伊迷宫

    1147.木乃伊迷宫 时限:1000ms 内存限制:10000K 总时限:3000ms 描述 木乃伊地下宫殿是一个6行6列的迷宫.作为敢到木乃伊地下宫殿里去探险的你,有没有跟木乃伊抓迷藏的心理准备呵! ...

  6. 实验三:Java迷宫生成

    实验内容 1.迷宫游戏是非常经典的游戏,在该题中要求随机生成一个迷宫,并求解迷宫: 2.要求查找并理解迷宫生成的算法,并尝试用两种不同的算法来生成随机的迷宫. 3.要求迷宫游戏支持玩家走迷宫,和系统走 ...

  7. 【实验三】LZW编解码算法实现与分析

    一.实验目的 1.掌握词典编码的基本原理,用C/C++/Python等语言编程实现LZW解码器并分析编解码算法. 2.选择十种不同格式类型的文件,使用LZW编码器进行压缩得到输出的压缩比特流文件.对各 ...

  8. 南京邮电大学操作系统实验三:虚拟内存页面置换算法

    实验内容 使用数组存储一组页面请求,页面请求的数量要50个以上,访问的页面号可以用随机数生成(0~20): (1)设置为分配给进程的页框数(假定是5),使用LRU算法,模拟完成全部的页面请求,最后输出 ...

  9. 无线定位技术实验三 基于信号强度的位置指纹定位仿真

    前些天发现了十分不错的人工智能学习网站,通俗易懂,风趣幽默,没有广告,分享给大家,大家可以自行看看.(点击跳转人工智能学习资料) 微信公众号:创享日记 发送:指纹定位 获取完整报告(含源码+结果+思考 ...

最新文章

  1. 世界首个2nm制程芯片公布!这次IBM跑在了台积电三星英特尔前面
  2. iphone照片删掉又出现_iPhone 内存不够用,原因在这儿!
  3. SQLSERVER 设置默认值
  4. 整合看点: DellEMC的HCI市场如何来看?
  5. 怎么将pdf转换成word
  6. 计算机考研落榜了怎么办,考研落榜了怎么办
  7. InstallShield 杀掉进程
  8. [转]ubuntu server:开机自动登录
  9. python程序设计实验七_Python程序设计实验报告七:组合数据类型
  10. mybatis 3的TypeHandler深入解析(及null值的处理)
  11. hdu 1520 Anniversary party(第一道树形dp)
  12. 佳能Canon PIXMA MG3020 打印机驱动
  13. phpquery中文手册
  14. 人与人,人与自然。文/江湖一剑客
  15. android TV 开发规范
  16. 1380 D - Berserk And Fireball(思维,贪心)
  17. pandas parquet文件读取pyarrow、feather文件保存与读取;requests 或wget下载图片文件
  18. 新手前端微信小程序img图片无法显示问题
  19. js中each的用法
  20. STM32(一)STM32简介

热门文章

  1. Face detection in color images, 彩色图像中的人脸检测
  2. unity3d画出漂亮的玫瑰图案函数。
  3. VS2019及其他多个老版本的VS下载说明
  4. 微信支付【 wx.chooseWXPay、WeixinJSBridge.invoke】
  5. 中国三相开关磁阻电动机行业市场供需与战略研究报告
  6. css图片颜色设置为黑白
  7. 无源晶振与有源晶振的区别
  8. 十进制12345在32位计算机中的十六进制表示方法
  9. MT7628路由器工作原理,MT7628处理器相关参数介绍
  10. 网易云音乐接入微信状态