问题描述:
有一个3×3的棋盘,其中有0~8九个数字,0表示空格,其他的数字可以和0交换位置。求由初始状态到达目标状态步数最少的解。
解决八数码问题的常用方法为图搜索法,可用广度优先、深度优先和A*算法实现,其中A*算法又因估价函数的不同而有着不同的搜索时间。
程序说明:
在本程序中,用广度优先、实现了八数码问题, 初始状态默认为: 目标状态为:
2 8 3 1 2 3
1 0 4 7 8 4
7 6 5 0 6 5
程序实现:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace bashuma { class Program { const int N=3; static List<Node> open = new List<Node>(); static List<Node> colse = new List<Node>(); enum Move{Left,Top,Right,Bottom}; static void Main(string[] args) { int[,] SourceMetrix = new int[,] { { 2, 8, 3 }, { 1, 0, 4 }, { 7, 6, 5 } }; int[,] TargetMetrix = new int[,] { { 1, 2, 3, }, { 7, 8, 4 }, { 0, 6, 5 } }; Node n = new Node(); n.ID = 1; n.Metrix = new int[,] { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; ArrayCopy( n.Metrix ,SourceMetrix); n.PID=1; open.Add(n); //colse.Add(n); int i = 1; while (open.Count >= 1) { Node current = open[0]; open.RemoveAt(0); colse.Add(current); if (IsEnd(current, TargetMetrix) == 1) { PrintPath(colse); break; } Node parent = colse[current.PID -1 ]; if (IsMove(current, parent, Move.Left) == 1) { i++; Node tNode = new Node(); tNode.ID = i; tNode.PID = current.ID; tNode.Metrix = new int[,] { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; int[,] tmp = new int[,] { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; ArrayCopy(tmp,current .Metrix); tNode.Metrix = MetrixMove(tmp, Move.Left); open.Add(tNode); } if (IsMove(current, parent, Move.Top) == 1) { i++; Node tNode = new Node(); tNode.ID = i; tNode.PID = current.ID; tNode.Metrix = new int[,] { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; int[,] tmp = new int[,] { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; ArrayCopy(tmp, current.Metrix); tNode.Metrix = MetrixMove(tmp, Move.Top); open.Add(tNode); } if (IsMove(current, parent, Move.Right) == 1) { i++; Node tNode = new Node(); tNode.ID = i; tNode.PID = current.ID; tNode.Metrix = new int[,] { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; int[,] tmp = new int[,] { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; ArrayCopy(tmp, current.Metrix); tNode.Metrix = MetrixMove(tmp, Move.Right); open.Add(tNode); } if (IsMove(current, parent, Move.Bottom) == 1) { i++; Node tNode = new Node(); tNode.ID = i; tNode.PID = current.ID; tNode.Metrix = new int[,] { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; int[,] tmp = new int[,] { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; ArrayCopy(tmp, current.Metrix); tNode.Metrix = MetrixMove(tmp, Move.Bottom); open.Add(tNode); } } } private static int[,] ArrayCopy(int [,] s,int [,] t) { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { s[i,j] = t[i,j]; } } return s; } /// <summary> /// 移动状态 /// </summary> /// <param name="array"></param> /// <param name="move"></param> /// <returns></returns> private static int[,] MetrixMove(int [,] array, Move move) { int[,] tmp = { {0,0,0},{0,0,0},{0,0,0}}; ArrayCopy(tmp,array); int row = -1; int col = -1; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (tmp[i,j] == 0) { row = i; col = j; break; } } if ((row != -1) && (col != -1)) { break; } } if ((row >= 0 || row <= 2) && (col >= 0 || col <= 2)) { int i = row; int j = col; //Move m = move; switch (move) { case Move.Left: j--; // m = Move.Right; break; case Move.Top: i--; //m = Move.Bottom; break; case Move.Right: j++; //m = Move.Left; break; case Move.Bottom: i++; //m = Move.Top; break; default: break; } if ((i >= 0 && i <= 2) && (j >= 0 && j <= 2)) { //int[][] mt = MetrixMove(tmp, row, col, m); return MetrixMove(tmp,row,col,move); } } return tmp; } /// <summary> /// 移动状态 /// </summary> /// <param name="m">状态矩阵</param> /// <param name="row"></param> /// <param name="col"></param> /// <param name="move"></param> /// <returns></returns> private static int[,] MetrixMove(int[,] m, int row, int col, Move move) { int[,] tmp = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; ArrayCopy(tmp, m); if ((m != null) && (row >= 0 && row <= 2) && (col >= 0 && col <= 2)) { int i = row; int j = col; switch (move) { case Move .Left: j--; break; case Move .Top : i--; break; case Move .Right : j++; break; case Move .Bottom : i++; break; default : i = -1; j = -1; break; } if ((i >= 0 && i <= 2) && (j >= 0 && j <= 2)) { int val = tmp[i,j]; tmp[i,j] = tmp[row,col]; tmp[row,col] = val; } else { return null; } } else { return null; } return tmp; } /// <summary> /// 判断当前状态是否可以移动操作 /// </summary> /// <param name="n"></param> /// <param name="p"></param> /// <param name="move"></param> /// <returns></returns> private static int IsMove(Node n, Node p, Move move) { if (n.PID == n.ID) { return 1; } int row = -1; int col = -1; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (n.Metrix[i,j] == 0) { row = i; col = j; break; } } if ((row != -1) && (col != -1)) { break; } } if ((row >= 0 || row <= 2) && (col >= 0 || col <= 2)) { int i = row; int j = col; Move m = move; switch (move) { case Move.Left: j--; break; case Move.Top: i--; break; case Move.Right: j++; break; case Move.Bottom: i++; break; default: break; } if ((i >= 0 && i <= 2) && (j >= 0 && j <= 2)) { int[,] mt = MetrixMove(n.Metrix ,row,col,m); if ((mt != null)) { if (IsTheSameMetrix(mt, p.Metrix) == 0) { return 1; } } } } return 0; } /// <summary> /// 判断连个矩阵元素是否相同 /// </summary> /// <param name="m1"></param> /// <param name="m2"></param> /// <returns>0 否,1 是</returns> private static int IsTheSameMetrix(int[,] m1, int[,] m2) { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (m1[i,j] !=m2[i,j]) { return 0; } } } return 1; } /// <summary> /// 判断当前状态是否是目标状态 /// </summary> /// <param name="node">状态节点</param> /// <param name="target">目标矩阵值</param> /// <returns></returns> private static int IsEnd(Node node, int [,]target) { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (node.Metrix[i,j] != target[i,j]) { return 0; } } } return 1; } /// <summary> /// 输出搜索路径 /// </summary> /// <param name="list"></param> private static void PrintPath(List<Node> list) { if (null == list) { return; } List<Node> tmp = new List<Node>(); int pid = list[list.Count - 1].PID; tmp.Add(list[list.Count - 1]); for (int i = list.Count - 2; i >= 0; i--) { if (list[i].ID == pid) { tmp.Add(list[i]); pid = list[i].PID; } } for (int j = tmp.Count - 1; j >= 0; j--) { PrintMetrix(tmp[j].Metrix); } } /// <summary> /// 输出一个矩阵 /// </summary> /// <param name="m"></param> private static void PrintMetrix(int[,] m) { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { Console.Write("{0}/t", m[i, j]); } Console.WriteLine(); } Console.WriteLine("**************************"); } } /// <summary> /// 状态空间数据结构 /// </summary> struct Node { public int ID; public int [,] Metrix ; public int PID; } }