Пример #1
0
        private static short ScoreNode(GameTree leaf)
        {
            short score = 0;

            switch (leaf.Data.State)
            {
            case GameState.Xwin:
                score = 10000;
                break;

            case GameState.Owin:
                score = -10000;
                break;

            case GameState.Draw:
                score = 0;
                break;

            case GameState.Open:

                var xWins = (short)(CountWins(Player.X, leaf.Data) * 10);
                var oWins = (short)(CountWins(Player.O, leaf.Data) * 10);
                score = (short)(xWins - oWins);

                score = leaf.Data.GameBoard.Aggregate(score, (current, board) => (short)(current + CalculateScore(board)));
                break;
            }
            leaf.Score = score;
            return(score);
        }
Пример #2
0
        private UltimateTicTacToeMove MinMax()
        {
            var minMax = AlphaBeta(_gameTree, short.MinValue + 10, short.MaxValue - 10, Player == Player.X);

            Debug.WriteLine($"MinMax:{minMax}, Low:{_gameTree.GetLeafNodes().Min(node => node.Score)}, High:{_gameTree.GetLeafNodes().Max(node => node.Score)}");
            Debug.WriteLine($"I'm looking ahead {_gameTree.GetTreeDepth()} moves!");

            var possibleMoves = _gameTree.Children.Where(child => child.Score == minMax);

            // ReSharper disable PossibleMultipleEnumeration
            var index = new Random().Next(0, possibleMoves.Count());

            _gameTree = possibleMoves.ElementAt(index); //Update the game state to the move chosen
            return(possibleMoves.ElementAt(index).Data.LastMove);
            // ReSharper restore PossibleMultipleEnumeration
        }
Пример #3
0
        public UltimateTicTacToeMove TakeTurn(UltimateTicTacToeBoard ticTacToeBoard)
        {
            _taunt("Planning My Move...");
            GameTree currentTree = _gameTree?.GetNode(ticTacToeBoard);

            Debug.WriteLine($"There were {_gameTree?.GetNodeCount()} nodes in the tree prior to this move.");

            //Taunt the player if they played well!
            if (_gameTree?.Children != null && _gameTree.Children.Count != 0)
            {
                var lowScore         = _gameTree.Children.Min(node => node.Score);
                var highScore        = _gameTree.Children.Max(node => node.Score);
                var bestMove         = Player == Player.O ? highScore : lowScore;
                var worstMove        = Player == Player.X ? highScore : lowScore;
                var bestPlayedMoves  = _gameTree.Children.Where(child => child.Score == bestMove);
                var worstPlayedMoves = _gameTree.Children.Where(child => child.Score == worstMove);
                var playedMoves      = bestPlayedMoves as IList <GameTree> ?? bestPlayedMoves.ToList();
                if (playedMoves.Contains(currentTree) && playedMoves.Count == 1 && Math.Abs(bestMove - worstMove) > 250)
                {
                    _taunt("Nice Move Kiddums!");
                    Thread.Sleep(timeout: new TimeSpan(0, 0, 5));
                }
                else if (worstPlayedMoves.Contains(currentTree) && Math.Abs(bestMove - worstMove) > 250)
                {
                    _taunt("What are you thinking?");
                    Thread.Sleep(timeout: new TimeSpan(0, 0, 5));
                }
            }

            _gameTree = currentTree ?? new GameTree(data: ticTacToeBoard.Clone());
            Debug.WriteLine($"Tree Triming reduced it to {_gameTree.GetNodeCount()} nodes.");
            Debug.WriteLine($"Memory Used {GC.GetTotalMemory(false)}");
            GC.Collect();
            GC.WaitForPendingFinalizers();
            Debug.WriteLine($"Memory Used {GC.GetTotalMemory(false)}");
            PopulateTree();
            Debug.WriteLine($"Memory Used {GC.GetTotalMemory(false)}");
            Debug.WriteLine($"Tree population increased it to {_gameTree.GetNodeCount()} nodes at a depth of {_gameTree.GetTreeDepth()}.");
            var move = MinMax();

            return(move);
        }
Пример #4
0
        private static short AlphaBeta(GameTree node, short alpha, short beta, bool maximizingPlayer)
        {
            if (node.Children.Count == 0)
            {
                return(ScoreNode(node));
            }

            if (maximizingPlayer)
            {
                var value = short.MinValue;
                foreach (var child in node.Children)
                {
                    value = Math.Max(value, AlphaBeta(child, alpha, beta, false));
                    alpha = Math.Max(alpha, value);
                    if (beta < alpha)
                    {
                        break;
                    }
                }
                node.Score = value;
                return(value);
            }
            else
            {
                var value = short.MaxValue;
                foreach (var child in node.Children)
                {
                    value = Math.Min(value, AlphaBeta(child, alpha, beta, true));
                    beta  = Math.Min(beta, value);
                    if (beta < alpha)
                    {
                        break;
                    }
                }
                node.Score = value;
                return(value);
            }
        }