N-Puzzle Game
N-Puzzle 是一种滑块类推盘游戏,常见的有15-puzzle和8-puzzle。
如下图所示,由15个方块和一个空位组成,规则很简单,移动方块,让所有的方块按照数字的顺序排列。
使用Silverlight实现如下:
那么如何使用算法来解决15-puzzle,已得到一个在任意状态下到达最终按顺序排列的一个路径呢?
IDA*(Iterative Deepening A*) 算法
IDA*是迭代加深的A*算法,深度优先,一次只记录一条路径,减少空间需求。
简单来说,给定一个限定值limit,开始深度优先搜索,当前节点的F()(估值函数)值超过limit时结束,然后每次增加limit,循环迭代搜索直到找到最终路径。
1. GoalState : 最终按数字顺序排列的状态
2. StartState : 任意打乱顺序的开始状态
3. IsResolved : 判断当前状态是否已达到GoalState
4. Manhattan Distance : 对于当前状态的任一点 P1(X1,Y1),到其值在目标状态的位置 P2(X2,Y2)的距离, D= Abs(X1-X2) + Abs(Y1-Y2)
算法如下:

1 public class PuzzleNode 2 { 3 public PuzzleNode(int[] state, int blank, PuzzleNode node) 4 { 5 this.state = state; 6 this.BlankPosition = blank; 7 this.parent = node; 8 if (parent != null) 9 cost = parent.Cost + 1; 10 } 11 12 /// <summary> 13 /// The current state 14 /// </summary> 15 /// <returns></returns> 16 public int[] CurrentState() 17 { 18 return state; 19 } 20 21 /// <summary> 22 /// Total cost 23 /// </summary> 24 public int Cost { get { return cost; } } 25 26 /// <summary> 27 /// The position of blank 28 /// </summary> 29 public int BlankPosition { get; set; } 30 31 /// <summary> 32 /// The move from parent to the current node 33 /// </summary> 34 public Direction Direction { get; set; } 35 36 private int[] state; 37 private int cost; 38 private PuzzleNode parent; 39 }

1 public List<PuzzleNode> IDAStar(int[] startboard) 2 { 3 int limit = SearchHelper.Heuristic(root); 4 5 List<PuzzleNode> solution = null; 6 List<PuzzleNode> path = new List<PuzzleNode>(); 7 path.Add(root); 8 while (solution == null) 9 { 10 solution = DepthLimitSearch(limit, path); 11 limit += 1; 12 } 13 14 return solution; 15 } 16 17 private List<PuzzleNode> DepthLimitSearch(int cost, List<PuzzleNode> path) 18 { 19 if (cost >= Int32.MaxValue) 20 throw new ArgumentException("cost over flow"); 21 22 var node = path.Last(); 23 if (IsSolved(node)) 24 { 25 return path; 26 } 27 28 foreach (var child in GetSuccessors(node)) 29 { 30 if (((int)child.Direction + (int)node.Direction != 0) && (SearchHelper.Heuristic(child) + child.Cost) <= cost) 31 { 32 var nextpath = new List<PuzzleNode>(path); 33 nextpath.Add(child); 34 var solution = DepthLimitSearch(cost, nextpath); 35 if (solution != null) 36 { 37 return solution; 38 } 39 } 40 } 41 return null;
我们将数字换成图片,变成一个拼图游戏。大家来试一下吧。