ZBLOG

用c#语言写一段完整代码解决A*算法实现八数码问题

下面是一个使用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助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=10034

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?