public List<Step[]> GetSolution(BoardState state, BoardGoal goal, CancellationToken cancellationToken) { if (state == null) { throw new ArgumentNullException(nameof(state)); } if (goal == null) { throw new ArgumentNullException(nameof(goal)); } if (state.Width != goal.Width || state.Height != goal.Height) { throw new ArgumentException($"The state ({state.Width}x{state.Height}) and the goal ({goal.Width}x{goal.Height}) has different sizes."); } PriorityQueueV1 openSet = new PriorityQueueV1(); openSet.Enqueue(NodeV1.CreateInitialNode(state, goal)); while (true) { NodeV1 current = openSet.Dequeue(); if (current.State.Satisfies(goal)) { return new List<Step[]> { GetPathFrom(current).Reverse().ToArray() }; } foreach (NodeV1 neighbor in current.GetNeighbors(goal)) { openSet.Enqueue(neighbor); } cancellationToken.ThrowIfCancellationRequested(); } }
public List<Step[]> GetSolution(BoardState state, BoardGoal goal, CancellationToken cancellationToken) { if (state == null) { throw new ArgumentNullException(nameof(state)); } if (goal == null) { throw new ArgumentNullException(nameof(goal)); } if (state.Width != goal.Width || state.Height != goal.Height) { throw new ArgumentException($"The state ({state.Width}x{state.Height}) and the goal ({goal.Width}x{goal.Height}) has different sizes."); } List<Step[]> solutions = new List<Step[]>(); int targetCost = int.MaxValue; PriorityQueueV5 openSet = new PriorityQueueV5(); openSet.Enqueue(NodeV5.CreateInitialNode(state, goal)); while (true) { NodeV5 current = openSet.Dequeue(); if (current.Cost > targetCost) { break; } if (current.EstimatedDistanceToGoal == 0) { Step[] solution = GetPathFrom(current).Reverse().ToArray(); solutions.Add(solution); if (solution.Length < targetCost) { targetCost = solution.Length; } continue; } foreach (NodeV5 neighbor in current.GetNeighbors(goal)) { if (!openSet.Contains(neighbor)) { openSet.Enqueue(neighbor); } } cancellationToken.ThrowIfCancellationRequested(); } return solutions; }
private async void OnOkClicked(object sender, RoutedEventArgs e) { this.IsEnabled = false; try { BoardDescription templateDescription = this.boardFormatter.ParseBoardDescription(this.TemplateDescription); BoardTemplate template = new BoardTemplate(templateDescription.Width, templateDescription.Height, templateDescription.Values); BoardDescription goalDescription = this.boardFormatter.ParseBoardDescription(this.GoalDescription); BoardGoal goal = new BoardGoal(goalDescription.Width, goalDescription.Height, goalDescription.Values); Drill drillToSave = this.drill.Update(this.DrillName, template, goal); if (this.update) { await this.drillService.Update(drillToSave); } else { await this.drillService.Add(drillToSave); } this.SavedDrill = drillToSave; this.Close(); } catch (InvalidBoardException exception) { MessageBox.Show( this, string.Join(Environment.NewLine, exception.Errors.Select(x => x.Message)), "Invalid board", MessageBoxButton.OK, MessageBoxImage.Warning); } catch (InvalidDrillException exception) { MessageBox.Show(this, exception.Message, "Invalid drill", MessageBoxButton.OK, MessageBoxImage.Warning); } catch { MessageBox.Show("An unexpected error occured during saving."); } finally { this.IsEnabled = true; } }
public bool Satisfies(BoardGoal goal) { if (goal == null) { throw new ArgumentNullException(nameof(goal)); } for (int i = 0; i < goal.TileCount; i++) { if (goal[i] != 0 && goal[i] != this.Values[i]) { return false; } } return true; }
public IEnumerable<NodeV1> GetNeighbors(BoardGoal goal) { if (this.State.CanSlideLeft) { yield return this.CreateNeighbor(Step.Left, this.State.SlideLeft(), goal); } if (this.State.CanSlideUp) { yield return this.CreateNeighbor(Step.Up, this.State.SlideUp(), goal); } if (this.State.CanSlideRight) { yield return this.CreateNeighbor(Step.Right, this.State.SlideRight(), goal); } if (this.State.CanSlideDown) { yield return this.CreateNeighbor(Step.Down, this.State.SlideDown(), goal); } }
public BoardState Generate(BoardTemplate template, BoardGoal goal) { if (template == null) { throw new ArgumentNullException(nameof(template)); } if (goal == null) { throw new ArgumentNullException(nameof(goal)); } for (int i = 0; i < RetryCount; i++) { BoardState state = this.Generate(template); if (!state.Satisfies(goal)) { return state; } } throw new BoardGenerationException("Failed to generate a board that doesn't satisfy the specified goal."); }
private static int GetManhattanDistance(BoardState state, BoardGoal goal) { int width = state.Width; int height = state.Height; int sum = 0; for (int i = 0; i < goal.TileCount; i++) { if (goal[i] == 0) { continue; } for (int j = 0; j < state.TileCount; j++) { if (state[j] == goal[i]) { int x1 = i % width; int y1 = i / height; int x2 = j % width; int y2 = j / height; sum += Math.Abs(x1 - x2) + Math.Abs(y1 - y2); break; } } } return sum; }
public static NodeV1 CreateInitialNode(BoardState state, BoardGoal goal) { return new NodeV1(state, GetManhattanDistance(state, goal)); }
private NodeV1 CreateNeighbor(Step previousStep, BoardState newState, BoardGoal goal) { return new NodeV1(this, previousStep, newState, this.distanceFromInitialNode + 1, GetManhattanDistance(newState, goal)); }
public static SimplifiedBoardState Create(BoardState state, BoardGoal goal) { int[] values = new int[state.TileCount]; int eye = 0; for (int i = 0; i < state.TileCount; i++) { if (state[i] == 0) { eye = i; values[i] = -1; continue; } for (int j = 0; j < goal.TileCount; j++) { if (state[i] == goal[j]) { values[i] = state[i]; break; } } } return new SimplifiedBoardState(state.Width, state.Height, values, eye); }