/// <summary> /// Find the places that will force the other player to defend, put his /// piece in a place that is not going to create a fork. /// </summary> /// <param name="playerPiece"> /// Flag for representing the diferent players. /// </param> /// <param name="result"> /// The result set for storing the values. /// </param> /// <param name="board"> /// The board to use. /// </param> /// <returns> /// True if at least 1 possible wins was found. /// </returns> public static bool GetBlockForkingMove(bool playerPiece, BrainResult result, Board board) { // can the other player create a fork? var outerResult = new BrainResult(); var fork = GetForkingMove(!playerPiece, outerResult, board, true); if (fork && outerResult.Moves.Count > 0) { var tempBoard = board.Clone(); for (int i = 0; i < board.BoardSize; i++) { if (tempBoard.BoardArray[i] == 0) { tempBoard.BoardArray[i] = playerPiece ? 1 : -1; var innerResult = new BrainResult(); if (GetWinningMove(playerPiece, 1, innerResult, tempBoard) // am I going to make two in a row && !outerResult.ContainsMove(tempBoard, i)) // this pos won't allow the user to fork { result.Moves.Add(board.GetMove(i)); return true; } tempBoard.BoardArray[i] = 0; } } } return false; }
public static bool GetEmptySideMove(BrainResult result, Board board) { for (int i = 0; i < board.BoardSize;i++) { // is empty and is not corner if (board.BoardArray[i] == 0 && board.Corners.All(c => board.GetIndex(c) != i)) { result.Moves.Add(board.GetMove(i)); return true; } } return false; }
/// <summary> /// Fork by creating an opportunity where you can win in two ways. /// </summary> /// <param name="playerPiece"> /// Flag for representing the diferent players. /// </param> /// <param name="result"> /// The result set for storing the values. /// </param> /// <param name="board"> /// The board to use. /// </param> /// <param name="getAllForks"> /// Are we to get all the forks or stop after the first one is found. /// </param> /// <returns> /// True if at least 1 possible forking move was found. /// </returns> public static bool GetForkingMove(bool playerPiece, BrainResult result, Board board, bool getAllForks = false) { var tempBoard = board.Clone(); for (int i = 0; i < board.BoardSize; i++) { if (tempBoard.BoardArray[i] == 0) { var piece = playerPiece ? 1 : -1; tempBoard.BoardArray[i] = piece; var outerResult = new BrainResult(); if (GetWinningMove(playerPiece, 2, outerResult, tempBoard)) { var m = board.GetMove(i); var innerResult = new BrainResult(); var notWin = !GetWinningMove(!playerPiece, 1, innerResult, tempBoard); // switch last to the other player var index = board.GetIndex(m.X, m.Y); tempBoard.BoardArray[index] = piece * -1; var notFork = !GetOppositionForkingMove(playerPiece, tempBoard); if (notWin && notFork) { result.Moves.Add(m); if (!getAllForks) { return true; } } // switch back tempBoard.BoardArray[index] = piece; } tempBoard.BoardArray[i] = 0; } } return getAllForks && result.Moves.Count > 0; }
/// <summary> /// Play the center. /// </summary> /// <remarks> /// If it is the first move of the game, playing on a corner gives the /// other player more opportunities to make a mistake and may therefore /// be the better choice. /// However, it makes no difference between perfect players. /// </remarks> public static bool GetCentreMove(BrainResult result, Board board) { // only if the board has odd dimensions if (board.BoardWidth % 2 != 0 && board.BoardHeight % 2 != 0) { var x = board.BoardWidth / 2; var y = board.BoardHeight / 2; var i = board.GetIndex(x, y); // and if the place is empty if (board.BoardArray[i] == 0) { result.Moves.Add(board.GetMove(i)); return true; } } return false; }