private UtilityGameMove GetMinUtilityMove(UtilityGameMove originalMove, UtilityGameMove nextMove)
 {
     if (originalMove.Utility <= nextMove.Utility)
     {
         return(originalMove);
     }
     return(nextMove);
 }
        private UtilityGameMove MinValue(GameState gs, int alpha, int beta, GameMove lastMove = null, int depth = 0)
        {
            //var lastMoveValue = lastMove != null ? $"{lastMove.Location}, ${((lastMove.GameSymbol == GameSymbol.Cross) ? "Cross" : "Naught")}" : "null";
            //Console.WriteLine($"Min value is called. Alpha: {alpha}, Beta: {beta}, lastMove: {lastMoveValue}");

            var terminalState = PlayerUtilities.GetTerminalState(gs, PlayerSymbol);

            if (terminalState != PlayerUtilities.TerminalState.Incomplete)
            {
                if (lastMove == null)
                {
                    throw new Exception("Cannot find best move, in terminal state but with no last move");
                }
                var utilityValue = GetUtilityOfTerminalState(terminalState);
                return(new UtilityGameMove(lastMove.Location, lastMove.GameSymbol, utilityValue));
            }

            var moves = gs.GetMoves();
            var v     = new UtilityGameMove(moves.First().Location, moves.First().GameSymbol, Int32.MaxValue);

            foreach (var move in moves)
            {
                var copiedGameState = gs.Clone() as GameState;
                copiedGameState.ApplyMove(move);
                var u = MaxValue(copiedGameState, alpha, beta, move, ++depth);
                v    = GetMinUtilityMove(v, u);
                beta = Math.Min(beta, v.Utility);
                if (alpha >= beta)
                {
                    if (lastMove != null)
                    {
                        return(new UtilityGameMove(lastMove.Location, lastMove.GameSymbol, v.Utility));
                    }
                    return(v);
                }
            }
            if (lastMove != null)
            {
                return(new UtilityGameMove(lastMove.Location, lastMove.GameSymbol, v.Utility));
            }
            return(v);
        }