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;
        }
예제 #5
0
        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.");
        }
예제 #7
0
        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;
        }
예제 #8
0
 public static NodeV1 CreateInitialNode(BoardState state, BoardGoal goal)
 {
     return new NodeV1(state, GetManhattanDistance(state, goal));
 }
예제 #9
0
 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);
        }