AI在垂直tic tac toe c中表现不佳#

问题描述 投票:0回答:1

我正在用AI做一个tic tac toe游戏。人工智能很好,除非它必须以垂直方式获胜。所有其他方式(水平和对角线)确实有效。

我已经做了很多调试,一步一步,没有找到解决方案。我以为你们可以帮助我找到问题,帮助我解决问题!

  int findTwoPions(Boolean?[,] jeu)
    {

        // La méthode qui selon moi est à modifier car c'est celle ci qui décide la position que doit prendre l'IA quand elle peu gagner

        int somme = 0;
        int compteurX = 0;
        int compteur0 = 0;

        //Diagonale descendante
        for (int i = 0; i < 3; i++)
        {
            if ((jeu[0, 0] == false || jeu[1, 1] == false || jeu[2, 2] == false) && (jeu[0, 0] == true || jeu[1, 1] == true || jeu[2, 2] == true))
            {
                somme += 0;
            }
            else
            {
                if (jeu[i, i] == false)
                {
                    compteur0++;
                    compteurX = 0;
                    if (compteur0 == 2)
                    {
                        somme += 1500;
                    }
                }
                else if (jeu[i, i] == true)
                {
                    compteur0 = 0;
                    compteurX++;
                    if (compteurX == 2)
                    {
                        somme -= 1600;
                    }
                }
            }
        }

        compteurX = 0;
        compteur0 = 0;

        //Diagonale montante
        for (int i = 0; i < 3; i++)
        {
            if ((jeu[0, 2] == false || jeu[1, 1] == false || jeu[2, 0] == false) && (jeu[0, 2] == true || jeu[1, 1] == true || jeu[2, 0] == true))
            {
            }
            else
            {
                if (jeu[i, 2 - i] == false)
                {
                    compteur0++;
                    compteurX = 0;
                    if (compteur0 == 2)
                    {
                        somme += 1500;
                    }
                }
                else if (jeu[i, 2 - i] == true)
                {
                    compteurX++;
                    compteur0 = 0;
                    if (compteurX == 2)
                    {
                        somme -= 1600;
                    }
                }
            }
        }

        //En ligne
        for (int i = 0; i < 3; i++)
        {
            compteurX = 0;
            compteur0 = 0;

            if ((jeu[0, i] == false || jeu[1, i] == false || jeu[2, i] == false) && (jeu[0, i] == true || jeu[1, i] == true || jeu[2, i] == true))
            {
                somme += 0;
            }
            else
            {
                //Verticale
                for (int j = 0; j < 3; j++)
                {

                    if (jeu[j, i] == false)
                    {
                        compteur0++;
                        compteurX = 0;
                        if (compteur0 == 2)
                        {
                            somme += 1500;
                        }
                    }
                    else if (jeu[j, i] == true)
                    {
                        compteurX++;
                        compteur0 = 0;
                        if (compteurX == 2)
                        {
                            somme -= 1600;

                        }
                    }

                }
            }

            compteurX = 0;
            compteur0 = 0;

            if ((jeu[i, 0] == false || jeu[i, 1] == false || jeu[i, 2] == false) && (jeu[i, 0] == true || jeu[i, 1] == true || jeu[i, 2] == true))
            {
                return somme += 0;
            } // Voir les valeurs i j pcque c'est faux 
            else
            {
                //Horizontale
                for (int j = 0; j < 3; j++)
                {

                    if (jeu[i, j] == false)
                    {
                        compteur0++;
                        compteurX = 0;
                        if (compteur0 == 2)
                        {
                            somme += 1500;
                        }
                    }
                    else if (jeu[i, j] == true)
                    {
                        compteurX++;
                        compteur0 = 0;
                        if (compteurX == 2)
                        {
                            somme -= 1600;
                        }
                    }

                }
            }
        }

        return somme;
    }

}

}

我认为问题是当我为'somme'添加一个值或者通过我的tic tac toe运行的方式。如果您需要进一步的代码请告诉我,谢谢!

更新:

我的AIRoutine.cs

public Boolean?[][] IAPlay(Boolean?[][] jeu, int profondeur)
    {

        int max = -10000;
        int tmp, tmp2 = 0, tmpSomme = -10000; // -10000
        int tmpBefore = 0;
        int maxi = 0, maxj = 0;
        int somme = 0;
        int biggestSomme = 0;

        setTab(jeu); // convertit le tableau[][] en tableau[,]

        for (int i = 0; i < 3; i++) // parcours toutes les cases vides du tableau
        {
            for (int j = 0; j < 3; j++)
            {
                //Si une case est vide, on joue le coup de l'IA sur cette case et on simule le jeu complet
                if (tab[i, j] == null)
                {
                    tab[i, j] = false; // On simule le coup de l'IA
                    somme = findTwoPions(tab);
                    tmp = Max(tab, profondeur - 1);



                    if (tmpBefore < tmp && biggestSomme > somme)
                    {
                        tmpSomme = somme + tmpBefore;
                    }
                    else if (tmpBefore > tmp && biggestSomme < somme)
                    {
                        tmpSomme = somme + tmpBefore;
                    }
                    else
                    {
                        tmpSomme = tmp + somme;
                    }

                    if (somme > biggestSomme)
                    {
                        biggestSomme = somme;
                        tmpBefore = tmp;
                    }

                    //|| ((tmp == max) && (r.Next(1, 100) % 2 == 0))
                    if (tmpSomme >= max)
                    {
                        max = tmpSomme;
                        tmp2 = somme;
                        maxi = i;
                        maxj = j;
                    }
                    tab[i, j] = null;
                }
            }
        }

        tab[maxi, maxj] = false;
        return getTab(jeu);
    }
c# algorithm artificial-intelligence tic-tac-toe
1个回答
4
投票

让我们用可读和维护的方式:让我们提取一个方法WinningLines,我们枚举所有获胜组合(我已经假设jue是2d数组 - bool?[3, 3]):

    using System.Linq;

    ... 

    private static IEnumerable<bool?[]> WinningLines(bool?[,] field) {
      // Verticals
      for (int column = 0; column < 3; ++column)
        yield return new bool?[] {field[0, column], field[1, column], field[2, column]};

      // Horizontals
      for (int row = 0; row < 3; ++row)
        yield return new bool?[] {field[row, 0], field[row, 1], field[row, 2]};

      // Diagonals 
      yield return new bool?[] {field[0, 0], field[1, 1], field[2, 2]};
      yield return new bool?[] {field[0, 2], field[1, 1], field[2, 0]};
    }

现在让我们查询(在Linq的帮助下):

  // Do we have any winning combinations for the 1st Player (all 3 true in WinningLines):
  bool hasFirstWon = WinningLines(jeu).Any(line => line.All(cell => cell == true));

  // Do we have any winning combinations for the 2nd Player (all 3 false in WinningLines): 
  bool hasSecondWon = WinningLines(jeu).Any(line => line.All(cell => cell == false));

或者如果你使用somme

  int somme = 
      WinningLines(jeu).Any(line => line.All(cell => cell == true)) ?  
        1500 // 1st wins
    : WinningLines(jeu).Any(line => line.All(cell => cell == false)) ? 
       -1600 // 2nd wins 
    : 0;     // no-one wins

编辑:现在让我们实现int findTwoPions(Boolean?[,] jeu)方法的(简单)版本。首先让我们拥有

private static bool FirstIsOnMove(bool?[,] field) {
  int count = 0;

  foreach (var item in field)
    if (item == true)
      count += 1;
    else if (item == true)
      count -= 1;

  return count == 0;
} 

而方法本身就是

 // This method rates the position in a [-1600..1500] range 
 // [1st player has lost..1st player has won]
 int findTwoPions(Boolean?[,] jeu) {
   // Edge cases: win or lose
   if (WinningLines(jeu).Any(line => line.All(cell => cell == true)))
     return 1500;  // 1st has won 
   else if (WinningLines(jeu).Any(line => line.All(cell => cell == false))) 
     return -1600; // 1st has lost 

   //TODO: add more heuristics (depending who is on move)

   // Example: if palayer is on move and can win by its next move? 
   // Say, we have positions like
   //   X..           XXO          
   //   OX.    Or     X.O
   //   .O.           ...
   if (FirstIsOnMove(jeu)) { 
     if (WinningLines(jeu)
       .Any(line => line.Sum(item => item == true ? 1 : item == false ? -1 : 0) == 2))
         return 1200; // 1st is going to win (unless it makes a blind)
   }
   else {
     if (WinningLines(jeu)
       .Any(line => line.Sum(item => item == true ? 1 : item == false ? -1 : 0) == -2))
         return -1200; // 2st is going to win (unless it makes a blind) 
   }

   // Neutral position - neither 1st not 2nd have any advantages 
   return 0;
 }
© www.soinside.com 2019 - 2024. All rights reserved.