| 
					
				 | 
			
			
				@@ -3,6 +3,9 @@ using MinMaxAB; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 namespace Connect4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/// Доска для игры в 4 в ряд 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 public class GameBoard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public Player[][] cells; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -23,6 +26,12 @@ public class GameBoard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private bool cacheInvalidated = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private Player winnerCache = Player.None; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Закинуть монетку сверху 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <param name="player">Игрок, закинувший монетку</param> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <param name="column">Столбец, в который закинуть монетку</param> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <returns>Получилось ли поместить монетку</returns> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public bool PlaceCoin(Player player, int column) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         int row = 0; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -38,6 +47,11 @@ public class GameBoard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Убрать верхнюю монетку 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <param name="column">Столбец, из которого убрать монетку</param> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <returns>Удалось ли убрать монетку</returns> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public bool RemoveFromTop(int column) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         int row = 0; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -53,6 +67,10 @@ public class GameBoard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Найти победители 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <returns>Игрок-победитель</returns> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public Player? GetWinner() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!cacheInvalidated) return winnerCache; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -66,26 +84,32 @@ public class GameBoard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (cells[i][j] == Player.None) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                bool h = i + 3 < dimensions.Columns; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                bool v = j + 3 < dimensions.Rows; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Горизонталь 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                bool horizontal = i + 3 < dimensions.Columns; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (!h && !v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Вертикаль 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                bool vertical = j + 3 < dimensions.Rows; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!horizontal && !vertical) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                bool d = h && v; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                bool bd = v && i - 3 >= 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Диагональ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                bool diagonal = horizontal && vertical; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Вторая диагональ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                bool reverseDiagonal = vertical && i - 3 >= 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Проходим по всем возможным длинам последовательности 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 for (int k = 1; k < 4; k++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    h = h && cells[i][j] == cells[i + k][j]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    v = v && cells[i][j] == cells[i][j + k]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    d = d && cells[i][j] == cells[i + k][j + k]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    bd = bd && cells[i][j] == cells[i - k][j + k]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (!h && !v && !d && !bd) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    horizontal = horizontal && cells[i][j] == cells[i + k][j]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    vertical = vertical && cells[i][j] == cells[i][j + k]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    diagonal = diagonal && cells[i][j] == cells[i + k][j + k]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    reverseDiagonal = reverseDiagonal && cells[i][j] == cells[i - k][j + k]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (!horizontal && !vertical && !diagonal && !reverseDiagonal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (h || v || d || bd) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (horizontal || vertical || diagonal || reverseDiagonal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     winnerCache = cells[i][j]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     return cells[i][j]; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -97,6 +121,10 @@ public class GameBoard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return Player.None; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Проверить, есть ли пустые столбцы 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <returns>true если есть пустые столбцы</returns> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public bool HasEmptyColumns() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         for (int x = 0; x < dimensions.Columns; x++) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -107,6 +135,11 @@ public class GameBoard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Найти символ, обозначающий игрока 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <param name="player">Игрок</param> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <returns>Символ, обозначающий данного игрока</returns> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     protected char PlayerChar(Player player) => player switch 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         Player.Human => 'O', 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -114,6 +147,10 @@ public class GameBoard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         _ => ' ', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Сериализовать доску 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <returns>Строка, содержащая отформатированное представление доски</returns> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public override string ToString() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         string sep = $"\n{new('-', dimensions.Columns * 4)}"; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -139,6 +176,10 @@ public class GameBoard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return builder.ToString(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Скопировать доску вместе с ее содержимым 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <returns>Копия доски с таким же содержимым</returns> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public GameBoard Clone() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         var newBoard = new GameBoard(dimensions, cells.DeepCopy()); 
			 |