예제 #1
0
        /*
         * private void Set_Can_Win(TicTacToeDecisionNode ticTacToeDecisionNode, Player originalPlayer)
         * {
         *  if(ticTacToeDecisionNode.IsWinForOriginalPlayer)
         *  {
         *      ticTacToeDecisionNode.CanWinNode = true;
         *      return;
         *  }
         *
         *  if(ticTacToeDecisionNode.CurrentPlayer.Letter == originalPlayer.Letter)
         *  {
         *      // if I am making the next move and any children is a winning move or a "killer move" it is also a killer move
         *      foreach(var childNode in ChildNodes)
         *      {
         *          if(childNode.IsWinForOriginalPlayer || childNode.CanWinNode)
         *          {
         *              ticTacToeDecisionNode.CanWinNode = true;
         *              return;
         *          }
         *      }
         *  }
         *  else
         *  {
         *      // if the other player is the next move and all of their children are killer moves, it is a killer move
         *      // if any of them are not killer moves, then it is not a killer move
         *      foreach (var childNode in ticTacToeDecisionNode.ChildNodes)
         *      {
         *          Set_Can_Win(childNode, originalPlayer);
         *          if (childNode.CanWinNode == false)
         *          {
         *              ticTacToeDecisionNode.CanWinNode = false;
         *              return;
         *          }
         *      }
         *      ticTacToeDecisionNode.CanWinNode = true;
         *      return;
         *  }
         * }
         *
         * private void Set_Will_Lose(TicTacToeDecisionNode ticTacToeDecisionNode, Player playerForNode)
         * {
         *  // No more child nodes, check these nodes
         *  if (ticTacToeDecisionNode.GameState == GameState.Tie)
         *  {
         *      ticTacToeDecisionNode.IsLosingNodeForOriginalPlayer = false;
         *      return;
         *  }
         *  else if (ticTacToeDecisionNode.GameState == GameState.Win && ticTacToeDecisionNode.WinningPlayer.Letter == playerForNode.Letter)
         *  {
         *      ticTacToeDecisionNode.IsLosingNodeForOriginalPlayer = false;
         *      return;
         *  }
         *  else if (ticTacToeDecisionNode.GameState == GameState.Win && ticTacToeDecisionNode.WinningPlayer.Letter != playerForNode.Letter)
         *  {
         *      ticTacToeDecisionNode.IsLosingNodeForOriginalPlayer = true;
         *      return;
         *  }
         *
         *  if (ticTacToeDecisionNode.GameState != GameState.InProgress && ticTacToeDecisionNode.ChildNodes.Count > 0)
         *  {
         *      throw new InvalidOperationException("Invalid state");
         *  }
         *
         *  foreach (var childNode in ticTacToeDecisionNode.ChildNodes)
         *  {
         *      Set_Will_Lose(childNode, playerForNode);
         *
         *      if (childNode.IsLosingNodeForOriginalPlayer == false)
         *      {
         *          ticTacToeDecisionNode.IsLosingNodeForOriginalPlayer = false;
         *          return;
         *      }
         *  }
         *
         *  ticTacToeDecisionNode.IsLosingNodeForOriginalPlayer = true;
         * }
         *
         * private void Set_Will_Win_Or_Tie(TicTacToeDecisionNode ticTacToeDecisionNode, Player playerForNode)
         * {
         *  // No more child nodes, check these nodes
         *  if (ChildNodes.Count == 0)
         *  {
         *      if (ticTacToeDecisionNode.GameState == GameState.Win && ticTacToeDecisionNode.WinningPlayer.Letter == playerForNode.Letter)
         *      {
         *          ticTacToeDecisionNode.IsNonLosingNodeForOriginalPlayer = true;
         *          return;
         *      }
         *      else if (ticTacToeDecisionNode.GameState == GameState.Win && ticTacToeDecisionNode.WinningPlayer.Letter != playerForNode.Letter)
         *      {
         *          ticTacToeDecisionNode.IsNonLosingNodeForOriginalPlayer = false;
         *          return;
         *      }
         *      else if (ticTacToeDecisionNode.GameState == GameState.Tie)
         *      {
         *          ticTacToeDecisionNode.IsNonLosingNodeForOriginalPlayer = true;
         *          return;
         *      }
         *  }
         *
         *  if (ticTacToeDecisionNode.GameState != GameState.InProgress && ticTacToeDecisionNode.ChildNodes.Count > 0)
         *  {
         *      throw new InvalidOperationException("Invalid state");
         *  }
         *
         *  foreach (var childNode in ticTacToeDecisionNode.ChildNodes)
         *  {
         *      Set_Will_Win_Or_Tie(childNode, playerForNode);
         *      if (childNode.IsNonLosingNodeForOriginalPlayer == false)
         *      {
         *          ticTacToeDecisionNode.IsNonLosingNodeForOriginalPlayer = false;
         *          return;
         *      }
         *  }
         *
         *  ticTacToeDecisionNode.IsNonLosingNodeForOriginalPlayer = true;
         * }
         *
         * private static void Set_Will_Win(TicTacToeDecisionNode ticTacToeDecisionNode, Player originalPlayer)
         * {
         *  // No more child nodes, check these nodes
         *  if (ticTacToeDecisionNode.ChildNodes.Count == 0)
         *  {
         *      if (ticTacToeDecisionNode.GameState == GameState.Tie)
         *      {
         *          ticTacToeDecisionNode.IsWinForOriginalPlayer = false;
         *          return;
         *      }
         *      else if (ticTacToeDecisionNode.GameState == GameState.Win && ticTacToeDecisionNode.WinningPlayer.Letter != originalPlayer.Letter)
         *      {
         *          ticTacToeDecisionNode.IsWinForOriginalPlayer = false;
         *          return;
         *      }
         *      else if (ticTacToeDecisionNode.GameState == GameState.Win && ticTacToeDecisionNode.WinningPlayer.Letter == originalPlayer.Letter)
         *      {
         *          ticTacToeDecisionNode.IsWinForOriginalPlayer = true;
         *          return;
         *      }
         *  }
         *
         *  if (ticTacToeDecisionNode.GameState != GameState.InProgress && ticTacToeDecisionNode.ChildNodes.Count > 0)
         *  {
         *      throw new InvalidOperationException("Invalid state");
         *  }
         *
         *  foreach (var childNode in ticTacToeDecisionNode.ChildNodes)
         *  {
         *      Set_Will_Win(childNode, originalPlayer);
         *      if(childNode.IsWinForOriginalPlayer == false)
         *      {
         *          ticTacToeDecisionNode.IsWinForOriginalPlayer = false;
         *          return;
         *      }
         *  }
         *
         *  ticTacToeDecisionNode.IsWinForOriginalPlayer = true;
         * }
         */
        private void CreateChildNodes()
        {
            if (IsBoardInWinningState(ThisModel))
            {
                // don't add child nodes
                GameState = GameState.Win;
                //CurrentPlayer = null;
            }
            else if (IsBoardFull(ThisModel))
            {
                // don't add child nodes - game over with no winner
                GameState = GameState.Tie;
                //CurrentPlayer = null;
            }
            else
            {
                // there are still empty nodes
                GameState = GameState.InProgress;
                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        if (!ThisModel.Board.Squares[i, j].Played)
                        {
                            // Get the current player for the next turn
                            SquareLetter nextLetter    = SquareLetter.O;
                            Player       currentPlayer = ThisModel.Player1;
                            if (CurrentPlayerLetter == ThisModel.Player1.Letter)
                            {
                                nextLetter    = this.ThisModel.Player2.Letter;
                                currentPlayer = this.ThisModel.Player2;
                            }
                            else
                            {
                                nextLetter    = this.ThisModel.Player1.Letter;
                                currentPlayer = this.ThisModel.Player1;
                            }

                            // create a new game state for hypothetical move
                            var newGameState = new TicTacToeGameModel(ThisModel.Player1.PlayerType, ThisModel.Player2.PlayerType, ThisModel.Board, currentPlayer, i, j);

                            var childNode = new TicTacToeDecisionNode(newGameState, !IsOriginalPlayer, OriginalLetter, nextLetter, i, j);

                            ChildNodes.Add(childNode);
                        }
                    }
                }
            }
        }
예제 #2
0
        public static MoveModel GetBestMove(TicTacToeGameModel model)
        {
            //get the best move for the current player
            TicTacToeGameModel fakeGameModel = null;

            try
            {
                fakeGameModel = new TicTacToeGameModel(model.Player1.PlayerType, model.Player2.PlayerType, model.Board, model.CurrentPlayer);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unable to create game model");
                throw e;
            }

            TicTacToeDecisionNode decisionNode = null;

            try
            {
                Player lastPlayer = fakeGameModel.Player1;
                //use last player as current player
                if (fakeGameModel.CurrentPlayer == fakeGameModel.Player1)
                {
                    lastPlayer = fakeGameModel.Player2;
                }
                decisionNode = new TicTacToeDecisionNode(fakeGameModel, fakeGameModel.CurrentPlayer.Letter, lastPlayer.Letter);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unable to create decision node");
                throw e;
            }

            MoveModel bestMove = null;

            try
            {
                bestMove = decisionNode.GetBestMove();
            }
            catch (Exception e)
            {
                Console.WriteLine("Unable to get best move");
                throw e;
            }

            return(bestMove);
        }
예제 #3
0
        private static void SetNodeOutcome(TicTacToeDecisionNode node, bool isForOriginalPlayer, SquareLetter originalLetter)
        {
            if (node.GameState == GameState.Win && node.WinningPlayer.Letter == originalLetter)
            {
                node.Score = 100;
                return;
            }
            else if (node.GameState == GameState.Win && node.WinningPlayer.Letter != originalLetter)
            {
                node.Score = -100;
                return;
            }
            else if (node.GameState == GameState.Tie)
            {
                node.Score = 0;
                return;
            }


            // check children
            if (isForOriginalPlayer)
            {
                // get max
                int max = int.MinValue;
                foreach (var childNode in node.ChildNodes)
                {
                    SetNodeOutcome(childNode, !isForOriginalPlayer, originalLetter);
                    max = Math.Max(max, childNode.Score);
                }
                node.Score = max;
                return;
            }
            else
            {
                // get min
                int min = int.MaxValue;
                foreach (var childNode in node.ChildNodes)
                {
                    SetNodeOutcome(childNode, !isForOriginalPlayer, originalLetter);
                    min = Math.Min(min, childNode.Score);
                }
                node.Score = min;
                return;
            }
        }