public GameResults PlayGame(int games)
        {
            GameResults results           = new GameResults(Player1.Name, Player2.Name);
            Player      playerToMoveFirst = Player1;

            for (int index = 0; index < games; index++)
            {
                NaughtsAndCrossesGame game = new NaughtsAndCrossesGame();
                Player     currentPlayer   = playerToMoveFirst;
                GameMove   nextMove        = currentPlayer.MakeMove(game.GameState);
                MoveResult moveResult      = game.ApplyMove(nextMove);
                while (moveResult == MoveResult.Success)
                {
                    // Switch player
                    currentPlayer = currentPlayer == Player1 ? Player2 : Player1;
                    nextMove      = currentPlayer.MakeMove(game.GameState);
                    moveResult    = game.ApplyMove(nextMove);
                }
                if (moveResult == MoveResult.Win)
                {
                    if (currentPlayer == Player1)
                    {
                        results.PlayerScore1++;
                    }
                    else
                    {
                        results.PlayerScore2++;
                    }
                }

                if (moveResult == MoveResult.Draw)
                {
                    results.Draw++;
                }
                if (moveResult == MoveResult.Illegal)
                {
                    throw new Exception($"An illegal move was made by {currentPlayer.Name}");
                }

                if (AlternateFirstMove)
                {
                    playerToMoveFirst = playerToMoveFirst == Player1 ? Player2 : Player1;
                }
            }
            return(results);
        }
        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);
        }
        public MoveResult ApplyMove(GameMove move)
        {
            if (move.Location >= GameState.GameBoard.Length || GameState.GameBoard[move.Location] != GameSymbol.Blank)
            {
                return(MoveResult.Illegal);
            }

            GameState.GameBoard[move.Location] = move.GameSymbol;
            GameState.SwitchSymbol();

            GameCompletion gameCompletion = GetGameCompletion();

            if (gameCompletion == GameCompletion.Won)
            {
                return(MoveResult.Win);
            }
            if (gameCompletion == GameCompletion.Draw)
            {
                return(MoveResult.Draw);
            }
            return(MoveResult.Success);
        }
 public void ApplyMove(GameMove move)
 {
     GameBoard[move.Location] = move.GameSymbol;
     SwitchSymbol();
 }
 public UtilityGameMove(int location, GameSymbol gameSymbol, int utility)
 {
     Utility  = utility;
     GameMove = new GameMove(location, gameSymbol);
 }