加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 我的A *搜索8-Puzzle有什么问题?

发布时间:2020-12-15 22:06:17 所属栏目:百科 来源:网络整理
导读:我试图使用这些启发式的A *搜索来解决8-Puzzle: – h1:错位的瓷砖数量 – h2:总曼哈顿距离 – h3:以上的总和 移动的图块称为0. 我的目标是解决这些问题: 4 1 25 8 37 0 6 和 8 6 72 5 43 0 1 我遇到的问题是,通过我目前的A *实现,它能够解决第一个问题,
我试图使用这些启发式的A *搜索来解决8-Puzzle:
– h1:错位的瓷砖数量
– h2:总曼哈顿距离
– h3:以上的总和

移动的图块称为0.

我的目标是解决这些问题:

4 1 2
5 8 3
7 0 6

8 6 7
2 5 4
3 0 1

我遇到的问题是,通过我目前的A *实现,它能够解决第一个问题,但不能解决第二个问题.

所以请帮助我理解我的A *代码有什么问题:

int [,] current =从控制台输入为字符串(412583706)并转换为表示拼图的2D int.
正确相同,其中0位于右下角.

var openList = new List<int[,]> { current };
var closedList = new List<int[,]>();

while (openList.Count > 0)
{
    steps++;
    current = GetBestNodeFromList(correct,dimensions,openList,useHeuristic);
    // "GetBestNodeFromList()" finds the cheapest node in the openList.
    // cheapest node: lowest value of h3.

    openList.Remove(current);
    h1 = getHeuristic1b(current,correct,dimensions);
    h2 = getHeuristic2b(current,dimensions);
    h3 = h1 + h2;
    if (h1 == 0 && h2 == 0) { break; }

    openList = Puzzle_PossibleNext(current,closedList);
    // the method "PossibleNext()" finds possible next moves from the current
    // position. if the next move exists in the closedList,it is discarded.

    // Drawing the puzzle and showing heuristics.
    DrawCurrentState(h1,h2,h3,current,steps);

    // adding last visited position to the closedlist.
    closedList.Add(current);
}

第一个问题通过7个步骤解决.
根据我测试的不同程序,下一个问题可以通过32个步骤解决.

我的程序与另一个程序的不同之处在于前4个步骤是相同的??,然后另一个程序选择不同的路径,而我的程序一直在继续,无法找到解决方案.
看起来我的程序确实选择了最便宜的节点,所以这就是为什么我无法理解什么是错的.

这是我第一次使用寻路算法,所以我想解决它.
我已经有这个问题3天,我觉得我已经尝试了很多解决方案,但没有一个工作T_T

最好的祝福.

– – 编辑 – – –
附加代码:

// Put heuristic value from all in list,then return list item with lowest h-value.
static int[,] GetBestNodeFromList(int[,] correct,int d,List<int[,]> list,string useHeuristic)
{
    int[,] n = new int[d,d];
    if (list.Count > 0)
    {
        List<Int32> heuristicsValueList = new List<Int32>();
        for (int i = 0; i < list.Count; i++)
        {
            if (useHeuristic == "h1")      { heuristicsValueList.Add(getHeuristic1b(list[i],d)); }
            else if (useHeuristic == "h2") { heuristicsValueList.Add(getHeuristic2b(list[i],d)); }
            else  { heuristicsValueList.Add(getHeuristic3(list[i],d)); }
        }
        n = list[heuristicsValueList.IndexOf(heuristicsValueList.Min())];
    }
    return n;
}

———编辑2 ——–
?改变了我的代码,但仍然没有运气
拼图设置/节点及其启发式都在PuzzleNode对象中.

//从当前节点返回下一个可能移动的列表.
//不包括在closedNodeList中找到的移动.

static List<PuzzleNode> Puzzle_GenerateNextNodes(PuzzleNode node,List<PuzzleNode> closedNodeList)
        {
            List<PuzzleNode> nextList = new List<PuzzleNode>();
            Point isNow = new Point(0,0);

            // 1) Find where [0] is.
            int dimensions = (int)Math.Sqrt((double)node.n.Length);
            for (int x = 0; x < dimensions; x++) {
                for (int y = 0; y < dimensions; y++) { if (node.n[x,y] == 0) { isNow.X = y; isNow.Y = x; break; } }
            }

            // 2) Check possible moves.
            bool moveUp = false,moveDown = false,moveLeft = false,moveRight = false;

            if (isNow.X == 0)
            {
                moveRight = true;
                if (isNow.Y == 0) { moveDown = true; }
                else if (isNow.Y == 1) { moveUp = true; moveDown = true; }
                else if (isNow.Y == 2) { moveUp = true; }
            }
            else if (isNow.X == 1)
            {
                moveRight = true;
                moveLeft = true;
                if (isNow.Y == 0) { moveDown = true; }
                else if (isNow.Y == 1) { moveUp = true; moveDown = true; }
                else if (isNow.Y == 2) { moveUp = true; }
            }
            else if (isNow.X == 2)
            {
                moveLeft = true;
                if (isNow.Y == 0) { moveDown = true; }
                else if (isNow.Y == 1) { moveUp = true; moveDown = true; }
                else if (isNow.Y == 2) { moveUp = true; }
            }
            // 3) Create list of possible moves.

// Add moved puzzle node to list over next moves 
            if (moveRight)
            {
                int[,] right = new int[dimensions,dimensions];
                Array.Copy(node.n,right,node.n.Length);
                PuzzleNode tmp = new PuzzleNode( PuzzleMoveRight(right,isNow.X,isNow.Y) );
                if (!ListHasThisValue(tmp.n,closedNodeList,dimensions)) { nextList.Add(tmp); }
            }
// moveleft,up,down,same structure as moveRight
            if (moveLeft)
            {
                ..
            }
            if (moveUp)
            {
                ..
            }
            if (moveDown)
            {
                ..
            }

            return nextList;
        }

———–编辑3 —————-

顺便说一句,我想问一下,如果我对A *的不同步骤的实现得到了正确的理解.
目前,我的程序的A *搜索执行此操作:

>创建初始列表OPEN和CLOSED,将起始节点添加到OPEN
>启动循环,从OPEN中删除最便宜的节点,将其添加到CLOSED
*最便宜的节点由其曼哈顿距离值决定.
>使用节点查找邻居/子节点/下一步移动,添加这些移动
到SUCCESSOR列表.
>探索SUCCESSOR列表,检查其中是否包含目标状态,
否则添加到OPEN列表
>重复2-4,探索列表中的节点.

当我用Q1尝试这些步骤时,我得到7个步骤的解决方案,这是正确的.这也可以手工找到.
但是对于Q2,它一直持续到OPEN列表为空,没有其他东西可以探索.
那我错过了什么?

解决方法

我能够通过蛮力迅速找到解决方案.如果你使用完全愚蠢的启发式,A *应该恢复暴力.你如何比较你的州与封闭州名单?

var set = new int[,] {
  { 1,2,3 },{ 4,5,6 },{ 7,8,0 }
};
var clone = (int[,])set.Clone();

var foo = clone == set; // foo is false
var bar = clone.Equals(set); // bar is false

var closedStates = new List<int[,]>();
closedStates.Contains(state); // wrong - contains is using Equals
closedStates.Any(cs => AreEqual(cs,state)); // correct

static bool AreEqual(int[,] stateA,int[,] stateB) {
  for (var x = 0; x < DIMENSIONS; x++) {
    for (var y = 0; y < DIMENSIONS; y++) {
      if (stateA[x,y] != stateB[x,y]) {
        return false;
      }
    }
  }
  return true;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读