Преглед на файлове

Update 'Connect4Minimax.cs'

Всеволод Левитан преди 4 месеца
родител
ревизия
bfa8d743aa
променени са 1 файла, в които са добавени 20 реда и са изтрити 55 реда
  1. 20 55
      Connect4Minimax.cs

+ 20 - 55
Connect4Minimax.cs

@@ -33,61 +33,11 @@ public class Connect4Minimax
         return 0;
     }
 
-    private readonly int[][] directions = [
-        [ 0, 1 ],
-        [ 1, 0 ],
-        [ 1, 1 ],
-        [ -1, 1 ]
-    ];
-
-    // public int CountSequences(GameBoard board)
-    // {
-    //     int score = 0;
-
-    //     for (int row = 0; row < board.dimensions.Rows; row++)
-    //     {
-    //         for (int col = 0; col < board.dimensions.Columns; col++)
-    //         {
-    //             for (int dir = 0; dir < 4; dir++)
-    //             {
-    //                 int rowDir = directions[dir][0];
-    //                 int colDir = directions[dir][1];
-
-    //                 int endRow = row + (3 * rowDir);
-    //                 int endCol = col + (3 * colDir);
-
-    //                 if (endRow >= 0 && endRow < board.dimensions.Rows &&
-    //                     endCol >= 0 && endCol < board.dimensions.Columns)
-    //                 {
-    //                     int aiCount = 0;
-    //                     int humanCount = 0;
-
-    //                     for (int k = 0; k < 4; k++)
-    //                     {
-    //                         int currentRow = row + (k * rowDir);
-    //                         int currentCol = col + (k * colDir);
-
-    //                         if (board.cells[currentCol][currentRow] == Player.Computer)
-    //                             aiCount++;
-    //                         else if (board.cells[currentCol][currentRow] != Player.None)
-    //                             humanCount++;
-    //                     }
-
-    //                     score += EvaluateScoreDiff(humanCount, aiCount);
-    //                 }
-    //             }
-    //         }
-    //     }
-
-    //     return score;
-    // }
-
-
-    // БЫСТРЕЕ ПРИ ВЫСОКОЙ ЧАСТОТЕ ПРОЦА
-    public int CountSequences(GameBoard board)
+    public static int CountSequences(GameBoard board)
     {
         int score = 0;
 
+        // Считаем по горизонтали
         for (int col = 0; col < board.dimensions.Columns; col++)
         {
             for (int row = 0; row < board.dimensions.Rows - 3; row++)
@@ -105,6 +55,7 @@ public class Connect4Minimax
             }
         }
 
+        // По вертикали
         for (int col = 0; col < board.dimensions.Columns - 3; col++)
         {
             for (int row = 0; row < board.dimensions.Rows; row++)
@@ -122,6 +73,7 @@ public class Connect4Minimax
             }
         }
 
+        // По диагонали
         for (int col = 0; col < board.dimensions.Columns - 3; col++)
         {
             for (int row = 0; row < board.dimensions.Rows - 3; row++)
@@ -139,6 +91,7 @@ public class Connect4Minimax
             }
         }
 
+        // По второй диагонали
         for (int col = 3; col < board.dimensions.Columns; col++)
         {
             for (int row = 0; row < board.dimensions.Rows - 3; row++)
@@ -159,36 +112,47 @@ public class Connect4Minimax
         return score;
     }
 
-    private int EvaluateMinMax(GameBoard board, int depth, bool maxPlayer = false, int alpha = int.MinValue, int beta = int.MaxValue)
+    private static int EvaluateMinMax(GameBoard board, int depth, bool maxPlayer = false, int alpha = int.MinValue, int beta = int.MaxValue)
     {
         var currentWinner = board.GetWinner();
 
+        // Выходим, если выиграли или проиграли
         if (currentWinner == Player.Computer) return (depth + 1) * 100_000;
         else if (currentWinner == Player.Human) return -(depth + 1) * 100_000;
+
+        // Выходим, если больше некуда ходить
         if (!board.HasEmptyColumns()) return 0;
 
+        // Последняя итерация
         if (depth == 0) return CountSequences(board);
 
         int best = maxPlayer ? int.MinValue : int.MaxValue;
 
+        // Считаем все возможные ходы
         for (int i = 0; i < board.dimensions.Columns; i++)
         {
+            // Если невозможно сделать ход
             if (!board.PlaceCoin(maxPlayer ? Player.Computer : Player.Human, i)) continue;
 
+            // Итерация оппонента
             int x = EvaluateMinMax(board, depth - 1, !maxPlayer, alpha, beta);
+            // Выбираем лучший (или худший) исход
             best = maxPlayer ? int.Max(best, x) : int.Min(best, x);
+            // Отменяем сделанный ход
             board.RemoveFromTop(i);
 
+            // Обновляем альфа-бета значения
             if (maxPlayer) alpha = int.Max(alpha, best);
             else beta = int.Min(beta, best);
 
-            if (beta <= alpha) i++;
+            // if (beta <= alpha) i++;
+            if (beta <= alpha) return best;
         }
 
         return best;
     }
 
-    public int GetBestMove(GameBoard board, int depth)
+    public static int GetBestMove(GameBoard board, int depth)
     {
         List<(int Column, int Score)> moves = [];
         // Parallel.For(0, board.dimensions.Columns, new() { MaxDegreeOfParallelism = 1 }, i =>
@@ -199,6 +163,7 @@ public class Connect4Minimax
             moves.Add((i, EvaluateMinMax(newBoard, depth)));
         });
 
+        // Находим счет с максимальным счетом, с приоритетом на центральные колонки
         return moves.OrderByDescending(m => m.Score).ThenBy(m => int.Abs(m.Column - (board.dimensions.Columns / 2))).First().Column;
     }
 }