/// <summary> /// AlphaBeta Pruning algorithm adapted from genric AlphaBeta Pseudo-code: https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning /// </summary> /// <param name="game">Current game object (containing up-to-date board simulation)</param> /// <param name="alpha">Alpha value</param> /// <param name="beta">Beta value</param> /// <param name="maximizingPlayer">Maximizing player (True when it is THIS AI's turn in the simulation)</param> /// <returns></returns> private float AlphaBetaPrune(Game game, float alpha, float beta, bool maximizingPlayer) { // Check the current game state and if it is completed, return the (maximizing player's) value associated with the game outcome GameState state = game.GetGameState(); if (state.IsCompleted) { if (state.Winner == this) { return 1f + (1f - state.TotalMoves / 9f); } else if (state.Winner == null) { return 0; } else { return -1f - (1f - state.TotalMoves / 9f); ; } } // If the game was not completed by the previous move, continue recursing through possible moves float value; if (maximizingPlayer) { value = float.MinValue; foreach (Square square in game.Board.Squares) { if (square.Owner == null) { square.Owner = this; value = Math.Max(value, AlphaBetaPrune(game, alpha, beta, false)); alpha = Math.Max(alpha, value); square.Owner = null; if (beta <= alpha) { break; } } } } else { value = float.MaxValue; foreach (Square square in game.Board.Squares) { if (square.Owner == null) { square.Owner = _playerOpponent; value = Math.Min(value, AlphaBetaPrune(game, alpha, beta, true)); beta = Math.Min(beta, value); square.Owner = null; if (beta <= alpha) { break; } } } } return value; }