这篇文章主要介绍了利用JavaScript在网页实现八数码启发式A*算法动画效果,需要的朋友可以参考下
最近人工智能课老师布置了一个八数码实验,网上看到很多八数码的启发式A*算法,但是大多数都是利用C或者C++在控制台实现的,于是我用js在网页中做了一个类似的。
首先八数码就是一个九宫格,其中有一个空格,其他八个对应数字1-8,

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

启发式算法是指在求解时,利用启发函数将不符合规则的解节点去掉,从而缩小问题的解空间。
A*算法是利用评价函数的启发式算法,在本例中,利用当前节点状态与最终节点状态所不同的格子数来评估节点的优劣,将优越节点储存并在之后展开,将劣质节点抛弃。
利用web实现这一点首先在html中添加九个如图所示input文本框,背景图片为数码格

页面代码为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <!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>
<p 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>
</p>
<button onclick= "run()" >求解</button>
</body>
</html>
|
Salin selepas log masuk
然后利用javascript获取输入的值,并保存在二维数组中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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);
|
Salin selepas log masuk
其中Graph类是用来来保存一个状态节点相关数据:
1 2 3 4 5 6 7 | var Graph = function (formData){
this.form=formData;
this.evalue=0;
this.udirect=0;
this.parent=null;
};
|
Salin selepas log masuk
实现一个showGraph()函数来显示八数码状态:
1 2 3 4 5 6 7 8 9 | 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)" ;
}
}
}
|
Salin selepas log masuk
利用评估函数evaluateGraph()评估当前节点与目标节点的差距值
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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;
}
|
Salin selepas log masuk
利用moveGraph()函数来移动并返回一个新节点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | function moveGraph(theGraph, direct){
var HasGetBlank = 0;
var AbleMove = 1;
var i, j, t_i, t_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 ;
}
if (AbleMove == 0)
{
return theGraph;
}
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;
}
|
Salin selepas log masuk
最后是搜索函数,通过从初始节点开始一层层向下搜索,直到抵达目标节点,返回子节点,从子节点一层层向上回溯父节点,便可找到解路径:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 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)
{
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.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;
if (g2.evalue == 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];
}
return g;
}
|
Salin selepas log masuk
最后将解路径节点按顺序压入堆栈,每秒弹出一个节点,显示,形成动画:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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);
}
|
Salin selepas log masuk
Atas ialah kandungan terperinci 利用JavaScript在网页实现八数码启发式A*算法动画效果的图文代码介绍. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!