Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Tic-Tac-Toe的Minimax算法_C#_Algorithm_Recursion_Minimax - Fatal编程技术网

C# Tic-Tac-Toe的Minimax算法

C# Tic-Tac-Toe的Minimax算法,c#,algorithm,recursion,minimax,C#,Algorithm,Recursion,Minimax,我试图用Jason Fox()实现minimax算法,但它不起作用,计算机只是随机移动。下面是我编写的Game类(我必须创建一个cloneGrid函数,因为数组被作为引用传递,有没有更好的方法来克服这个问题?) 类游戏 { 公共枚举块{Empty=0,X=1,O=2}; 静态整数[,]winConditions=新整数[8,3] { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }, { 0, 3, 6 }, { 1, 4, 7 }, { 2, 5, 8 }, { 0

我试图用Jason Fox()实现minimax算法,但它不起作用,计算机只是随机移动。下面是我编写的
Game
类(我必须创建一个
cloneGrid
函数,因为数组被作为引用传递,有没有更好的方法来克服这个问题?)

类游戏
{ 
公共枚举块{Empty=0,X=1,O=2};
静态整数[,]winConditions=新整数[8,3]
{
{ 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 },
{ 0, 3, 6 }, { 1, 4, 7 }, { 2, 5, 8 },
{ 0, 4, 8 }, { 2, 4, 6 }
};
公共件[]网格=新件[9];
公共件CurrentTurn=件.X;
int-Choice=0;
公用件计算机;
公共棋手;
公共游戏()
{
CurrentTurn=件X;
Player=Piece.X;
}
公共无效重置()
{
CurrentTurn=件X;
SetPlayer(件号X);
网格=新件[9];
}
公共棋手(棋手)
{
这个。玩家=玩家;
这个。计算机=开关(播放器);
}
公共void MakeMove(int Move)
{
如果(当前回合==玩家)
{
Grid=makeGridMove(Grid、CurrentTurn、Move);
CurrentTurn=开关件(CurrentTurn);
}
else if(CurrentTurn==计算机)
{
极小极大值(cloneGrid(网格),CurrentTurn);
Grid=makeGridMove(Grid、CurrentTurn、Choice);
CurrentTurn=开关件(CurrentTurn);
Console.WriteLine(Choice.ToString());
}
}
int minimax(工件[]输入网格,工件播放器)
{
工件[]网格=克隆ID(InputGrid);
如果(检查分数(网格,玩家)!=0)
返回检查分数(网格、玩家);
else if(checkGameEnd(Grid))返回0;
列表分数=新列表();
列表移动=新列表();
对于(int i=0;i<9;i++)
{
if(网格[i]==件空)
{
添加(minimax(makeGridMove(Grid,Player,i),开关(Player));
加入(i);
}
}
如果(播放器==计算机)
{
int MaxScoreIndex=scores.IndexOf(scores.Max());
选择=移动[MaxScoreIndex];
返回分数。Max();
}
其他的
{
int MinScoreIndex=scores.IndexOf(scores.Min());
选择=移动[MinScoreIndex];
返回分数.Min();
}
}
静态整数校验分数(计件[]网格,计件玩家)
{
if(checkGameWin(网格,玩家))返回10;
否则如果(选中GameWin(网格、开关(玩家)),返回-10;
否则返回0;
}
静态bool checkGameWin(棋子[]网格,棋子玩家)
{
对于(int i=0;i<8;i++)
{
如果
(
网格[winConditions[i,0]==播放器&&
网格[winConditions[i,1]==玩家&&
网格[winConditions[i,2]==玩家
)
{
返回true;
}
}
返回false;
}
静态bool CHECKGAMEND(件号[]网格)
{
如果(p==Piece.Empty)返回false,则返回foreach(网格中的p块);
返回true;
}
静态单件开关(单件)
{
如果(件==件.X)返回件.O;
否则返回件.X;
}
静态工件[]克隆ID(工件[]网格)
{
工件[]克隆=新工件[9];
对于(inti=0;i<9;i++)克隆[i]=Grid[i];
返回克隆;
}
静态工件[]makeGridMove(工件[]网格,工件移动,int位置)
{
工件[]新网格=克隆ID(网格);
newGrid[位置]=移动;
返回新网格;
}
}

这是愚蠢的,但错误是我在检查当前玩家的分数,但应该只检查AI的分数。所以解决方法是使用:checkScore(网格,计算机),而不是checkScore(网格,播放器)

这很好,非常感谢。我不得不对代码进行一些修改,使算法能够正确地为我工作。所以我在这里发布我所做的

    static currentPlayer;

    static float minimax(int[,] board, bool isMinimizing)
    {

        int[,] copy = board.Clone() as int[,];

        //if I won - > return 10
        if (isWinner(currentPlayer, copy))
            return 10f;
       // if opponent won - > return -10
        if (isWinner(OtherPlayer(currentPlayer), copy))
            return -10f;
        // if no moves left - > return 0
        if (isFull(copy))
            return 0;

        List<float> scores = new List<float>();
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                if (copy[i, j] == -1)
                {
                    copy[i, j] = isMinimizing? currentPlayer : OtherPlayer(currentPlayer);
                    float score = minimax(copy, !isMinimizing);
                    copy[i, j] = -1;
                    scores.Add(score);
                }
            }
        }
        if (isMinimizing)
            return scores.Max();

        return scores.Min();

    }
staticcurrentplayer;
静态浮点极小极大值(int[,]板,布尔最小)
{
int[,]copy=board.Clone()为int[,];
//如果我赢了->返回10
如果(isWinner(currentPlayer,副本))
返回10f;
//如果对手赢了->返回-10
如果(isWinner(其他玩家(当前玩家),复制))
返回-10f;
//如果没有向左移动->返回0
如果(完整(副本))
返回0;
列表分数=新列表();
对于(int i=0;i<3;i++)
{
对于(int j=0;j<3;j++)
{
如果(复制[i,j]=-1)
{
复制[i,j]=正在最小化?当前播放器:其他播放器(当前播放器);
浮动分数=最小最大值(复制,!Isminimize);
复制[i,j]=-1;
分数。添加(分数);
}
}
}
如果(正在最小化)
返回分数。Max();
返回分数.Min();
}

可能重复@JuanM.Elosegui-不,这根本不是重复。同样的主题。别误会,这是一个有趣的问题,但基本上我们要么在头脑中玩调试器,要么复制并粘贴调试器,然后在机器上使用调试器——所以在我们这么做之前:您是否已经使用调试器完成了代码?如果是:问题出在哪里?@talhaLodhi-你有一个选择:学习使用调试器还是学习编写单元测试。@Carsten对使用调试器不太熟悉,但我尝试使用console.writeline添加调试代码来检查分数值,虽然这是一个递归函数,但速度太慢,我注意到大部分分数都是-10,只有很少的零,没有10分,还有,你知道有关于VS调试和单元测试的好视频教程吗?次要性能点:似乎是
    static currentPlayer;

    static float minimax(int[,] board, bool isMinimizing)
    {

        int[,] copy = board.Clone() as int[,];

        //if I won - > return 10
        if (isWinner(currentPlayer, copy))
            return 10f;
       // if opponent won - > return -10
        if (isWinner(OtherPlayer(currentPlayer), copy))
            return -10f;
        // if no moves left - > return 0
        if (isFull(copy))
            return 0;

        List<float> scores = new List<float>();
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                if (copy[i, j] == -1)
                {
                    copy[i, j] = isMinimizing? currentPlayer : OtherPlayer(currentPlayer);
                    float score = minimax(copy, !isMinimizing);
                    copy[i, j] = -1;
                    scores.Add(score);
                }
            }
        }
        if (isMinimizing)
            return scores.Max();

        return scores.Min();

    }