C# Tic-tac-toe评估误差

C# Tic-tac-toe评估误差,c#,evaluation,tic-tac-toe,alpha-beta-pruning,C#,Evaluation,Tic Tac Toe,Alpha Beta Pruning,我试着用不同的板子大小和块数来制作tic-tac-toe,以赢得比赛 我有一个依赖于开放路径的求值函数。例如,如果我们有 O--X O--- --O O--X O--- --O 我们得到10^2(垂直第一列)+10^1(垂直第二列)+10^1(对角线)+10^1(水平第二行)+10^1(水平最后一行) 要获得最佳移动,我使用函数: public Move FindBestMove(Board board, int depth, Game.Player currentTurn, Board.Pie

我试着用不同的板子大小和块数来制作tic-tac-toe,以赢得比赛

我有一个依赖于开放路径的求值函数。例如,如果我们有

O--X O--- --O O--X O--- --O 我们得到10^2(垂直第一列)+10^1(垂直第二列)+10^1(对角线)+10^1(水平第二行)+10^1(水平最后一行)

要获得最佳移动,我使用函数:

public Move FindBestMove(Board board, int depth, Game.Player currentTurn, Board.Piece currentPiece, Move move1 = null)
{
    if (depth <= 0 || board.AreEmptyPlaces() == false)
    {
        move1.Score = board.Score;

        if (_log)
        {
            Console.WriteLine("\n" + new String('\t', 4 - depth) +
                              string.Format("bestScore = {0}, player = {1}, status = {2}", board.Score,
                                            currentTurn, move1.EvaluateResult + "\n"));
        }

        return move1;
    }

    List<Move> allMoves = board.GetAllMoves(currentPiece);
    Move bestMove = null;

    foreach (Move move in allMoves)
    {
        Board newBoard = (Board)board.Clone();
        newBoard.MakeMove(move);

        Board newBoardForOpponent = (Board)board.Clone();
        Move moveForOppeonent = new Move { Piece = move.Piece == Board.Piece.O ? Board.Piece.X : Board.Piece.O, Position = move.Position, Score = move.Score };
        newBoardForOpponent.MakeMove(moveForOppeonent);

        IEvaluate evaluateOpenPathForOpponent = new EvaluateOpenPath(newBoardForOpponent.BoardSize, newBoardForOpponent.pieces, currentPiece == Board.Piece.O ? Board.Piece.X : Board.Piece.O, newBoardForOpponent.ToWin);
        IEvaluate evaluateOpenPath = new EvaluateOpenPath(newBoard.BoardSize, newBoard.pieces, currentPiece, newBoard.ToWin);

        EvaluateResult opponentResult = evaluateOpenPathForOpponent.EvaluateOpponent();
        EvaluateResult playerResult = evaluateOpenPath.Evaluate();

        if (currentTurn == Game.Player.Computer)
        {
            newBoard.Score += (playerResult.Score) + (opponentResult.Status == EvaluateResult.EvaluateStatus.Won ? opponentResult.Score : 0);
        }
        else
        {
            newBoard.Score += (playerResult.Score) + (opponentResult.Status == EvaluateResult.EvaluateStatus.Lost ? opponentResult.Score : 0);
        }

        if (currentTurn == Game.Player.Computer && (_initialDepth == depth || _initialDepth - 1 == depth) &&
            //(playerResult.Score == 0 && opponentResult.Score == 0) &&
                   (opponentResult.Status == EvaluateResult.EvaluateStatus.Lost ||
                    playerResult.Status == EvaluateResult.EvaluateStatus.Won))
        {
            //bestMove = BestMoveChagneStatus(bestMove, move, playerResult, opponentResult);
            bestMove = BestMoveChagneStatus(bestMove, move, playerResult, opponentResult);
            bestMove.Source = Move.SourceEnum.LostOrWon;
            break;
        }

        if (_log)
        {
            Console.WriteLine(
                new String('\t', 4 - depth) +
                "gracz = {1}, pozycja = {2},wynik = {0}, glebokosc = {3}, status = {4}, (bestmove = {5})",
                newBoard.Score, move.Piece, move.Position, depth, move.EvaluateResult, bestMove);
        }

        Move findBestMove = FindBestMove(newBoard, depth - 1, (currentTurn == Game.Player.Computer ? Game.Player.Human : Game.Player.Computer), (currentPiece == Board.Piece.O ? Board.Piece.X : Board.Piece.O), move);
        if (findBestMove != null)
        {
            if (bestMove == null)
            {
                bestMove = findBestMove;
            }
            else
            {
                if (currentTurn == Game.Player.Computer &&
                    //(playerResult.Score == 0 && opponentResult.Score == 0) &&
                           (opponentResult.Status == EvaluateResult.EvaluateStatus.Lost ||
                            playerResult.Status == EvaluateResult.EvaluateStatus.Won))
                {
                    //bestMove = BestMoveChagneStatus(bestMove, move, playerResult, opponentResult);
                    bestMove = BestMoveChagneStatus(bestMove, move, playerResult, opponentResult);
                    bestMove.Source = Move.SourceEnum.LostOrWon;
                    break;
                }

                if (bestMove.EvaluateResult == EvaluateResult.EvaluateStatus.None && findBestMove.EvaluateResult != EvaluateResult.EvaluateStatus.None)
                {
                    bestMove = BestMoveChagneStatus(bestMove, findBestMove, playerResult, opponentResult);
                    bestMove.Source = Move.SourceEnum.Status;
                }
                else if (bestMove.EvaluateResult == EvaluateResult.EvaluateStatus.Lost &&
                         findBestMove.EvaluateResult == EvaluateResult.EvaluateStatus.Won)
                {
                    bestMove = BestMoveChagneStatus(bestMove, findBestMove, playerResult, opponentResult);
                    bestMove.Source = Move.SourceEnum.Status;
                }
                else if (findBestMove.Score > bestMove.Score && findBestMove.EvaluateResult == EvaluateResult.EvaluateStatus.Won)
                {
                    bestMove = BestMoveChagneStatus(bestMove, findBestMove, playerResult, opponentResult);
                    bestMove.Source = Move.SourceEnum.Score;
                }
                else if (findBestMove.Score == bestMove.Score && Random.NextDouble() > 0.00 && findBestMove.EvaluateResult == EvaluateResult.EvaluateStatus.Won)
                {
                    bestMove = BestMoveChagneStatus(bestMove, findBestMove, playerResult, opponentResult);
                    bestMove.Source = Move.SourceEnum.Score;
                }
            }
        }
    }

    return bestMove;

}

private static Move BestMoveChagneStatus(Move bestMove, Move move, EvaluateResult playerResult,
                                         EvaluateResult opponentResult)
{
    bestMove = move;
    if (playerResult.Status != EvaluateResult.EvaluateStatus.None)
    {
        bestMove.EvaluateResult = playerResult.Status;
    }
    else if (opponentResult.Status != EvaluateResult.EvaluateStatus.None)
    {
        bestMove.EvaluateResult = opponentResult.Status;
    }
    else
    {
        bestMove.EvaluateResult = EvaluateResult.EvaluateStatus.None;
    }
    return bestMove;
}
public Move FindBestMove(棋盘,整数深度,游戏。玩家当前回合,棋盘。棋子当前棋子,移动移动1=null)
{
if(depth bestMove.Score&&findBestMove.EvaluateResult==EvaluateResult.evaluateTestatus.Won)
{
bestMove=BestMoveChagneStatus(bestMove、findBestMove、playerResult、opponentResult);
bestMove.Source=Move.SourceEnum.Score;
}
else if(findBestMove.Score==bestMove.Score&&Random.NextDouble()>0.00&&findBestMove.EvaluateResult==EvaluateResult.EvaluateStatus.Won)
{
bestMove=BestMoveChagneStatus(bestMove、findBestMove、playerResult、opponentResult);
bestMove.Source=Move.SourceEnum.Score;
}
}
}
}
返回最佳移动;
}
私有静态移动最佳移动状态(移动最佳移动、移动、评估结果playerResult、,
评估结果对手结果)
{
最佳移动=移动;
if(playerResult.Status!=EvaluateResult.evaluateTestatus.None)
{
bestMove.EvaluateResult=playerResult.Status;
}
else if(opponentResult.Status!=EvaluateResult.EvaluateStatus.None)
{
bestMove.EvaluateResult=对手结果状态;
}
其他的
{
bestMove.EvaluateResult=EvaluateResult.evaluateTestatus.None;
}
返回最佳移动;
}
程序找到移动,但它并不总是最好的。尤其是当对手有2次获胜机会时,他看不到任何动作。而且当算法有制胜招式时,他会首先阻挡对手。例如:

XO- XO- --- XO- XO- --- 若计算机是O,他会先阻止X,但它不应该


你能告诉我这个功能有什么可以改进的吗?也许有一个我看不到的错误:(评估函数工作得很好,我编写了单元测试来测试它。

您可能想看看针对这类问题的典型游戏算法:特别是negamax和alpha/beta修剪。您似乎对OOP有点过火。请尝试简化代码,使其更易于理解。这非常冗长……就像Jar一样ed说OOP可能会碍事。我的意思是,我试图帮助调试你的代码,但是有太多明显的冗余。。。