是什么导致一段时间后开始计算错误? [英] What could cause this to start miscalculating after awhile?

查看:77
本文介绍了是什么导致一段时间后开始计算错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为棋盘游戏实现 NegaMax .我现在正以0的深度进行测试,这意味着当前玩家只是评估自己的所有举动,而不考虑其他玩家接下来会做什么.它可以完美地在大约一半的游戏中正常工作(正确计算分数),然后在游戏进行的过程中开始吐出无意义的答案.

I'm trying to implement NegaMax for a game of checkers. I'm just testing it with a depth of 0 right now, meaning the current player just evaluates all his moves without regard to what the other player might do next. It works perfectly for about half the game (computes the scores correctly), and then part way through it starts spitting out non-sense answers.

例如,怀特可能还剩1个棋子,布莱克则有5个棋子,但是它将评估怀特的举动(例如得分为7),因为他们的输球都应该为负数.布莱克可能会在下一步行动中获胜,但即使获胜次数为1000,它也会将获胜的行动评估为-4.

For example, White might have 1 piece left, and Black will have 5, but it will evaluate White's moves as a score of 7 for example, when they should all be negative because he's losing. Black might about to win on his next move, but it will evaluate the winning move as a -4 even though it should be 1000.

我可以理解它始终输出垃圾,但是为什么它在头几回合就起作用,然后然后开始混乱?

I can understand it consistently outputting garbage, but why would it work for the first few turns and then start messing up?

private static Move GetBestMove(Color color, Board board, int depth)
{
    var bestMoves = new List<Move>();
    IEnumerable<Move> validMoves = board.GetValidMoves(color);
    int highestScore = int.MinValue;
    Board boardAfterMove;
    int tmpScore;
    var rand = new Random();

    Debug.WriteLine("{0}'s Moves:", color);

    foreach (Move move in validMoves)
    {
        boardAfterMove = board.Clone().ApplyMove(move);

        if (move.IsJump && !move.IsCrowned && boardAfterMove.GetJumps(color).Any())
            tmpScore = NegaMax(color, boardAfterMove, depth);
        else
            tmpScore = -NegaMax(Board.Opposite(color), boardAfterMove, depth);

        Debug.WriteLine("{0}: {1}", move, tmpScore);

        if (tmpScore > highestScore)
        {
            bestMoves.Clear();
            bestMoves.Add(move);
            highestScore = tmpScore;
        }
        else if (tmpScore == highestScore)
        {
            bestMoves.Add(move);
        }
    }

    return bestMoves[rand.Next(bestMoves.Count)];
}

private static int NegaMax(Color color, Board board, int depth)
{
    return BoardScore(color, board);
}

private static int BoardScore(Color color, Board board)
{
    if (!board.GetValidMoves(color).Any()) return -1000;
    return board.OfType<Checker>().Sum(c => (c.Color == color ? 1 : -1) * (c.Class == Class.Man ? 2 : 3));
}


我在6x6的板上隔离了一个不喜欢的板状态:


I've isolated a board state that it doesn't like, on a 6x6 board:

 . . .
. w B 
 W . .
. . . 
 . w .
. . W 

w = white, b = black, capital letter = king

看来这不是时间或移动次数问题,只是不喜欢特定的董事会状态.不过,我看不到任何有关此状态的奇特信息.

It appears that this is not a time or number-of-moves played issue, it just doesn't like particular board states. I don't see anything peculiar about this state though.

在这种状态下,它将布莱克的所有4步动作评估为-13.如果您看一下我的得分方式,则表示每个人2分,每个国王3分,如果由其他球员拥有,则为负.看起来好像将所有碎片都视为白色...这是获得13的唯一方法.

In this state, it evaluates all 4 of Black's moves as -13. If you look at how I did the scoring, it says 2 pts per man, 3 pts per king, negative if owned by the other player. It looks as though it is treating all the pieces as white...that's the only way to get 13.

我找到了另一个线索.在棋盘得分法中,我得到了它来打印所看到的内容.这就是告诉我的内容:

I found another clue. In the board score method I got it to print what it's seeing.. this is what it's telling me:

2: White 
4: White 
6: White 
13: White 
17: White 

木板正方形的编号如下:

Where the board squares are numbered like this:

  00  01  02
03  04  05
  06  07  08
09  10  11
  12  13  14
15  16  17

我认为确实是说黑色的部分是白色的...现在找出造成这种情况的原因.

I think it is indeed saying the black piece is white...... now to figure out what's causing this.

所以...现在我知道颜色是错误的,但只对BoardScore函数有效.我的常规显示例程从未对此付诸实践,否则我将在数小时前发现问题.我认为可能是在ApplyMove函数中颜色被切换了.

So... now I know that the color is wrong, but only to the BoardScore function. My normal display routine never picked up on this otherwise I would have figured out the problem hours ago. I'm thinking it might be in the ApplyMove function that the color gets switched..

public Board ApplyMove(Move m)
{
    if (m.IsJump)
    {
        bool indented = m.Start % Width < _rowWidth;
        int offset = indented ? 1 : 0;
        int enemy = (m.Start + m.End) / 2 + offset;
        this[m.Color, enemy] = Tile.Empty;
    }

    this[m.Color, m.End] = this[m.Color, m.Start];
    this[m.Color, m.Start] = Tile.Empty;

    var checker = this[m.Color, m.End] as Checker;
    if (m.IsCrowned) checker.Class = Class.King;

    return this;
}

但这也没有多大意义……只是将片段从开始位置复制到结束位置.需要研究m.Color是什么...也许它会提供更多线索!我感觉像个侦探.

But that doesn't make a lot of sense either... the piece is just copied from the start position to the end position. Need to investigate what m.Color is... perhaps it'll provide more clues! I feel like a detective.

推荐答案

鉴于您的描述,我发现自己怀疑零件颜色数据.如果以某种方式将其设置为错误,则会将一切评估为否定.

Given your description I find myself suspecting the piece color data. If it were somehow set to something wrong it would evaluate everything as negative.

我发现自己对您的BoardScore函数不太满意-像这样的复杂公式可以隐藏错误并且很难调试.

I find myself not too happy with your BoardScore function--complex formulas like that are good at hiding errors and are hard to debug.

我将添加一个Checker.Value(Color)函数来简化BoardScore,并使您可以更轻松地查看正在发生的事情.

I would add a function Checker.Value(Color) to simplify BoardScore and allow you to view what was going on more easily.

您尚未显示Color的数据类型,如果它允许的损坏值超过黑白,则将导致您观察到的行为.

You haven't shown the datatype of Color, if it permits more than black and white a corrupted value there would cause the behavior you are observing.

鉴于您的最新更新,我将查看boardAfterMove并确保其正确生成.

Given your latest update I would look at boardAfterMove and make sure it's being generated correctly.

再次那里有两个电话-是否克隆正确?

Edit again: There are two calls there--is it cloning properly?

这篇关于是什么导致一段时间后开始计算错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆