protected void CompletelyRandom() { bool done = false; int x, y; bool result; while (!done) { x = rand.Next(GameState.BOARDHEIGHT); y = rand.Next(GameState.BOARDWIDTH); if (opponentBoard.AvailableMove(x, y)) { result = opponentBoard.MakeMove(x, y); opponentBoard.DisplayAction(x, y, $"NPC player{playerNum}"); // DEBUG, Change to display just opponent board later DisplayGameState.DisplayOpponentBoard(opponentBoard); //DisplayGameState.DisplayBothBoards(opponentBoard, ownBoard); if (result) { currentSearch = new HashSet <Tuple <int, int> >(); currentSearch.Add(new Tuple <int, int>(x, y)); searchNewShip = false; } done = true; } } }
// Hmmm, there are some really difficult game states for NPC to check // In the interest of time, I will not make the AI completely optimal // Some ship placement can be really tricky and will require AI to keep track of order of moves // For now I do not want to do that protected void Nextmove() { List <int[]> soFar = new List <int[]>(); // NPC will randomly select a hit, and use DFS to prioritize adjacent hits // Continue Adjacent path if able, otherwise, choose any legal move // Randomly choose to go thorugh direction list forward or backward int index = rand.Next(currentSearch.Count); //gotta assign it to something Tuple <int, int> temp; HashSet <Tuple <int, int> > highPriority = new HashSet <Tuple <int, int> >(); HashSet <Tuple <int, int> > lowPriority = new HashSet <Tuple <int, int> >(); List <int[]> highPriorityList = new List <int[]>(); List <int[]> lowPriorityList = new List <int[]>(); // Randomly choosing a number from HashSet // O(N) but best to have this here since it's done once per move foreach (Tuple <int, int> t in currentSearch) { foreach (Tuple <int, int> direction in Ship.DIRECTIONS) { temp = new Tuple <int, int>(t.Item1 + direction.Item1, t.Item2 + direction.Item2); // check if the move is good if (ValidMove(temp.Item1, temp.Item2)) { if (TwoAdjacent(temp.Item1, temp.Item2)) { if (!highPriority.Contains(temp)) { highPriority.Add(temp); highPriorityList.Add(new int[] { temp.Item1, temp.Item2 }); } } else if (!lowPriority.Contains(temp)) { lowPriority.Add(temp); lowPriorityList.Add(new int[] { temp.Item1, temp.Item2 }); } } } } int[] result; if (highPriority.Count > 0) { result = highPriorityList[rand.Next(highPriorityList.Count)]; } else if (lowPriority.Count > 0) { result = lowPriorityList[rand.Next(highPriorityList.Count)]; } else { result = new int[] { 0, 0 }; Console.WriteLine("Something went seriously wrong at choose next NPC move"); } opponentBoard.MakeMove(result[0], result[1]); if (opponentBoard.IsHit(result[0], result[1])) { currentSearch.Add(new Tuple <int, int>(result[0], result[1])); } opponentBoard.DisplayAction(result[0], result[1], $"NPC player{playerNum}"); // DEBUG, Display just opponent board state DisplayGameState.DisplayOpponentBoard(opponentBoard); //DisplayGameState.DisplayBothBoards(opponentBoard, ownBoard); // Check if AI will continue to search for ships or go completely random next turn FoundAllNearbyShips(); }