第二章 趣味迷宫
来源:互联网 发布:利用网络漏洞赚钱 编辑:程序博客网 时间:2024/05/16 00:48
我们将迷宫问题难度上升一点,就是找一条最近的路径走出迷宫
一般针对最短路径问题,bfs是最简单的选择,A*是较好的选择,但是A*过程较繁琐,今天我们将采用IDA*算法来实现这个寻找迷宫出口问题
算法思想和流程:
IDA*算法简单的讲就是迭代+A*的实现,因实现过程非常简单,而且效率还很优,所以掌握IDA*势在必行
1、没有学习IDA*算法以前,觉得如果是最短路径问题,则dfs是无法实现的,bfs可以实现,但是IDA*告诉了我dfs怎么实现最短路径问题,而且实现的更好
2、、回顾下IDA*的步骤,没有了A*的优先队列,甚至连bfs广搜所需的简单队列和判重数组都不用,从一个阈值开始递归,这个值一般可以理解为递归的最大深度,若找不到目标点,则这个值进行扩大,列入++操作,再重新递归操作,找到则返回,返回的一定是最优值
3、回顾下IDA*的判断函数(IDA*的精髓啊):当前局面的估价函数值+当前的搜索深度 > 预定义的最大搜索深度时,就进行剪枝。
实现起来较容易,代码量也很少
//最近的路走出迷宫//IDA*算法实现#include <iostream>using namespace std;#define M 15//行#define N 20//列int map[][N]={{0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},{1,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1},{1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,1,0,1},{1,0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0,1,0,1},{1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,1,0,1,0,1},{1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,1},{1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,0,1},{1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1},{1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,0,1,0,1},{1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1},{1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,0,1},{1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1},{1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,0,1,0,1},{1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1},{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0}};int dir[][2]={-1,0,0,-1,1,0,0,1};int starti=0,startj=0;//开始点坐标int endi=M-1,endj=N-1;//结束点坐标int maxDeep;//最大深度int H(int i,int j){//估价函数return abs(endi-i)+abs(endj-j);}bool dfs(int curi,int curj,int depth){if(depth+H(curi,curj)>maxDeep)//IDA*估价剪枝return false;if(curi==endi&&curj==endj)return true;for(int i=0;i<4;i++){int ni=curi+dir[i][0];int nj=curj+dir[i][1];if(ni>=0&&ni<M&&nj>=0&&nj<N&&map[ni][nj]==0){map[ni][nj]=2;if(dfs(ni,nj,depth+1))return true;map[ni][nj]=0;}}return false;}int IDAstar(){maxDeep=H(starti,startj);map[starti][startj]=2;while(!dfs(starti,startj,0))maxDeep++;return maxDeep;}int main(){ cout<<IDAstar(); return 0;}
下面我们的主要任务就是做一个这样的游戏了,可以模拟动态的走出这个迷宫,还可以自己DIY通路和障碍,动手开始吧
HTML代码如下,只要复制粘贴,保存html打开就能见到后面的效果了
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title><style type="text/css">body,div,h2,ul,li{margin:0;padding:0;}body{font:12px/1.5 Arail;}.box{width:860px;margin:10px auto;background:#eee;border:1px solid #b8b8b8;overflow:hidden}.title{height:30px;line-height:30px;font-size:14px;padding:0 15px 0 35px;border-bottom:1px solid #b8b8b8;background:#fafafa url(http://js.alixixi.com/img/mm/ico.gif) 5px 50% no-repeat;}.title span{float:left;}.title a{float:right;color:#06f;outline:none;}.title a:hover{color:red;} .box .tool { width:300px; float:left; } .box .content { width:480px; margin-left:310px; } .tool div { margin:10px auto; height:40px; text-align:center; } .content .tag { height:30px; line-height:30px; } .content td { width:10px; height:10px; font-size:xx-large; line-height:10px; border:1px solid #c3c3c3; background:#fff; text-align:center; }</style><script type="text/javascript"> //一些常量 var matrix = [[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],[1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1],[1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1],[1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1],[1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1],[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1],[1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1],[1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],[1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1],[1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],[1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1],[1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],[1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1],[1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0] ]; var M = 15, N = 20; var dir = [[-1, 0], [0, -1], [1, 0], [0, 1]]; var starti = 0, startj = 0;//开始点坐标 var endi = M - 1, endj = N - 1;//结束点坐标 function H(i,j){//估价函数 return Math.abs(endi - i) + Math.abs(endj - j); } var BLACK="#000"; var BLUE="#06f"; var WHITE="#fff";</script><script type="text/javascript"> //一些公共函数 //获取ID var $ = function (id) { return typeof id === "string" ? document.getElementById(id) : id }; //获取tagName var $$ = function (tagName, oParent) { return (oParent || document).getElementsByTagName(tagName) }; //获取class var $$$ = function (sClass, oParent) { var aClass = [], i = 0, reClass = new RegExp("(\\s|^)" + sClass + "($|\\s)"), aElement = $$("*", oParent); for (i = 0; i < aElement.length; i++) reClass.test(aElement[i].className) && aClass.push(aElement[i]); return aClass };</script><script type="text/javascript"> //创建数独对象 var Maze = function () { this.initialize.apply(this, arguments) }; Maze.prototype = { initMatrix: function (matrix,Map) { for (var i = 0; i < M; i++) { matrix[i] = new Array(N); for (var j = 0; j < N; j++) { matrix[i][j] = Map[i][j]; } } }, renewMatrix: function (matrix,Map) { for (var i = 0; i < M; i++) { for (var j = 0; j < N; j++) { matrix[i][j] = Map[i][j]; } } }, initialize: function (obj ,Map) { var oThis = this; this.Parent = $(obj);//获得table对象 this.Table = $$("table", this.Parent)[0]; this.tag = $$$("tag", this.Parent)[0]; this.ButtonA = $$$("answer", this.Parent)[0]; this.ButtonB = $$$("restore", this.Parent)[0]; this.ButtonC = $$$("show", this.Parent)[0]; this.ButtonD = $$$("diy", this.Parent)[0]; this.matrix = new Array(M);//存放数独矩阵 this.diyMatrix = new Array(M);//diy迷宫 this.Td = [];//table中的所有td列矩阵 this.maxDeep = 0; this.stime = null;//计时 this.initMatrix(this.matrix, Map); this.initMatrix(this.diyMatrix, Map); this.dom = document.documentElement || document.body; this.ButtonA.onclick = function () { oThis.tag.innerText = "运行"; oThis.initOperation(); oThis.show(); oThis.answer(); oThis.print(); } this.ButtonB.onclick = function () { oThis.tag.innerText = "还原迷宫"; oThis.initOperation(); oThis.show(); } this.ButtonC.onclick = function () { oThis.tag.innerText = "显示答案"; oThis.initOperation(); oThis.answer(); oThis.show(); } this.ButtonD.onclick = function () { oThis.tag.innerText = "DIY迷宫"; oThis.initOperation(); oThis.show(); oThis.diy(); } this.create(Map); }, initOperation: function () {//初始化操作 var oThis = this; oThis.renewMatrix(oThis.matrix, oThis.diyMatrix); clearInterval(oThis.stime); }, create: function (Map) { var oThis = this; var aFrag = document.createDocumentFragment(); var i = 0, j = 0; for (i = 0; i < M; i++) { var tr = document.createElement("tr"); oThis.Td.push([]); for (j = 0; j < N; j++) { var td = document.createElement("td"); if (Map[i][j] == 1) td.style.backgroundColor = BLACK; oThis.Td[i].push(td); tr.appendChild(td); } aFrag.appendChild(tr); } this.Table.appendChild(aFrag); }, print: function () { var oThis = this; var curi = starti, curj = startj; var preDir = -3;//访问的上一个方向 this.stime = setInterval(function () { oThis.Td[curi][curj].style.backgroundColor = BLUE; if (curi == endi && curj == endj) clearTimeout(oThis.stime); for (var i = 0; i < 4; i++) { var ni = curi + dir[i][0]; var nj = curj + dir[i][1]; if (ni >= 0 && ni < M && nj >= 0 && nj < N && Math.abs(i - preDir) != 2 && oThis.matrix[ni][nj] == 2) { curi = ni, curj = nj; preDir = i; break; } } }, 100); }, show: function () { for (var i = 0; i < M; i++) for (var j = 0; j < N; j++) { if (this.matrix[i][j] == 2) this.Td[i][j].style.backgroundColor = BLUE; else if (this.matrix[i][j] == 1) this.Td[i][j].style.backgroundColor = BLACK; else this.Td[i][j].style.backgroundColor = WHITE; } }, find:function(obj){ for (var i = 0; i < M; i++) for (var j = 0; j < N; j++) if (this.Td[i][j] == obj) return { i: i, j: j }; }, diy: function () { var oThis=this; for (var i = 0; i < M; i++) { for (var j = 0; j < N; j++) { this.Td[i][j].onclick = function () { var pos = oThis.find(this); var i=pos.i,j=pos.j; if (oThis.diyMatrix[i][j] == 0) { oThis.diyMatrix[i][j] = 1; this.style.backgroundColor = BLACK; } else { oThis.diyMatrix[i][j] = 0; this.style.backgroundColor = WHITE; } } } } }, answer: function () { this.IDAstar(); //this.show(); }, dfs:function(curi, curj, depth) { if (depth + H(curi, curj) > this.maxDeep)//IDA*估价剪枝 return false; if (curi == endi && curj == endj) return true; for (var i = 0; i < 4; i++) { var ni = curi + dir[i][0]; var nj = curj + dir[i][1]; if (ni >= 0 && ni < M && nj >= 0 && nj < N && this.matrix[ni][nj] == 0) { this.matrix[ni][nj] = 2; if (this.dfs(ni, nj, depth + 1) == true) return true; this.matrix[ni][nj] = 0; } } return false; }, IDAstar:function(){ this.maxDeep = H(starti, startj); this.matrix[starti][startj]=2; while (this.dfs(starti, startj, 0) == false) { if (this.maxDeep > 100) break; this.maxDeep = this.maxDeep + 1; } } }; window.onload = function () { var Box = $$$("box"); //创建实例 new Maze(Box[0], matrix); };</script></head><body><div class="box"> <h2 class="title"><span>迷宫模拟</span></h2> <div class="tool"> <div><button class="answer">运行</button></div> <div><button class="restore">还原迷宫</button></div> <div><button class="show">显示答案</button></div> <div><button class="diy">DIY迷宫</button></div> </div> <div class="content"> <div class="tag">默认迷宫</div> <table class="sudoku"> </table> </div></div></body></html>
效果如下:
初始状态:
点击运行:
蓝色条会一直动
点击显示答案会将最近的路径显示出来
点击DIY迷宫可以自己DIY,然后再点击运行或者显示答案,会重新计算结果
后记:
我一直觉得编程没有那么枯燥,也可以是玩出来的
王川
2014/2/13
0 0
- 第二章 趣味迷宫
- 趣味算法-0的迷宫
- 人脸照片生成趣味迷宫
- 趣味编程100第二题
- 《C语言单片机开发趣味入门》第二节
- 电子科技大学第八届ACM趣味程序设计竞赛第二场题解
- SDUT 趣味循环赛第二场 玄黄的三角形题解
- 趣味迷宫 F(2011) = 2012 , 从2011走到2012
- 【UKIEPC2015 J】【趣味迷宫搜索】Jelly Raid 来回巡逻 不被发觉 循环节预处理
- 完美未来之星 复赛第二场 迷宫(DFS)
- 迷宫
- 迷宫
- 迷宫
- 迷宫
- 迷宫?
- 迷宫
- 迷宫
- 迷宫
- 几个 Context 上下文的区别
- 移植Qt到开发板的过程
- Sdk Manager.exe 闪退问题的解决
- MongoDB初步——安装与运行
- 编写Java Socket程序的几种结构
- 第二章 趣味迷宫
- 高斯混合模型(GMM)介绍以及学习笔记
- div嵌套p后,出现空白行
- JAVA中的强引用,弱引用,虚引用和软引用
- New algorimths
- 二分查找 Binary Search
- 恢复Ext3下被删除的文件
- 冒泡排序 Bubble Sort
- HDU 2275 Kiki & Little Kiki 1