下面是一个使用C#语言实现A*算法解决八数码问题的示例代码:
using System;
using System.Collections.Generic;
class Node
{
public int[] state;
public int cost;
public int heuristic;
public int depth;
public Node parent;
public Node(int[] s, int c, int h, int d, Node p)
{
state = s;
cost = c;
heuristic = h;
depth = d;
parent = p;
}
}
class EightPuzzleSolver
{
private static readonly int[] goalState = { 1, 2, 3, 4, 5, 6, 7, 8, 0 };
// 计算当前状态与目标状态的曼哈顿距离
private static int CalculateManhattanDistance(int[] currentState)
{
int distance = 0;
for (int i = 0; i < currentState.Length; i++)
{
if (currentState[i] != goalState[i])
{
distance += Math.Abs((currentState[i] % 3) - (goalState[i] % 3)) +
Math.Abs((currentState[i] / 3) - (goalState[i] / 3));
}
}
return distance;
}
// 检查是否为合法状态
private static bool IsValidState(int[] state)
{
// 八数码问题中,空白位置用0表示
// 检查数组中是否包含重复元素(除了空白位置)
HashSet<int> set = new HashSet<int>(state);
if (set.Count != state.Length || set.Contains(0))
{
return false;
}
return true;
}
// 查找数组中指定元素的索引
private static int FindIndex(int[] array, int value)
{
for (int i = 0; i < array.Length; i++)
{
if (array[i] == value)
{
return i;
}
}
return -1;
}
// 获取空白位置可以移动的方向
private static List<int> GetValidMoves(int blankIndex)
{
List<int> validMoves = new List<int>();
if (blankIndex >= 3) // 可以向上移动
validMoves.Add(blankIndex - 3);
if (blankIndex % 3 != 0) // 可以向左移动
validMoves.Add(blankIndex - 1);
if ((blankIndex + 1) % 3 != 0) // 可以向右移动
validMoves.Add(blankIndex + 1);
if (blankIndex < 6) // 可以向下移动
validMoves.Add(blankIndex + 3);
return validMoves;
}
public static void SolvePuzzle(int[] initialState)
{
if (!IsValidState(initialState))
{
Console.WriteLine("无效的初始状态");
return;
}
PriorityQueue<Node> openList = new PriorityQueue<Node>();
Node initialNode = new Node(initialState, 0, CalculateManhattanDistance(initialState), 0, null);
openList.Enqueue(initialNode, initialNode.cost + initialNode.heuristic);
HashSet<string> visitedStates = new HashSet<string>();
while (!openList.IsEmpty())
{
Node current = openList.Dequeue();
visitedStates.Add(string.Join(",", current.state));
if (current.state.Equals(goalState))
{
Console.WriteLine("找到解决方案!");
// 输出解决路径
List<Node> path = new List<Node>();
Node node = current;
while (node != null)
{
path.Insert(0, node);
node = node.parent;
}
foreach (Node n in path)
{
PrintPuzzle(n.state);
Console.WriteLine();
Console.WriteLine("移动成本: " + n.cost);
Console.WriteLine("启发式值: " + n.heuristic);
Console.WriteLine("----------------------");
}
return;
}
int blankIndex = FindIndex(current.state, 0);
List<int> validMoves = GetValidMoves(blankIndex);
foreach (int move in validMoves)
{
int[] newState = (int[])current.state.Clone();
// 交换空白位置与移动方向上的数字
int temp = newState[move];
newState[move] = 0;
newState[blankIndex] = temp;
if (!visitedStates.Contains(string.Join(",", newState)))
{
Node newNode = new Node(newState, current.cost + 1,
CalculateManhattanDistance(newState),
current.depth + 1,
current);
openList.Enqueue(newNode, newNode.cost + newNode.heuristic);
visitedStates.Add(string.Join(",", newState));
}
}
}
Console.WriteLine("无法找到解决方案");
}
private static void PrintPuzzle(int[] state)
{
for (int i = 0; i < state.Length; i++)
{
if (state[i] == 0)
Console.Write("_ ");
else
Console.Write(state[i] + " ");
if ((i + 1) % 3 == 0)
Console.WriteLine();
}
}
static void Main(string[] args)
{
int[] initialState = { 1, 2, 3, 4, 5, 6, 8, 7, 0 };
SolvePuzzle(initialState);
}
}
该代码实现了一个八数码问题的求解器,使用A*算法和曼哈顿距离作为启发式函数进行搜索。你可以根据需要自行调整初始状态,并运行该代码以获取解决方案。
内容由零声教学AI助手提供,问题来源于学员提问