public GameTree GetNode(UltimateTicTacToeBoard data) { if (Data.Equals(data)) { return(this); } if (Children == null || Children.Count < 1) { return(null); } var nodes = new List <GameTree>(); nodes.AddRange(Children); for (var i = 0; i < nodes.Count; i++) { if (nodes[i].Data.ToString().Equals(data.ToString())) { return(nodes[i]); } if (nodes[i].Children != null && nodes[i].Children.Count >= 1) { nodes.AddRange(nodes[i].Children); } } return(null); }
private static short CountWins(Player player, UltimateTicTacToeBoard board) { var wins = (short)(CanWin(player, board, new[] { 0, 1, 2 }) ? 1 : 0); wins += (short)(CanWin(player, board, new[] { 3, 4, 5 }) ? 1 : 0); wins += (short)(CanWin(player, board, new[] { 6, 7, 8 }) ? 1 : 0); wins += (short)(CanWin(player, board, new[] { 0, 3, 6 }) ? 1 : 0); wins += (short)(CanWin(player, board, new[] { 1, 4, 7 }) ? 1 : 0); wins += (short)(CanWin(player, board, new[] { 2, 5, 8 }) ? 1 : 0); wins += (short)(CanWin(player, board, new[] { 0, 4, 8 }) ? 1 : 0); wins += (short)(CanWin(player, board, new[] { 2, 4, 6 }) ? 1 : 0); return(wins); }
UltimateTicTacToeMove ITicTacToePlayer.TakeTurn(UltimateTicTacToeBoard ticTacToeBoard) { byte outerCell; if (ticTacToeBoard.RequiredOuterCell == null) { var validCells = ticTacToeBoard.GetValidOuterCells(); outerCell = validCells[new Random().Next(0, validCells.Count)]; } else { outerCell = ticTacToeBoard.RequiredOuterCell.Value; } var validInnerCells = ticTacToeBoard.GetValidInnerCells(outerCell); var innerCell = validInnerCells[new Random().Next(0, validInnerCells.Count)]; return(new UltimateTicTacToeMove(Player, outerCell, innerCell)); }
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); }
public UltimateTicTacToeBoard Clone(bool cloneMoves = false) { var clonedBoard = new UltimateTicTacToeBoard(); if (cloneMoves) { foreach (var move in _moves) { clonedBoard._moves.AddLast(move); } } else if (_moves.Count >= 1) { clonedBoard._moves.AddLast(_moves.Last.Value); } clonedBoard.WinningMove = WinningMove; clonedBoard.State = State; for (int i = 0; i < 9; i++) { clonedBoard._grid[i] = _grid[i].Clone(); } return(clonedBoard); }
public void AddChild(UltimateTicTacToeBoard data) { Children.Add(new GameTree(data)); }
public GameTree(UltimateTicTacToeBoard data) { Data = data; Children = new List <GameTree>(); }
private static bool CanWin(Player player, UltimateTicTacToeBoard board, IEnumerable <int> cells) { var winState = player == Player.X ? GameState.Xwin : GameState.Owin; return(cells.All(cell => board.GameBoard.ElementAt(cell).State == GameState.Open || board.GameBoard.ElementAt(cell).State == winState)); }
private static void PlayGame() { var board = new UltimateTicTacToeBoard(); ITicTacToePlayer player1 = new HumanConsolePlayer(Player.X); ITicTacToePlayer player2 = new HumanConsolePlayer(Player.O); Console.SetWindowSize(80, 48); Console.WriteLine("Ultimate Tic Tac Toe!!!"); bool correctPlayers = false; while (!correctPlayers) { Console.Write("How Many Players? "); int players; correctPlayers = int.TryParse(Console.ReadLine(), out players); if (correctPlayers) { if (players == 2) { player1 = new HumanConsolePlayer(Player.X); player2 = new HumanConsolePlayer(Player.O); } else if (players == 1) { Console.WriteLine("Do you want to play as X or O?"); var response = Console.ReadLine(); if (response?.StartsWith("x", StringComparison.InvariantCultureIgnoreCase) == true) { player1 = new HumanConsolePlayer(Player.X); player2 = new MinMaxAIPlayer(Player.O); } else if (response?.StartsWith("o", StringComparison.InvariantCultureIgnoreCase) == true) { player1 = new MinMaxAIPlayer(Player.X); player2 = new HumanConsolePlayer(Player.O); } else { correctPlayers = false; } } else if (players == 0) { player1 = new MinMaxAIPlayer(Player.X); player2 = new MinMaxAIPlayer(Player.O); } else { correctPlayers = false; } } if (!correctPlayers) { Console.WriteLine("Sorry kiddums, try again!"); } } var startTime = DateTime.UtcNow; string[] player1LastTaunt = { "" }; Taunt p1Taunt = delegate(string msg) { if (player1LastTaunt[0].Equals(msg)) { return; } player1LastTaunt[0] = msg; Console.WriteLine(msg); }; player1.SetTauntDelegate(p1Taunt); string[] player2LastTaunt = { "" }; Taunt p2Taunt = delegate(string msg) { if (player2LastTaunt[0].Equals(msg)) { return; } player2LastTaunt[0] = msg; Console.WriteLine(msg); }; player2.SetTauntDelegate(p2Taunt); var playerTurn = Player.X; while (board.State == GameState.Open) { player1LastTaunt[0] = ""; player2LastTaunt[0] = ""; var validMove = false; while (!validMove) { var move = playerTurn == Player.X ? player1.TakeTurn(board.Clone(cloneMoves: true)) : player2.TakeTurn(board.Clone(cloneMoves: true)); validMove = board.MakeMove(playerTurn, move.OuterCell, move.InnerCell); if (!validMove) { Console.WriteLine("Sorry kiddums, try again!"); } else { Console.Clear(); Console.WriteLine(GetCurrentGameStats(DateTime.UtcNow.Subtract(startTime))); Console.WriteLine(); Console.WriteLine(board.ToString()); } } playerTurn = playerTurn == Player.X ? Player.O : Player.X; } var gameTime = DateTime.UtcNow.Subtract(startTime); _playtime = _playtime.Add(gameTime); _totalPlaytime = _totalPlaytime.Add(gameTime); string stateStr = null; switch (board.State) { case GameState.Xwin: _xWins++; stateStr = "Player X Wins!"; break; case GameState.Owin: _oWins++; stateStr = "Player O Wins!"; break; case GameState.Open: break; case GameState.Draw: _draws++; stateStr = "DRAW!"; break; default: throw new ArgumentOutOfRangeException(); } Console.Clear(); Console.WriteLine(GetGameStats()); Console.WriteLine(); Console.WriteLine(board.ToString()); Console.WriteLine("Game has Ended: " + stateStr); }
UltimateTicTacToeMove ITicTacToePlayer.TakeTurn(UltimateTicTacToeBoard ticTacToeBoard) { Console.Clear(); Console.WriteLine(ticTacToeBoard.ToString()); Console.WriteLine(); if (ticTacToeBoard.LastMove != null) { Console.WriteLine($"{ticTacToeBoard.LastMove.Player} made the move [{BoardToCell(ticTacToeBoard.LastMove.OuterCell)}:{BoardToCell(ticTacToeBoard.LastMove.InnerCell)}]"); Console.WriteLine(""); } Console.WriteLine($"Player {Player}'s, Please make your move!"); byte outerCell; if (ticTacToeBoard.RequiredOuterCell == null) { Console.WriteLine("You get to play anywhere, choose wisely!"); Console.Write("Outer Cell 1-9: "); byte.TryParse(Console.ReadLine(), out outerCell); outerCell = CellToBoard(outerCell); Console.WriteLine(); } else { outerCell = ticTacToeBoard.RequiredOuterCell.Value; } var msg = "You are now playing in the "; switch (outerCell) { case 0: msg += "upper left cell"; break; case 1: msg += "upper middle cell"; break; case 2: msg += "upper right cell"; break; case 3: msg += "middle left cell"; break; case 4: msg += "center cell"; break; case 5: msg += "middle right cell"; break; case 6: msg += "lower left cell"; break; case 7: msg += "lower center cell"; break; case 8: msg += "lower right cell"; break; default: msg += "DEFAULT ERROR"; break; } Console.WriteLine(); Console.WriteLine(msg); Console.WriteLine(); Console.Write("Inner Cell 1-9: "); byte innerCell; byte.TryParse(Console.ReadLine(), out innerCell); innerCell = CellToBoard(innerCell); ticTacToeBoard.MakeMove(Player, outerCell, innerCell); Console.Clear(); Console.WriteLine(ticTacToeBoard.ToString()); return(new UltimateTicTacToeMove(Player, outerCell, innerCell)); }