利用JavaScript在网页实现八数码启发式A*算法动画效果


Posted in Javascript onApril 16, 2017

最近人工智能课老师布置了一个八数码实验,网上看到很多八数码的启发式A*算法,但是大多数都是利用C或者C++在控制台实现的,于是我用js在网页中做了一个类似的。

首先八数码就是一个九宫格,其中有一个空格,其他八个对应数字1-8,

利用JavaScript在网页实现八数码启发式A*算法动画效果

移动空格,使得最后状态为有序,如下图

利用JavaScript在网页实现八数码启发式A*算法动画效果

启发式算法是指在求解时,利用启发函数将不符合规则的解节点去掉,从而缩小问题的解空间。

A*算法是利用评价函数的启发式算法,在本例中,利用当前节点状态与最终节点状态所不同的格子数来评估节点的优劣,将优越节点储存并在之后展开,将劣质节点抛弃。

利用web实现这一点首先在html中添加九个如图所示input文本框,背景图片为数码格

利用JavaScript在网页实现八数码启发式A*算法动画效果

页面代码为

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>八数码</title>
 <style type="text/css">
 #result input{
  display: inline-block;
  font-family:"微软雅黑";
  font-size: 60px;
  font-weight: 900;
  text-align: center;
  width:100px;
  height:100px;
  background:url(images/0.png);
  background-size:cover;
 }
</style>
</head>
<body>
 <div id="result">
  <input type="text" id="r1">
  <input type="text" id="r2">
  <input type="text" id="r3"><br>
  <input type="text" id="r4">
  <input type="text" id="r5">
  <input type="text" id="r6"><br>
  <input type="text" id="r7">
  <input type="text" id="r8">
  <input type="text" id="r9"><br>
 </div>
 <button onclick="run()">求解</button>
</body>
</html>

然后利用javascript获取输入的值,并保存在二维数组中

var startArray=[[8,1,3],[0,2,4],[7,6,5]];//初始化八数码数组
   //获取输入的初始状态
   var cpic=1;
   for(var i=0;i<N;i++){
    for(var j=0;j<N;j++){
     var rid='r'+cpic++;
     var inputValue=getId(rid).value;
     if(inputValue==""){inputValue=0;}
     startArray[i][j]=parseInt(inputValue);
     getId(rid).value="";
    }
   }
var startGraph=new Graph(startArray);
var endArray=[[ 1,2,3],[ 8,0,4 ],[ 7,6,5 ]];
var endGraph=new Graph(endArray);//目标节点
evaluateGraph(startGraph,endGraph);
showGraph(startGraph);

其中Graph类是用来来保存一个状态节点相关数据:

//节点类
  var Graph = function(formData){
   this.form=formData;
   this.evalue=0;
   this.udirect=0;
   this.parent=null;
  };

实现一个showGraph()函数来显示八数码状态:

function showGraph(graph) {
   var c=1;
   for(var i=0;i<N;i++){
    for(var j=0;j<N;j++){
     var s='r'+c++;
     getId(s).style.backgroundImage="url(images/"+graph.form[i][j]+".png)";
    }
   }
  }

利用评估函数evaluateGraph()评估当前节点与目标节点的差距值

//评估函数
  function evaluateGraph(theGraph, endGraph){
   var differ = 0;//差距数
   for (var i = 0; i<N; i++)
   {
    for (var j = 0; j<N; j++)
    {
     if (theGraph.form[i][j] != endGraph.form[i][j]){differ++;}
    }
   }
   theGraph.evalue = differ;
   return differ;
  }

利用moveGraph()函数来移动并返回一个新节点:

//移动数码组
  function moveGraph(theGraph, direct){
   var HasGetBlank = 0;//是否找到空格位置
   var AbleMove = 1;//是否可移动
   var i, j, t_i, t_j;
   //查找空格坐标i,j
   for (i = 0; i<N; i++)
   {
    for (j = 0; j<N; j++)
    {
     if (theGraph.form[i][j] == 0)
     {
      HasGetBlank = 1;
      break;
     }
    }
    if (HasGetBlank == 1)
     break;
   }
   t_i = i;
   t_j = j;
   //移动空格
   switch (direct)
   {
    case 1://上
     t_i--;
     if (t_i<0)
      AbleMove = 0;//移动超过边界
     break;
    case 2://下
     t_i++;
     if (t_i >= N)
      AbleMove = 0;
     break;
    case 3://左
     t_j--;
     if (t_j<0)
      AbleMove = 0;
     break;
    case 4://右
     t_j++;
     if (t_j >= N)
      AbleMove = 0;
     break;
   }
   //Direct方向不能移动,返回原节点
   if (AbleMove == 0)
   {
    return theGraph;
   }
   //向Direct方向移动,生成新节点
   var ta=[[0,0,0],[0,0,0],[0,0,0]];
   var New_graph = new Graph(ta);
   for (var x = 0; x<N; x++)//复制数码组
   {
    for (var y = 0; y<N; y++)
    {
     New_graph.form[x][y] = theGraph.form[x][y];
    }
   }
   //交换
   New_graph.form[i][j] = New_graph.form[t_i][t_j];//交换空格和移动方向上的数字
   New_graph.form[t_i][t_j] = 0;
   return New_graph;
  }

最后是搜索函数,通过从初始节点开始一层层向下搜索,直到抵达目标节点,返回子节点,从子节点一层层向上回溯父节点,便可找到解路径:

//搜索路径
  function Search(beginGraph, endGraph){
   var g1, g2, g;
   var Step = 0;//深度
   var Direct = 0;//方向
   var i;
   var front=-1,rear=-1;
   g1=beginGraph;//初始八数码节点
   while (g1)//队列不空,从close队列中拿出一个节点
   {
    for (i = 1; i <= 4; i++){//分别从四个方向推导出新子节点
     Direct = i;
     if (Direct == g1.udirect)
      continue;//跳过屏蔽方向
     g2=moveGraph(g1,Direct);
     if (evaluateGraph(g2,g1)!=0){//数码组是否可以移动
      evaluateGraph(g1,endGraph);
      evaluateGraph(g2,endGraph);//评价新的节点
      if (g2.evalue <= g1.evalue + 1)//利用评估值判断是否为优越节点
      { //若为优,将g2的父节点指向g1
       g2.parent = g1;
       //设置屏蔽方向,防止往回推
       switch (Direct){
        case 1://上
         g2.udirect = 2;
         break;
        case 2://下
         g2.udirect = 1;
         break;
        case 3://左
         g2.udirect = 4;
         break;
        case 4://右
         g2.udirect = 3;
         break;
       }
       Qu[++rear]=g2;//把优越节点放到close队列
       if (g2.evalue == 0)//为0则搜索完成
       {
        g = g2;
        break;
       }
      }
      else{g2 = null;}//抛弃劣质节点
     }
    }
    //搜索完成,继续退出
    if (typeof g !== 'undefined')
    {
     if (g.evalue == 0)
     {
      break;
     }
    }
    Step++;//统计深度
    if (Step>Max_Step){
     alert("超过搜索深度!");
     break;}
    g1=Qu[++front];//从close队列中拿出一个节点继续下一轮展开
   }
   return g;
  }

最后将解路径节点按顺序压入堆栈,每秒弹出一个节点,显示,形成动画:

var top=-1;
   var G;
   G = Search(startGraph, endGraph);
   //解序列存入堆栈
   var P=G;
   while (P != null)
   {
    top++;
    St[top] = P;
    P = P.parent;
   }
   //动画执行
   var si=setInterval(function () {
    if (top>-1)
    {
     showGraph(St[top]);
     top--;
    }else {
     clearInterval(si);
    }
   },1000);
  }

以上所述是小编给大家介绍的利用JavaScript在网页实现八数码启发式A*算法动画效果,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的,在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js实现div的切换特效上一个下一个
Feb 11 Javascript
用JQuery实现全选与取消的两种简单方法
Feb 22 Javascript
PHP 数组current和next用法分享
Mar 05 Javascript
Jquery解析json字符串及json数组的方法
May 29 Javascript
深入理解JavaScript中的对象
Jun 04 Javascript
15个常用的jquery代码片段
Dec 19 Javascript
JavaScript tab选项卡插件实例代码
Feb 23 Javascript
利用CSS、JavaScript及Ajax实现图片预加载的方法
Nov 29 Javascript
微信小程序实现获取准确的腾讯定位地址功能示例
Mar 27 Javascript
JavaScript一元正号运算符示例代码
Jun 30 Javascript
vue 组件中使用 transition 和 transition-group实现过渡动画
Jul 09 Javascript
element中table高度自适应的实现
Oct 21 Javascript
JavaScript 函数的定义-调用、注意事项
Apr 16 #Javascript
AngularJS双向绑定和依赖反转实例详解
Apr 15 #Javascript
JavaScript简单计算人的年龄示例
Apr 15 #Javascript
微信小程序 ES6Promise.all批量上传文件实现代码
Apr 14 #Javascript
微信小程序动态的加载数据实例代码
Apr 14 #Javascript
JAVA中截取字符串substring用法详解
Apr 14 #Javascript
jQuery插件FusionCharts绘制2D双折线图效果示例【附demo源码】
Apr 14 #jQuery
You might like
基于PHP5魔术常量与魔术方法的详解
2013/06/13 PHP
浅析php创建者模式
2014/11/25 PHP
PHP中生成UUID自定义函数分享
2015/06/10 PHP
JavaScript 模仿vbs中的 DateAdd() 函数的代码
2007/08/13 Javascript
Mootools 1.2教程 Tooltips
2009/09/15 Javascript
jquery实现下拉菜单的二级联动利用json对象从DB取值显示联动
2014/03/27 Javascript
JavaScript实现给按钮加上双重动作的方法
2015/08/14 Javascript
JS使用eval解析JSON的注意事项分析
2015/11/14 Javascript
Easyui form combobox省市区三级联动
2016/01/13 Javascript
深入理解逻辑表达式的用法 与或非的用法
2016/06/06 Javascript
Javascript封装id、class与元素选择器方法示例
2017/03/13 Javascript
详解使用angular-cli发布i18n多国语言Angular应用
2017/05/20 Javascript
浅析JavaScript中的平稳退化(graceful degradation)
2017/07/24 Javascript
详解ES6中的三种异步解决方案
2018/06/28 Javascript
解决vue 界面在苹果手机上滑动点击事件等卡顿问题
2018/11/27 Javascript
JS/CSS实现字符串单词首字母大写功能
2019/09/03 Javascript
微信小程序 组件的外部样式externalClasses使用详解
2019/09/06 Javascript
详细分析vue响应式原理
2020/06/22 Javascript
Python中自定义函数的教程
2015/04/27 Python
使用paramiko远程执行命令、下发文件的实例
2017/10/01 Python
TensorFlow实现iris数据集线性回归
2018/09/07 Python
python集合常见运算案例解析
2019/10/17 Python
PyQt5结合matplotlib绘图的实现示例
2020/09/15 Python
HTML5 实现图片上传预处理功能
2020/02/06 HTML / CSS
微软中国官方商城:Microsoft Store中国
2018/10/12 全球购物
应届毕业生的自我鉴定
2013/11/13 职场文书
求职简历推荐信范文
2013/12/02 职场文书
医学生个人求职信范文
2014/02/07 职场文书
趣味活动策划方案
2014/02/08 职场文书
原材料检验岗位职责
2014/03/15 职场文书
计算机应用专业毕业生求职信
2014/06/03 职场文书
少先队辅导员事迹材料
2014/12/24 职场文书
小学教师求职信范文
2015/03/20 职场文书
2015年出纳工作总结与计划
2015/05/18 职场文书
不服劳动仲裁起诉书
2015/05/20 职场文书
甲午风云观后感
2015/06/02 职场文书