public static List <Node> SolveSA(out Score score) { Stopwatch sw = Stopwatch.StartNew(); Random random = new Random(DateTime.Now.Second); Int64 numberOfNodes = -1; Int32 numberOfDiamonds = 0; List <Node> path = new List <Node>(); List <Node> Goals = new List <Node>(goals); Node startingNode = nodeGrid[initialLocation.X, initialLocation.Y]; while (Goals.Count > 0) { Node closestGoal = Goals[0]; Int32 distanceToGoal = GetManhattanDistance(startingNode.Position, closestGoal.Position); for (int i = 1; i < Goals.Count; i++) { Int32 distanceToClosestGoalCandidate = GetManhattanDistance(startingNode.Position, Goals[i].Position); if (distanceToClosestGoalCandidate < distanceToGoal) { distanceToGoal = distanceToClosestGoalCandidate; closestGoal = Goals[i]; } } Stack <Node> stack = new Stack <Node>(); List <Node> visited = new List <Node>(); Node currentNode = startingNode; currentNode.SetHCost(closestGoal.Position); currentNode.Visited = true; visited.Add(currentNode); stack.Push(currentNode); Boolean GoalReached = false; while (stack.Count > 0) { currentNode = stack.Peek(); path.Add(currentNode); numberOfNodes = Math.Max(numberOfNodes, visited.Count); if (currentNode == closestGoal) { GoalReached = true; break; } if (Goals.Contains(currentNode)) { numberOfDiamonds++; Goals.Remove(currentNode); } List <Node> neighbours = GetNodeWalkableNeighbours(currentNode.Position, true); if (neighbours.Count > 0) { while (true) { Node neighbour = neighbours.OrderBy(x => Guid.NewGuid()).FirstOrDefault(); neighbour.SetHCost(closestGoal.Position); if (neighbour.hCost < currentNode.hCost || (neighbour.hCost > currentNode.hCost && Convert.ToDecimal(random.NextDouble()) < SATemperature)) { neighbour.Visited = true; stack.Push(neighbour); path.Add(neighbour); visited.Add(neighbour); break; } } } else { currentNode = stack.Pop(); } } if (GoalReached) { numberOfDiamonds++; startingNode = closestGoal; foreach (Node v in visited) { v.Visited = false; } } Goals.Remove(closestGoal); } score = new Score("SA", numberOfNodes, numberOfDiamonds, numberOfDiamonds == goals.Count, sw.Elapsed); return(path); }
// Game Solver // Algorithms public static List <Node> SolveAStar(out Score score) { Stopwatch sw = Stopwatch.StartNew(); Int64 numberOfNodes = -1; Int32 numberOfDiamonds = 0; List <Node> Goals = new List <Node>(goals), path = new List <Node>(); Node startingNode = nodeGrid[initialLocation.X, initialLocation.Y]; while (Goals.Count > 0) { Node closestGoal = Goals[0]; Int32 distanceToGoal = GetManhattanDistance(startingNode.Position, closestGoal.Position); for (int i = 1; i < Goals.Count; i++) { Int32 distanceToClosestGoalCandidate = GetManhattanDistance(startingNode.Position, Goals[i].Position); if (distanceToClosestGoalCandidate < distanceToGoal) { distanceToGoal = distanceToClosestGoalCandidate; closestGoal = Goals[i]; } } List <Node> openSet = new List <Node>(); HashSet <Node> closedSet = new HashSet <Node>(); openSet.Add(startingNode); Node currentNode; Boolean GoalReached = false; while (openSet.Count > 0) { numberOfNodes = Math.Max(numberOfNodes, openSet.Count); currentNode = openSet[0]; for (int i = 1; i < openSet.Count; i++) { if (openSet[i].fCost < currentNode.fCost || (openSet[i].fCost == currentNode.fCost && openSet[i].hCost < currentNode.hCost)) { currentNode = openSet[i]; } } openSet.Remove(currentNode); closedSet.Add(currentNode); if (currentNode == closestGoal) { List <Node> pathToClosestGoal = new List <Node>(); GoalReached = true; while (currentNode != startingNode) { pathToClosestGoal.Add(currentNode); currentNode = currentNode.ParentNode; } pathToClosestGoal.Reverse(); path.AddRange(pathToClosestGoal); break; } List <Node> neighbours = GetNodeWalkableNeighbours(currentNode.Position); foreach (Node neighbour in neighbours) { if (closedSet.Contains(neighbour)) { continue; } if (currentNode.gCost + 1 < neighbour.gCost || !openSet.Contains(neighbour)) { neighbour.gCost = currentNode.gCost + 1; neighbour.ParentNode = currentNode; if (!openSet.Contains(neighbour)) { neighbour.SetHCost(closestGoal.Position); openSet.Add(neighbour); } } } } if (GoalReached) { numberOfDiamonds++; startingNode = closestGoal; for (int i = 0; i < mapXSize; i++) { for (int j = 0; j < mapYSize; j++) { nodeGrid[i, j].SetGCost(startingNode.Position); } } } Goals.Remove(closestGoal); } sw.Stop(); score = new Score("A*", numberOfNodes, numberOfDiamonds, numberOfDiamonds == goals.Count, sw.Elapsed); return(path); }
public static List <List <Node> > SolveIDDFS(out Score score) { Stopwatch sw = Stopwatch.StartNew(); Int64 numberOfNodes = -1; Int32 numberOfDiamonds = 0; Boolean collectedAllDiamonds = false; List <List <Node> > path = new List <List <Node> >(); for (int currentDepth = 0; currentDepth < IDDFSMaxDepth && !collectedAllDiamonds; currentDepth++) { List <Node> Goals = goals; List <Node> currentDepthPath = new List <Node>(); List <Node> visited = new List <Node>(); Stack <Node> stack = new Stack <Node>(); Node CurrentNode = nodeGrid[initialLocation.X, initialLocation.Y]; CurrentNode.Visited = true; stack.Push(CurrentNode); visited.Add(CurrentNode); while (stack.Count > 0) { CurrentNode = stack.Pop(); currentDepthPath.Add(CurrentNode); if (Goals.Contains(CurrentNode)) { Goals.Remove(CurrentNode); numberOfDiamonds++; if (Goals.Count == 0) { break; } } List <Node> neighbours = GetNodeWalkableNeighbours(CurrentNode.Position, true); foreach (Node neighbour in neighbours) { if (GetManhattanDistance(initialLocation, neighbour.Position) <= currentDepth) { neighbour.Visited = true; stack.Push(neighbour); currentDepthPath.Add(neighbour); visited.Add(neighbour); } } } foreach (Node v in visited) { v.Visited = false; } Node StartingNode = currentDepthPath[0]; currentDepthPath.RemoveAt(0); currentDepthPath.Add(StartingNode); // Last iteration //path = currentDepthPath; // All iterations path.Add(currentDepthPath); numberOfNodes = Math.Max(numberOfNodes, visited.Count); collectedAllDiamonds = Goals.Count == 0; } sw.Stop(); score = new Score("IDDFS", numberOfNodes, numberOfDiamonds, collectedAllDiamonds, sw.Elapsed); return(path); }
public static void Update(GameTime gameTime, Game1 game, GameState gameState) { if (prevGameTime == null) { prevGameTime = new GameTime(gameTime.TotalGameTime, gameTime.ElapsedGameTime); } if (nodeGrid.Length == 0) { LoadMap(); } switch (gameState) { case GameState.MANUAL_MODE: if (!gameOver) { if (!humanStopWatch.IsRunning) { humanStopWatch.Start(); } ManualMode(gameTime); } else if (gameOver && humanStopWatch.IsRunning) { humanStopWatch.Stop(); Score humanScore = new Score("Human", humanPathNumberOfNodes, collectedDiamonds, collectedDiamonds == goals.Count, humanStopWatch.Elapsed); Scores.Add(humanScore); HumanScores.Add(humanScore); humanStopWatch.Reset(); } break; case GameState.ASTAR_MODE: if (path == null) { Score score; path = SolveAStar(out score); ComputerScores.Add(score); Scores.Add(score); } if (!gameOver) { MovePlayerFromPath(gameTime); } break; case GameState.IDDFS_MODE: if (multiPath == null) { Score score; multiPath = SolveIDDFS(out score); ComputerScores.Add(score); Scores.Add(score); } if (!gameOver) { MovePlayerFrom2DPath(gameTime); } break; case GameState.CSP_MODE: if (path == null) { Score score; path = SolveCSP(out score); ComputerScores.Add(score); Scores.Add(score); } if (!gameOver) { MovePlayerFromPath(gameTime); } break; case GameState.SA_MODE: if (path == null) { Score score; path = SolveSA(out score); ComputerScores.Add(score); Scores.Add(score); SAScores.Add(score); } if (!gameOver) { MovePlayerFromPath(gameTime); } break; } if (gameOver) { Resources.backgroundMusicInstance.Stop(); } MouseState mouseState = Mouse.GetState(); if (mouseState.X < backButtonPosition.X || mouseState.Y < backButtonPosition.Y || mouseState.X > backButtonPosition.X + Resources.buttonBackground.Width || mouseState.Y > backButtonPosition.Y + Resources.buttonBackground.Height) { backHover = false; } else { backHover = true; if (mouseState.LeftButton == ButtonState.Released && prevMouseState.LeftButton == ButtonState.Pressed) { game.gameState = GameState.MAIN_MENU; Resources.backgroundMusicInstance.Stop(); if (humanStopWatch.IsRunning) { humanStopWatch.Stop(); Score humanScore = new Score("Human", humanPathNumberOfNodes, collectedDiamonds, collectedDiamonds == goals.Count, humanStopWatch.Elapsed); Scores.Add(humanScore); HumanScores.Add(humanScore); humanStopWatch.Reset(); } Reset(); } } if (game.gameState != GameState.MAIN_MENU && game.gameState != GameState.SCORES) { prevMouseState = mouseState; } }