详细工程文件的下载地址: http://download.csdn.net/source/195320
/**/
/*----------------------------------------------------------------
// Copyright (C) 2007 Fengart
// 版权所有。
// 开发者:Fengart
// 文件名:FengartAI.cs
// 文件功能描述:这是一个能够解决八数码问题的高效方法,主要体现在对状态编码上。
/*----------------------------------------------------------------
//主页:http://fengart.9126.com
//blog: http://blog.csdn.net/fengart
//Emial: fengart@126.com
//----------------------------------------------------------------*/
using
System;
using
System.Collections.Generic;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
namespace
Eight_Num_Fengart
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 八数码问题的算法
/// </summary>
class FengartAI
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
代码说明#region 代码说明
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//*编码规则:
* 每一个状态及每一次操作的表示方法?
* 有许多表示方法,比如一个3*3的八数码盘可以压缩成一个int值表示,但不适用于15 puzzle或大于8 的
* puzzle问题。如果对空间要求很高,应该还可以再压缩。本文采用一个int表示的方法。
* 表示方法如下:由于int的表示范围大于1e9,所以我们取一个int的低9位,为了方便寻找空格的位置,int
* 的个位我们用来放空格的位置(1-9)。而前8位,按照行从上到下,列从左到右的顺序依次记录对应位置上
* 的数字。例如:
* 可以表示成 2 3 1 5 8 4 6 7 5 ,个位的5表示空格在第5位,前八位数按顺序记录。坐标转换公式为:
num(压缩后的int) x y(求x行y列,1记起)1e(n)为 1乘10的n次
int temp=(x-1)*3+y
if temp > num%10 then return (num / 1e(9-temp+1)) %10
else return (num / 1e(9-temp) )%10
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
为了方便本文介绍,取目标状态为:1 2 3 4 5 6 7 8 9 即-->
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
操作本文用 u r d l 分别表示 空格的向上 向右 向下 向左 四个操作。比如,在简介中的图包括两步操作 l d ,可能与平时玩这类游戏的习惯不符合,但这是为了和ACM例题相统一。
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
对应地,每种操作引起的状态变化如下:
r :num值++ l :num值--
u :有点复杂
int t0 = 9-num%10 + 1
int t1 = num / 1e(t0)
int t2 = t1%1000
t1= t1- t2 + (t2 % 100) * 10 + t2 / 100
t1*= 1e(t0)
return (t1 + ( (num % t0) - 3))
d :见代码的change方法。
*
* 以上编码规则是参考了网上一位朋友的文章,我在此编码的基础上加了估值,例如num=2 3 1 5 8 4 6 7 5,
* 估值假设为5,那么编码成code=5 2 3 1 5 8 4 6 7 5,估值写在最前面,那么调用SortedList时就可以直接
* 让SortedList自己进行排序(当然,如果你想自己编写一个delegate来交给SortedList实现也是没问题的,但
* 我没测试过,不知道效率如何),那么现在的code就是由一个10位十进制的数组成,code已经不能再用int表示
* 了,因此我用了long (很不情愿,但想了很久还是用上了)。
*
* 另外我之前编了个也是解决八数码问题的深度优先递归算法,棋盘采用一维结构,却比这个搜索的时间短,
* 但不及“最好优先搜索”,主要是“最好优先搜索”所搜索的结点数实在是太少了,尽管排序浪费的时间
* 比较多,但测试过N次,性能最好的就是它。
*
* 本代码是为了应付人工智能的实验而编写的,写的潦草请不要介意。我又是通过这代码来“引玉”,相信
* 看过我编写的黑白棋源代码的人应该知道“引玉”是什么意思。如果你有“玉”(什么更高效的算法能在
* 更短的时间内求得结果,或者博弈方面的),就欢迎“砸”过来--fengart@126.com,我会很感激!
* (A* 算法解决八数码问题我已经研究过了,不要砸这个来)
* Fengart
* 2007.6.16
*
*/
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
#endregion
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// ten[i]代表10的i次方
/// </summary>
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
private static readonly long[] tens =...{ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 不是合理的编码
/// </summary>
private const int OutOfCode = -1;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 标志是否找到目标状态的编码
/// </summary>
public const int WinnerCode = 1;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private Direction[][] dirs;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private int startBoard;
private static int endBoard;
private static int[] endBoardArray;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private int MaxDepth;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private SortedList<long,StateMsg> openList;
private Stack<State> openStack;
private Queue<State> openQueue;
private Dictionary<long,StateMsg> boardtable;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private const int maxNodes = 362880; //至多搜索的结点数=最大局面状态数量:(9!)=362880;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private int nodes;
private int same;
private float time;
private Direction[] result;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 已经访问的结点数量
/// </summary>
public int Nodes
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
get ...{ return nodes; }
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 重复访问相同结点的数量
/// </summary>
public int Same
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
get ...{ return same; }
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
public float Time
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
get ...{ return time; }
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 最终结果
/// </summary>
public Direction[] Result
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
get ...{ return result; }
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
public FengartAI()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
dirs = new Direction[9][];
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
dirs[0] = new Direction[] ...{ Direction.Right, Direction.Down };
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
dirs[1] = new Direction[] ...{ Direction.Left, Direction.Right, Direction.Down };
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
dirs[2] = new Direction[] ...{ Direction.Left, Direction.Down };
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
dirs[3] = new Direction[] ...{ Direction.Up, Direction.Right, Direction.Down };
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
dirs[4] = new Direction[] ...{ Direction.Up, Direction.Left, Direction.Right, Direction.Down };
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
dirs[5] = new Direction[] ...{ Direction.Up, Direction.Left, Direction.Down };
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
dirs[6] = new Direction[] ...{ Direction.Up, Direction.Right };
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
dirs[7] = new Direction[] ...{ Direction.Left, Direction.Right, Direction.Up };
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
dirs[8] = new Direction[] ...{ Direction.Up, Direction.Left };
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 求与目标位置不同的个数(不计空格,因此返回值0~8)
/// </summary>
/// <param name="curboard"></param>
/// <returns></returns>
public static int Different(int curboard)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
int t_start = curboard;
int emp_start = curboard % 10;
int ev = 0;
//写2个for是为了减少9个if
for (int i = 9; i > emp_start; i--)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
t_start /= 10;
if (t_start % 10 != endBoardArray[i])
ev++;
}
for (int i = emp_start - 1; i >= 1; i--)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
t_start /= 10;
if (t_start % 10 != endBoardArray[i])
ev++;
}
return ev;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
public static int getBoard(long code)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return (int)(code % tens[9]);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private static int getEval(long code)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return (int)(code / tens[9]);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private static int getEmpIndex(long code)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return (int)(code % 10);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private static long combinCode(int board, int eval)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
long codehead = eval * tens[9];
return codehead + board;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 改变局面(移动空格)
/// </summary>
/// <param name="code"></param>
/// <param name="dir"></param>
public static long change(long code, Direction dir)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
int newboard;
int eval;
int num;
int t0;
long t1;
long t2;
switch (dir)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
case Direction.Left:
newboard = getBoard(code) - 1;
if (newboard == endBoard)
return WinnerCode;
eval = Different(newboard);
return combinCode(newboard, eval);
case Direction.Right:
newboard = getBoard(code) + 1;
if (newboard == endBoard)
return WinnerCode;
eval = Different(newboard);
return combinCode(newboard, eval);
case Direction.Up:
num = getBoard(code);
t0 = 9 - num % 10 + 1;
t1 = num / tens[t0];
t2 = t1 % 1000;
t1 = t1 - t2 + (t2 % 100) * 10 + t2 / 100;
t1 *= tens[t0];
newboard = (int)(t1 + ((num % tens[t0]) - 3));
if (newboard == endBoard)
return WinnerCode;
eval = Different(newboard);
return combinCode(newboard, eval);
case Direction.Down:
num = getBoard(code);
t0 = 9 - num % 10 + 1 - 3;//跟Up不同的地方
t1 = num / tens[t0];
t2 = t1 % 1000;
t1 = t1 - t2 + (t2 % 10) * 100 + t2 / 10;//跟Up不同的地方
t1 *= tens[t0];
newboard = (int)(t1 + ((num % tens[t0]) + 3));//跟Up不同的地方
if (newboard == endBoard)
return WinnerCode;
eval = Different(newboard);
return combinCode(newboard, eval);
}
return OutOfCode;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 恢复上一步的局面
/// </summary>
/// <param name="code"></param>
/// <param name="dir"></param>
public long unchange(long code, Direction dir)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return change(code, (Direction)(5 - dir));
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 当找到目标时,从哈希表里找原来的路径
/// </summary>
/// <param name="endCode"></param>
/// <param name="depth"></param>
private void setResult(long endCode, Direction curDir, Direction lastDir, int depth)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
long lastCode = endCode;
result = new Direction[depth];
result[depth - 1] = curDir;
for (int i = depth - 2; i >= 0; i--)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (boardtable.ContainsKey(lastCode))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
result[i] = boardtable[lastCode].Dir;
lastCode = unchange(lastCode, result[i]);
}
else
return;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//本算法的核心部分
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
带Open表和HashTable的最好优先搜索(每次扩展Open表后都对Open表排序)#region 带Open表和HashTable的最好优先搜索(每次扩展Open表后都对Open表排序)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 扩展Open表
/// </summary>
/// <param name="board"></param>
/// <param name="depth"></param>
private bool extentOpenList(long code, Direction lastDir, int depth)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
int empIndex = (int)(code % 10 - 1);
int len_moves = dirs[empIndex].Length;
long newcode;
Direction dir = 5 - lastDir;
for (int i = 0; i < len_moves; i++)
if (dirs[empIndex][i] != dir)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
newcode = change(code, dirs[empIndex][i]);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//跟目标匹配,结束
if (newcode == WinnerCode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
setResult(code, dirs[empIndex][i], lastDir, depth);
return true;
}
if (newcode <= tens[8])
throw new Exception("棋盘码修改错误! ");
if (newcode != OutOfCode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (!openList.ContainsKey(newcode))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (!boardtable.ContainsKey(newcode))
openList.Add(newcode, new StateMsg(depth, dirs[empIndex][i]));
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
same++;
if (depth < boardtable[newcode].Depth)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
boardtable.Remove(newcode);
openList.Add(newcode, new StateMsg(depth, dirs[empIndex][i]));
}
}
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
same++;
if (depth < openList[newcode].Depth)
openList[newcode] = new StateMsg(depth, dirs[empIndex][i]);
}
}
}
return false;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 带Open表和HashTable的最好优先搜索(每次扩展Open表后都对Open表排序)
/// </summary>
/// <returns></returns>
private int BestFirstSearch()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
int depth = 1;
Direction[] moves;
int board;
long newCode = combinCode(this.startBoard, 0);
int empIndex = getEmpIndex(newCode);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
moves = dirs[empIndex - 1];
StateMsg data;
if (extentOpenList(newCode, Direction.None, depth))
return WinnerCode;
while (openList.Count > 0)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
lock (this)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
nodes++;
if (nodes >= maxNodes)
return -1;
newCode = openList.Keys[0];
board = getBoard(newCode);
data = openList[newCode];
if (data.Depth != 0)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
depth = data.Depth;
if (board == endBoard)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return WinnerCode;
}
boardtable.Add(newCode, new StateMsg(depth, data.Dir));
openList.RemoveAt(0);
if (depth < MaxDepth)
if (extentOpenList(newCode, data.Dir, depth + 1))
return WinnerCode;
}
}
}
return -1;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
#endregion
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
带Open表和HashTable的深度优先搜索(排序后才插入Open表)#region 带Open表和HashTable的深度优先搜索(排序后才插入Open表)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 扩展OpenStack
/// </summary>
/// <param name="board"></param>
/// <param name="depth"></param>
private bool extentOpenStack(long code, Direction lastDir, int depth)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
int empIndex = (int)(code % 10 - 1);
int len_moves = dirs[empIndex].Length;
long newcode ;
SortedList<long, Direction> sort = new SortedList<long, Direction>(4);
Direction dir = 5 - lastDir;
Direction curdir;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
for (int i = 0; i < len_moves; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
curdir = dirs[empIndex][i];
if (curdir != dir)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
newcode = change(code, curdir);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//跟目标匹配,结束
if (newcode == WinnerCode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
setResult(code, dirs[empIndex][i], lastDir, depth);
return true;
}
if (newcode <= tens[8])
throw new Exception("棋盘码修改错误! ");
if (newcode != OutOfCode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (!boardtable.ContainsKey(newcode))
sort.Add(-newcode, curdir);
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
same++;
if (depth < boardtable[newcode].Depth)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
boardtable.Remove(newcode);
sort.Add(-newcode, curdir);
}
}
}
}
}
IEnumerator<KeyValuePair<long,Direction>> en = sort.GetEnumerator();
while (en.MoveNext())
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
openStack.Push(new State(-en.Current.Key, depth, en.Current.Value));
}
return false;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 带Open表和HashTable的深度优先搜索(排序后才插入Open表)
/// </summary>
/// <returns></returns>
private int DepthFirstSearch()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
lock (this)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
int depth = 1;
Direction[] moves;
int board;
long newCode = combinCode(this.startBoard, 0);
int empIndex = getEmpIndex(newCode);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
moves = dirs[empIndex - 1];
State data;
if (extentOpenStack(newCode, Direction.None, depth))
return WinnerCode;
while (openStack.Count > 0)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
lock (this)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
nodes++;
if (nodes >= maxNodes)
return -1;
data = openStack.Pop();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if (data != null)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
newCode = data.Code;
board = getBoard(newCode);
depth = data.Depth;
if (board == endBoard)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return WinnerCode;
}
if (boardtable.ContainsKey(newCode))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
same++;
if (depth < boardtable[newCode].Depth)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
boardtable[newCode] = new StateMsg(depth, data.Dir);
}
else
continue;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
boardtable.Add(newCode, new StateMsg(depth, data.Dir));
}
if (depth < MaxDepth)
if (extentOpenStack(newCode, data.Dir, depth + 1))
return WinnerCode;
}
}
}
return -1;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
#endregion
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
带Open表和HashTable的广度优先搜索(排序后才插入Open表)#region 带Open表和HashTable的广度优先搜索(排序后才插入Open表)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 扩展OpenQueue
/// </summary>
/// <param name="board"></param>
/// <param name="depth"></param>
private bool extentOpenQueue(long code, Direction lastDir, int depth)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
int empIndex = (int)(code % 10 - 1);
int len_moves = dirs[empIndex].Length;
long newcode;
SortedList<long, Direction> sort = new SortedList<long, Direction>(4);
Direction dir = 5 - lastDir;
Direction curdir;
for (int i = 0; i < len_moves; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
curdir = dirs[empIndex][i];
if (curdir != dir)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
newcode = change(code, curdir);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//跟目标匹配,结束
if (newcode == WinnerCode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
setResult(code, dirs[empIndex][i], lastDir, depth);
return true;
}
if (newcode <= tens[8])
throw new Exception("棋盘码修改错误! ");
if (newcode != OutOfCode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (!boardtable.ContainsKey(newcode))
sort.Add(newcode, curdir);
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
same++;
if (depth < boardtable[newcode].Depth)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
boardtable.Remove(newcode);
sort.Add(newcode, curdir);
}
}
}
}
}
IEnumerator<KeyValuePair<long, Direction>> en = sort.GetEnumerator();
while (en.MoveNext())
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
openQueue.Enqueue(new State(en.Current.Key, depth, en.Current.Value));
}
return false;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 带Open表和HashTable的广度优先搜索(排序后才插入Open表)
/// </summary>
/// <returns></returns>
private int BreadthFirstSearch()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
int depth = 1;
Direction[] moves;
int board;
long newCode = combinCode(this.startBoard, 0);
int empIndex = getEmpIndex(newCode);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
moves = dirs[empIndex - 1];
State data;
if (extentOpenQueue(newCode, Direction.None, depth))// Mask!
return WinnerCode;
while (openQueue.Count > 0) // Mask!
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
lock (this)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
nodes++;
if (nodes >= maxNodes)
return -1;
data = openQueue.Dequeue();// Mask!
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if (data != null)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
newCode = data.Code;
board = getBoard(newCode);
depth = data.Depth;
if (board == endBoard)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return WinnerCode;
}
if (boardtable.ContainsKey(newCode))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
same++;
if (depth < boardtable[newCode].Depth)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
boardtable[newCode] = new StateMsg(depth, data.Dir);
}
else
continue;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
boardtable.Add(newCode, new StateMsg(depth, data.Dir));
}
if (depth < MaxDepth)
if (extentOpenQueue(newCode, data.Dir, depth + 1))
return WinnerCode;
}
}
}
return -1;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
#endregion
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 把一维数组的局面编码成一个整数的表示形式
/// </summary>
/// <param name="genBoard"></param>
/// <returns></returns>
public int ToIntBoard(int[] genBoard)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
int board = 0;
int emp = 0;
for (int i = 0; i < genBoard.Length; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (genBoard[i] != 0)
board = 10 * board + genBoard[i];
else
emp = i + 1;
}
return 10 * board + emp;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 判断是否可以从初始状态到达目标状态(计算两个状态的逆序列,奇偶性相同的返回true)
/// </summary>
/// <param name="start"></param>
/// <param name="end"></param>
/// <returns></returns>
private bool ExistAns(int[] start, int[] end)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
int sequence_start = 0, sequence_end = 0;
for (int i = 0; i < start.Length; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (start[i] != 0)
for (int j = i + 1; j < start.Length; j++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (start[j] != 0 && start[j] < start[i])
sequence_start++;
}
if (end[i] != 0)
for (int j = i + 1; j < start.Length; j++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (end[j] != 0 && end[j] < end[i])
sequence_end++;
}
}
return (sequence_start + sequence_end) % 2 == 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 初始化求解
/// </summary>
/// <param name="start"></param>
/// <param name="end"></param>
/// <param name="maxDepth"></param>
private void InitComp(int[] start, int[] end, int maxDepth)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
nodes = 0;
same = 0;
MaxDepth = maxDepth;
result = null;
boardtable = new Dictionary<long, StateMsg>();
openList = new SortedList<long,StateMsg>();
openStack = new Stack<State>();
openQueue = new Queue<State>();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
this.startBoard = ToIntBoard(start);
endBoard = ToIntBoard(end);
int t_end = endBoard;
int emp_end = endBoard % 10;
endBoardArray = new int[10];
endBoardArray[0] = emp_end;
endBoardArray[emp_end] = 0;
for (int i = 9; i > emp_end; i--)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
t_end /= 10;
endBoardArray[i] = t_end % 10;
}
for (int i = emp_end - 1; i >= 1; i--)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
t_end /= 10;
endBoardArray[i] = t_end % 10;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//// <summary>
/// 求解8数码问题
/// </summary>
/// <param name="start"></param>
/// <param name="end"></param>
public Answer Compute(int[] start, int[] end, int maxDepth, int mode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (!ExistAns(start, end))
return Answer.NotExist;
InitComp(start, end, maxDepth);
if (startBoard == endBoard)
return Answer.Exist;
long oldtime = System.DateTime.Now.Ticks;
int eval = 0;
switch (mode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
case 0:
eval = DepthFirstSearch();
break;
case 1:
eval = BreadthFirstSearch();
break;
case 2:
eval = BestFirstSearch();
break;
default:
eval = BestFirstSearch();
break;
}
time = (System.DateTime.Now.Ticks - oldtime) / 10000000.0f;
if (eval == WinnerCode)
return Answer.Exist;
return Answer.NotExistInDepth;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
}