private int minimaxScoreWithCache(char[,] board, char currentSymbol) { Tuple <bool, char> result = BoardUtils.ComputeGameResult(board, Engine.EMPTY_CHAR); if (result.Item1) { // win if (result.Item2 == Symbol) { return(10); } // loose else if (result.Item2 != Engine.EMPTY_CHAR) { return(-10); } // draw else { return(0); } } List <int> scores = new List <int>(); foreach (var move in BoardUtils.GetAllLegalMoves(board, Engine.EMPTY_CHAR)) { char[,] workingBoard = (char[, ])board.Clone(); workingBoard[move.Item1, move.Item2] = currentSymbol; string key = GetCustomHash(workingBoard); if (!cache.ContainsKey(key)) { IPlayer opponent = PlayerManager.GetInstance().GetOpponent(currentSymbol); int score = minimaxScoreWithCache(workingBoard, opponent.Symbol); cache.Add(key, score); } scores.Add(cache[key]); } // if current player is our IA, we try to maximize the score, // else minimize it if (currentSymbol == Symbol) { return(scores.Max()); } else { return(scores.Min()); } }
internal override Tuple <int, int> AskNextMove(char[,] board) { Tuple <int, int> bestMove = null; int bestScore = int.MinValue; foreach (var move in BoardUtils.GetAllLegalMoves(board, Engine.EMPTY_CHAR)) { char[,] workingBoard = (char[, ])board.Clone(); workingBoard[move.Item1, move.Item2] = Symbol; IPlayer opponent = PlayerManager.GetInstance().GetOpponent(Symbol); int currentScore = minimaxScoreWithCache(workingBoard, opponent.Symbol); if (currentScore > bestScore) { bestScore = currentScore; bestMove = new Tuple <int, int>(move.Item1, move.Item2); } } return(bestMove); }