八数码游戏分析—启发式搜索算法(2)
来源:互联网 发布:c 游戏编程 pdf 编辑:程序博客网 时间:2024/05/22 17:35
大家通过阅读 八数码游戏分析——启发式搜索(一) 应该对解决八数码的启发式搜索算法有了一个大致的印象了,那么我就开始介绍基于 八数码游戏分析——启发式搜索(一)的一种改进的算法。
改进的启发式搜索策略:八数码的下一个格局中每个棋子移动到正确位置所需要的步数要少于当前格局中每个棋子移动到正确位置所需要的步数。
首先来解释一下什么是棋子移动到正确位置的步数。
我们在 八数码游戏分析——启发式搜索(一) 中提到每个数码的位置与最终格局的对比,如果位置相同,则说明此数码在正确位置。
还是拿那个图来说明:
图2.1
假设图2.1右边的格局是最终状态,那么可以看出左边格局中正确位置的数码就是红色字体标识的数码,分别是3,4,5,7。
我们把初始数码中的每个未移动到正确位置的数码拿出来单独分析
我们拿数码2来分析,如下图:
图2.2
可以看出数码2移动到正确位置需要一步,我们再拿数码8来分析:
图2.3
从图2.3可以看出,数码8移动到正确位置为两步
因此,一次可以得出数码1和数码6移动到正确位置都为一步,所以当前状态的每个棋子移动到正确位置的步数总和为:5步
那么当前状态的下一状态如下图所示:
图2.4
图2.4中,红色字体标识的是在正确位置的数码,八数码旁边的(n)表示当前数码格局中每个棋子移动到正确位置的步数总和为n步。
由此可以看出图2.4的左下方格局满足条件(一共要4步),所以左下方的格局为下一步格局。可能现在大家还没有看出此算法相对于前一个算法的优越性,
好,我们再向后继续推:
图2.5
细心的朋友一定还记得,在 八数码游戏分析——启发式搜索(一)中,推到这一步的时候有两个一样的格局可以选择,而此算法在下一步只有右下方的格局总步数(3步)少于当前格局总步数(4步)。
不仅如此,经过大量的测试证明,八数码问题运用此算法到达最终格局所用的步数也是最少的!
下面贴一个测试c程序:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #include"stdio.h"
- #include"math.h"
- #define num 3 //宏定义数码的行列数为3
-
-
- void show(int begin[num][num])
- {
- for(int i = 0; i < num; i++)
- {
- for(int j = 0; j < num; j++)
- printf("%d ", begin[i][j]);
- printf("\n");
- }
- printf("\n");
- }
-
-
- void exchange(int begin[num][num], int row_one, int column_one, int row_two, int column_two)
- {
- int temp;
- temp = begin[row_two][column_two] ;
- begin[row_two][column_two] = begin[row_one][column_one];
- begin[row_one][column_one] = temp;
- }
-
-
- int judge(int begin[num][num], int end[num][num])
- {
- int count=0;
- for(int i = 0; i < num; i++)
- for(int j = 0; j < num; j++)
- {
- if(begin[i][j] == 0)
- continue;
- else if(begin[i][j] != end[i][j])
- {
- for(int k=0; k<num; k++)
- for(int w=0; w<num; w++)
- if(begin[i][j] == end[k][w])
- count = count + fabs(i-k) + fabs(j-w);
- }
- }
- return count;
- }
-
-
- int yidong(int begin[num][num], int end[num][num], int right, int jishu, int ji_shu[50][3][3], int biaoji, int row, int column)
- {
- int temp_zhi;
- show(begin);
- int temp;
- if(right == 0)
- return 1;
- if(row > 0 && biaoji != 0)
- {
- exchange(begin, row - 1, column, row , column);
- temp = judge(begin, end);
- if(temp >= right)
- exchange(begin, row - 1, column, row , column);
- else if(temp < right)
- {
- temp_zhi = yidong(begin, end, temp, jishu+1, ji_shu, 2, row-1, column);
- if( temp_zhi == 1)
- return 1;
- exchange(begin, row - 1, column, row , column);
- }
- }
- if(column > 0 && biaoji != 1)
- {
- exchange(begin, row, column - 1, row , column);
- temp = judge(begin, end);
- if(temp >= right)
- exchange(begin, row, column - 1, row , column);
- else if(temp < right)
- {
- temp_zhi = yidong(begin, end, temp, jishu+1, ji_shu ,3, row, column - 1);
- if(temp_zhi == 1)
- return 1;
- exchange(begin, row, column - 1, row , column);
- }
- }
-
- if(row < num-1 && biaoji != 2)
- {
- exchange(begin, row + 1, column, row , column);
- temp = judge(begin, end);
- if(temp >= right)
- exchange(begin, row + 1, column, row , column);
- else if(temp < right)
- {
- temp_zhi =yidong(begin, end, temp, jishu+1, ji_shu, 0, row+1, column);
- if(temp_zhi == 1)
- return 1;
- exchange(begin, row + 1, column, row , column);
- }
- }
- if(column < num-1 && biaoji != 3)
- {
- exchange(begin, row, column + 1, row , column);
- temp = judge(begin, end);
- if(temp >= right)
- exchange(begin, row, column + 1, row , column);
- else if(temp < right)
- {
- temp_zhi = yidong(begin, end, temp, jishu+1, ji_shu, 1, row, column+1);
- if(temp_zhi == 1)
- return 1;
- exchange(begin, row, column + 1, row , column);
- }
- }
- return 0;
- }
-
-
- void shuru(int begin[][num],int blank[])
- {
- int temp, node, zero = 0;
- for (int i = 0; i < num; i++)
- for(int j = 0; j < num; j++)
- {
- node = 1;
- printf("请输入第%d行,第%d列的元素的值:", i+1, j+1);
- scanf("%d", &temp);
- for (int q = 0; q <= i && node == 1; q++)
- for (int w = 0; w < j; w++)
- if(temp == begin[q][w])
- {
- printf("输入重复,请重新输入\n");
- node = 0;
- j--;
- break;
- }
- if(temp < 0 || temp > num*num-1)
- {
- printf("请输入从%d到%d的数\n", zero, num*num-1);
- node = 0;
- j--;
- }
- if(node == 1)
- {
- if(temp == 0)
- {
- blank[0] = i;
- blank[1] = j;
- }
- begin[i][j] = temp;
- }
- }
- }
-
- int main()
- {
- int jishu = 0, ji_shu[50][3][3];
- int row;
- int column;
- int begin[num][num], blank[2],count=1;
- int end[num][num] = {1, 2, 3, 8, 0, 4, 7, 6, 5};
- printf ("-------%d数码游戏开始!--------\n", num);
- shuru(begin, blank);
- row = blank[0];
- column = blank[1];
- if(yidong (begin, end,judge(begin,end),jishu,ji_shu,4,row,column) == 0)
- printf("\n此8数码的问题可能无解!");
- getchar();getchar();
- return 0;
- }
下面是运行结果示例:
欢迎大家转载,如有转载请注明文章来自: http://blog.csdn.net/q345852047
0 0