利用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 相关文章推荐
JavaScript实际应用:innerHTMl和确认提示的使用
Jun 22 Javascript
我也种棵OO树JXTree[js+css+xml]
Apr 02 Javascript
Div自动滚动到末尾的代码
Oct 26 Javascript
MooTools 1.2介绍
Sep 14 Javascript
jQuery中调用WebService方法小结
Mar 28 Javascript
JavaScript中的变量声明早于赋值分析
Mar 01 Javascript
AngularJS初始化过程分析(引导程序)
Dec 06 Javascript
jQuery选择器源码解读(七):elementMatcher函数
Mar 31 Javascript
详解ES6中的let命令
Apr 05 Javascript
微信小程序自定义toast实现方法详解【附demo源码下载】
Nov 28 Javascript
jQuery实现下拉菜单动态添加数据点击滑出收起其他功能
Jun 14 jQuery
微信小程序实现拍照画布指定区域生成图片
Jul 18 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中的时间相差8小时的解决办法
2008/03/28 PHP
PHP版本常用的排序算法汇总
2015/12/20 PHP
取得窗口大小 兼容所有浏览器的js代码
2011/08/09 Javascript
JavaScript执行效率与性能提升方案
2012/12/21 Javascript
学习javascript的闭包,原型,和匿名函数之旅
2015/10/18 Javascript
jQuery实现移动端滑块拖动选择数字效果
2015/12/24 Javascript
JavaScript获取对象在页面中位置坐标的方法
2016/02/03 Javascript
JavaScript如何获取到导航条中HTTP信息
2017/10/10 Javascript
浅析node Async异步处理模块用例分析及常用方法介绍
2017/11/17 Javascript
利用原生js实现html5小游戏之打砖块(附源码)
2018/01/03 Javascript
vue中各选项及钩子函数执行顺序详解
2018/08/25 Javascript
layui.tree组件的使用以及搜索节点功能的实现
2019/09/26 Javascript
jQuery实现异步上传一个或多个文件
2020/08/17 jQuery
[02:54]DOTA2亚洲邀请赛 VG战队出场宣传片
2015/02/07 DOTA
Python创建模块及模块导入的方法
2015/05/27 Python
Python解析树及树的遍历
2016/02/03 Python
Python matplotlib画图与中文设置操作实例分析
2019/04/23 Python
PyQt5 对图片进行缩放的实例
2019/06/18 Python
Python 实例方法、类方法、静态方法的区别与作用
2019/08/14 Python
Python如何把多个PDF文件合并代码实例
2020/02/13 Python
Pytorch中.new()的作用详解
2020/02/18 Python
浅谈python中频繁的print到底能浪费多长时间
2020/02/21 Python
python中如何打包用户自定义模块
2020/09/23 Python
GOOD AMERICAN官网:为曲线性感而设计
2017/12/28 全球购物
iHerb台湾:维生素、保健品和健康产品
2018/01/31 全球购物
毕业自我鉴定
2013/11/05 职场文书
预防艾滋病宣传标语
2014/06/25 职场文书
学校创先争优活动总结
2014/08/28 职场文书
走群众路线学习笔记
2014/11/06 职场文书
质量保证书
2015/01/17 职场文书
2015年社区精神文明工作总结
2015/05/26 职场文书
八一建军节主持词
2015/07/01 职场文书
公司转让协议书
2016/03/19 职场文书
SQL Server 数据库实验课第五周——常用查询条件
2021/04/05 SQL Server
Mybatis-Plus进阶分页与乐观锁插件及通用枚举和多数据源详解
2022/03/21 Java/Android
利用Python多线程实现图片下载器
2022/03/25 Python