Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.52/21: Рейтинг темы: голосов - 21, средняя оценка - 4.52
 Аватар для andreyananas
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880

8-puzzle

20.01.2017, 16:52. Показов 5055. Ответов 38

Студворк — интернет-сервис помощи студентам
Предыстория: проходя, в универе курс "системы искусственного интеллекта", нам задали спроектировать приложение, которое будет решать "проблему" 8-puzzle разными алгоритмами и сравнивать их эффективность.
Почему-то мне захотелось сделать её нормальной: с адекватным UI, где можно будет увидеть каждых шаг решения задачи. Что-то наподобие этого .

Решил писать на Qt 5.7 MSVC 64 так как наиболее с ним знаком.
Первоначально программа должна решать задачу 8-puzzle при помощи информативного алгоритма A* H1 (количество фишек, которые стоят не на своих местах). Далее будут добавлены и другие.

1. Собственно пока что я не совсем понимаю, с помощью каких виджетов лучше проектировать сами пазлы .
То есть, нужно использовать QGraphicsScene и для каждой цифры создавать QGraphicsItem?
Или можно цифры сделать в виде QLabel и перемещать их в табличном лойауте?

2. Также, я не совсем понимаю как вообще решается задача. При этом сам алгоритм А*, вроде бы понятен...

п.с. заранее спасибо за помощь в поисках истины =)
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
20.01.2017, 16:52
Ответы с готовыми решениями:

Class QPainter игра Memory Puzzle
Хочу написать игру аналог Memory Puzzle. Когда начала писать, столкнулась с проблемой : Cоздаю 2 прямокутника, 1)и на каждом у...

Puzzle
Добрый день! есть игра Pazzle, которая разбивает картинку на кусочки и перемешивает их, т.е по типу "пятнашек". Необходимо...

The Spots Puzzle на прологе
Необходимо создать головоломку. Головоломка состоит из девяти брусочков размером 1x1x3, на каждый из которых нанесены точки. Задача...

38
 Аватар для Wyn
1073 / 654 / 230
Регистрация: 14.01.2016
Сообщений: 2,031
Записей в блоге: 9
26.01.2017, 08:34
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от 0x90h Посмотреть сообщение
периодический вызов processEvents
И что будет, если во время вызова processEvents пользователь снова вызовет функцию обсчёта алгоритма? ProcessEvents, как и мультипоток, тоже требует изменения программы и учёт его особенностей работы. Но да, как вариант.
1
737 / 704 / 110
Регистрация: 29.05.2015
Сообщений: 4,341
26.01.2017, 09:14
Цитата Сообщение от Wyn Посмотреть сообщение
И что будет, если во время вызова processEvents пользователь снова вызовет функцию обсчёта алгоритма? ProcessEvents, как и мультипоток, тоже требует изменения программы и учёт его особенностей работы. Но да, как вариант.
Зачем??? Алгоритм отработал, данные поменялись - вызывайте ProcessEvents и выводите на экран. Что значит, пользователь снова вызовет? Программа либо работает в цикле до решения, и пользователь ничего вызвать не может. Либо пошагово (по нажатию той же кнопки выполняется шаг алгоритма), но тогда и ProcessEvents не нужен.

ProcessEvents для визуализации длинных вычислений, чтобы понимать - ещё считает или уже зависла? Ну и для красоты, чтобы на форме какие-нить циферки тикали. Типо анимэ...
1
 Аватар для Wyn
1073 / 654 / 230
Регистрация: 14.01.2016
Сообщений: 2,031
Записей в блоге: 9
26.01.2017, 10:02
Цитата Сообщение от alexu_007 Посмотреть сообщение
Зачем??? Алгоритм отработал, данные поменялись - вызывайте ProcessEvents и выводите на экран. Что значит, пользователь снова вызовет? Программа либо работает в цикле до решения, и пользователь ничего вызвать не может. Либо пошагово (по нажатию той же кнопки выполняется шаг алгоритма), но тогда и ProcessEvents не нужен.
ProcessEvents для визуализации длинных вычислений, чтобы понимать - ещё считает или уже зависла? Ну и для красоты, чтобы на форме какие-нить циферки тикали. Типо анимэ...
processEvent не является волшебным методом. Это просто метод, который вызывает исполнения всех находящихся в данный момент в очереди событий. Если там окажется событие нажатия кнопки "Посчитать алгоритмом", то оно автоматом запустит выполнение ещё одного просчёта по алгоритму. В данном случае я говорю именно о алгоритме, а не о анимации решения, которое просчитал алгоритм. Анимация решения - отдельный разговор, там всё просто - сформировать анимации посредством QSequentialAnimationGroup и поставить эту группу на выполнение.
1
 Аватар для andreyananas
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
26.01.2017, 10:42  [ТС]
Цитата Сообщение от alexu_007 Посмотреть сообщение
Это что-то криво у вас написано. Массив 3х3 должен собираться мгновенно
С помощью алгоритма А* Н1 (Number of Misplaced tiles)? Что то я очень сомневаюсь.

Добавлено через 9 минут
Цитата Сообщение от Wyn Посмотреть сообщение
И что будет, если во время вызова processEvents пользователь снова вызовет функцию обсчёта алгоритма? ProcessEvents, как и мультипоток, тоже требует изменения программы и учёт его особенностей работы. Но да, как вариант.
Цитата Сообщение от alexu_007 Посмотреть сообщение
Зачем??? Алгоритм отработал, данные поменялись - вызывайте ProcessEvents и выводите на экран. Что значит, пользователь снова вызовет? Программа либо работает в цикле до решения, и пользователь ничего вызвать не может. Либо пошагово (по нажатию той же кнопки выполняется шаг алгоритма), но тогда и ProcessEvents не нужен.
ProcessEvents для визуализации длинных вычислений, чтобы понимать - ещё считает или уже зависла? Ну и для красоты, чтобы на форме какие-нить циферки тикали. Типо анимэ...
Цитата Сообщение от Wyn Посмотреть сообщение
processEvent не является волшебным методом. Это просто метод, который вызывает исполнения всех находящихся в данный момент в очереди событий. Если там окажется событие нажатия кнопки "Посчитать алгоритмом", то оно автоматом запустит выполнение ещё одного просчёта по алгоритму. В данном случае я говорю именно о алгоритме, а не о анимации решения, которое просчитал алгоритм. Анимация решения - отдельный разговор, там всё просто - сформировать анимации посредством QSequentialAnimationGroup и поставить эту группу на выполнение.
Ребята, вы немного не поняли проблему.
Суть в том, что во время поиска алгоритмом решения, если попытаться передвинуть окно программы -- оно подвисает (появляется надписать "Не отвечает"). Но как только алгоритм закончил подсчет ответа, все нормально работает.
Во время работы алгоритма никаких анимаций происходить НЕ должно!
Анимация возможна только после нахождения решения, её обработку я еще не делал.
0
693 / 465 / 162
Регистрация: 01.10.2015
Сообщений: 1,274
26.01.2017, 10:57
Цитата Сообщение от andreyananas Посмотреть сообщение
Ребята, вы немного не поняли проблему.
Вы нагружаете поток, в котором выполняется графический интерфейс, вычислениями, которые вдобавок выполняете в цикле, соответственно до завершения цикла, все события, связанные с изменением GUI, выполняться не будут, отсюда "подвисание". Проще говоря, основному потоку, ответственному за GUI, некогда заниматься своими прямыми обязанностями. Про отдельный поток вам уже говорили выше.
1
137 / 107 / 23
Регистрация: 06.10.2008
Сообщений: 451
26.01.2017, 11:01
QProgressBar?
Его можно обновлять в процессе работы алгоритма.
1
 Аватар для Wyn
1073 / 654 / 230
Регистрация: 14.01.2016
Сообщений: 2,031
Записей в блоге: 9
26.01.2017, 11:34
Цитата Сообщение от andreyananas Посмотреть сообщение
Ребята, вы немного не поняли проблему.
Мы всё верно поняли, у нас тут разговор немного о другом - об использовании вызова processEvent в качестве решения вашей проблемы.Это не очень хорошая вещь и она редко где используется. Уж лучше тогда выносить вычисления в отдельный поток.
При этом интерфейс, как в одним случае, так и в другом, придётся переделывать. К примеру, отключать кнопку, которая вызывает вычисление алгоритма, изменять указатель мышки на Busy и т.д. и т.п. Я бы советовал вам сейчас этим не заниматься и сосредоточиться на реализации алгоритмов и чернового варианта программы. А оптимизациями заниматься потом - если останется время.
1
737 / 704 / 110
Регистрация: 29.05.2015
Сообщений: 4,341
26.01.2017, 15:27
Цитата Сообщение от andreyananas Посмотреть сообщение
С помощью алгоритма А* Н1 (Number of Misplaced tiles)? Что то я очень сомневаюсь.
Ну объясните всё же принцип работы этого алгоритма, или дайте ссылку на него?
0
 Аватар для andreyananas
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
26.01.2017, 16:28  [ТС]
Цитата Сообщение от alexu_007 Посмотреть сообщение
Ну объясните всё же принцип работы этого алгоритма, или дайте ссылку на него?
Вот ссылка. И еще.
0
737 / 704 / 110
Регистрация: 29.05.2015
Сообщений: 4,341
26.01.2017, 20:56
Это алгоритм поиска кратчайшего пути из точки А к точке В. Как с его помощью сложить пазл? У меня что-то соображалки не хватает. И мне кажется, это вообще "не о том"...
0
 Аватар для andreyananas
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
26.01.2017, 21:02  [ТС]
Цитата Сообщение от alexu_007 Посмотреть сообщение
Это алгоритм поиска кратчайшего пути из точки А к точке В. Как с его помощью сложить пазл? У меня что-то соображалки не хватает. И мне кажется, это вообще "не о том"...
Такие же проблемы были.
0
737 / 704 / 110
Регистрация: 29.05.2015
Сообщений: 4,341
26.01.2017, 21:10
Ну так как задача решается?
0
 Аватар для andreyananas
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
26.01.2017, 23:39  [ТС]
Цитата Сообщение от alexu_007 Посмотреть сообщение
Ну так как задача решается?
Astar.h
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#ifndef ALGORITHMASTAR_H
#define ALGORITHMASTAR_H
 
#include "ialgorithm.h"
 
#include <QString>
#include <QMultiMap>
 
 
class AlgorithmAstar : public IAlgorithm
{
    enum class modeMove{up = 1, down, right, left};
 
    struct Node{
        Node * pLink1;
        Node * pLink2;
        Node * pLink3;
        Node * pLink4;
        Node * pParent;
        QVector<int> nodeState;
        int nodeCost;
        int distance;
        int indexEmpty;
        Node(): pLink1(nullptr), pLink2(nullptr), pLink3(nullptr), pLink4(nullptr), pParent(nullptr){}
    };
 
    Node * m_pRoot;
    QMultiMap<int, Node *> m_nodesOpen;
    QList<Node *> m_nodesClose;
    QVector<int> * m_pStartState;
    QVector<int> * m_pTargetState;
    QList<QVector<int>> m_ListResult;
    bool m_success;
public:
    explicit AlgorithmAstar(const QVector<int> vecFinalState = {1,2,3,4,5,6,7,8,0});
    ~AlgorithmAstar();
 
    bool solvePuzzle(const QVector<int> &State, int &time, int limit);
    QList<QVector<int> > getSolution(int &moves);
 
private:
    void makeRoot();
    int costCalculator(Node * pCurNode);
    void insertStates(Node * pCurNode);
    bool makeMove(Node * pCurNode, Node * pNodeChild, modeMove mode);
    bool checkNewNode(Node * pCurNode);
    bool isSuccess(Node * pCurNode);
    void buildResult(Node * pCurNode);
};
 
#endif // ALGORITHMASTAR_H



Astar.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#include "algorithmastar.h"
 
AlgorithmAstar::AlgorithmAstar(const QVector<int> vecFinalState)
{
    m_pTargetState = new QVector<int>(vecFinalState);
    m_pStartState = m_pTargetState;
}
 
AlgorithmAstar::~AlgorithmAstar()
{
    m_pStartState->clear();
    delete m_pStartState;
 
    m_pTargetState->clear();
    delete m_pTargetState;
 
    if(!m_nodesOpen.isEmpty())
        qDeleteAll(m_nodesOpen);
    if(!m_nodesClose.isEmpty())
        qDeleteAll(m_nodesClose);
}
 
 
QList<QVector<int>> AlgorithmAstar::getSolution(int &moves)
{
    moves = m_ListResult.size() - 1;
    return m_ListResult;
}
 
 
bool AlgorithmAstar::solvePuzzle(const QVector<int> &State, int &time, int limit)
{
    m_pStartState = new QVector<int>(State);
    m_success = false;
 
    makeRoot();
    int nodeCount(0);
    Node * pCurNode;
    time_t finish, start = clock();
    while(!m_nodesOpen.isEmpty())
    {
        pCurNode = m_nodesOpen.first();
        m_nodesOpen.erase(m_nodesOpen.begin());
        if(isSuccess(pCurNode))
            break;
 
        insertStates(pCurNode);
        m_nodesClose.push_back(pCurNode);
 
        if(limit != 0 && limit == nodeCount)
            break;
        nodeCount++;
    }
    finish = clock();
    time = finish - start;
    return m_success;
}
 
 
void AlgorithmAstar::makeRoot()
{
    if(!m_nodesOpen.isEmpty())
        qDeleteAll(m_nodesOpen);
    if(!m_nodesClose.isEmpty())
        qDeleteAll(m_nodesClose);
 
    m_pRoot = new Node();
    m_pRoot->nodeState = *m_pStartState;
    m_pRoot->nodeCost = costCalculator(m_pRoot);
    m_pRoot->distance = 0;
 
    m_pRoot->indexEmpty = m_pRoot->nodeState.indexOf(0);
 
    m_nodesOpen.insert(m_pRoot->nodeCost, m_pRoot);
}
 
 
int AlgorithmAstar::costCalculator(AlgorithmAstar::Node *pCurNode) // h1
{
    int cost(0);
    for(auto i(0); i < pCurNode->nodeState.size(); i++)
        if(pCurNode->nodeState[i] != m_pTargetState->at(i))
            cost++;
 
    return cost;
}
 
 
void AlgorithmAstar::insertStates(Node *pCurNode)
{
    // 1st LINK
    Node * pNodeChild = new Node();
    if(makeMove(pCurNode, pNodeChild, modeMove::up)
            && checkNewNode(pNodeChild))
    {
        pCurNode->pLink1 = pNodeChild;
        m_nodesOpen.insert(pNodeChild->nodeCost, pNodeChild);
    }
    else
    {
        delete pNodeChild;
    }
 
    // 2st LINK
    pNodeChild = new Node();
    if(makeMove(pCurNode, pNodeChild, modeMove::down)
            && checkNewNode(pNodeChild))
    {
        pCurNode->pLink2 = pNodeChild;
        m_nodesOpen.insert(pNodeChild->nodeCost, pNodeChild);
    }
    else
    {
        delete pNodeChild;
    }
 
    // 3st LINK
    pNodeChild = new Node();
    if(makeMove(pCurNode, pNodeChild, modeMove::right)
            && checkNewNode(pNodeChild))
    {
        pCurNode->pLink3 = pNodeChild;
        m_nodesOpen.insert(pNodeChild->nodeCost, pNodeChild);
    }
    else
    {
        delete pNodeChild;
    }
 
    // 4st LINK
    pNodeChild = new Node();
    if(makeMove(pCurNode, pNodeChild, modeMove::left)
            && checkNewNode(pNodeChild))
    {
        pCurNode->pLink4 = pNodeChild;
        m_nodesOpen.insert(pNodeChild->nodeCost, pNodeChild);
    }
    else
    {
        delete pNodeChild;
    }
}
 
 
bool AlgorithmAstar::makeMove(AlgorithmAstar::Node *pCurNode,
                              AlgorithmAstar::Node *pNodeChild,
                              AlgorithmAstar::modeMove mode) // MAKE AND INIT children
{
    bool moveCompleted(true);
    bool incorrectMove(false);
    pNodeChild->nodeState = pCurNode->nodeState;
    pNodeChild->indexEmpty = pNodeChild->nodeState.indexOf(0);
 
    if(pCurNode->distance > 2 &&
            pCurNode->pParent->indexEmpty == pNodeChild->indexEmpty) // check loop
    {
        incorrectMove = true;
    }
 
    switch(mode)
    {
    case modeMove::up:
        if(pNodeChild->indexEmpty > 2 && !incorrectMove)
        {
            std::swap(pNodeChild->nodeState[pNodeChild->indexEmpty],
                    pNodeChild->nodeState[pNodeChild->indexEmpty - 3]);
 
            pNodeChild->distance = pCurNode->distance + 1;
            pNodeChild->nodeCost = costCalculator(pNodeChild) + pNodeChild->distance;
            pNodeChild->pParent = pCurNode;
        }
        else
            moveCompleted = false;
        break;
 
    case modeMove::down:
        if(pNodeChild->indexEmpty < 6 && !incorrectMove)
        {
            std::swap(pNodeChild->nodeState[pNodeChild->indexEmpty],
                    pNodeChild->nodeState[pNodeChild->indexEmpty + 3]);
 
            pNodeChild->distance = pCurNode->distance + 1;
            pNodeChild->nodeCost = costCalculator(pNodeChild) + pNodeChild->distance;
            pNodeChild->pParent = pCurNode;
        }
        else
            moveCompleted = false;
        break;
 
    case modeMove::right:
        if(pNodeChild->indexEmpty%3 != 2 && !incorrectMove)
        {
            std::swap(pNodeChild->nodeState[pNodeChild->indexEmpty],
                    pNodeChild->nodeState[pNodeChild->indexEmpty + 1]);
 
            pNodeChild->distance = pCurNode->distance + 1;
            pNodeChild->nodeCost = costCalculator(pNodeChild) + pNodeChild->distance;
            pNodeChild->pParent = pCurNode;
        }
        else
            moveCompleted = false;
        break;
 
    case modeMove::left:
        if(pNodeChild->indexEmpty%3 != 0 && !incorrectMove)
        {
            std::swap(pNodeChild->nodeState[pNodeChild->indexEmpty],
                    pNodeChild->nodeState[pNodeChild->indexEmpty - 1]);
 
            pNodeChild->distance = pCurNode->distance + 1;
            pNodeChild->nodeCost = costCalculator(pNodeChild) + pNodeChild->distance;
            pNodeChild->pParent = pCurNode;
        }
        else
            moveCompleted = false;
        break;
 
    default:
        moveCompleted = false;
        break;
    }
 
    return moveCompleted;
}
 
 
bool AlgorithmAstar::checkNewNode(AlgorithmAstar::Node *pCurNode)
{
    bool bOk(true);
 
    foreach(auto node, m_nodesOpen)
        if(pCurNode->nodeState == node->nodeState
                && pCurNode->distance >= node->distance)
            bOk = false;
 
    foreach(auto node, m_nodesClose)
        if(pCurNode->nodeState == node->nodeState)
            if(pCurNode->distance >= node->distance)
                bOk = false;
            else
                m_nodesClose.removeOne(node);
 
    return bOk;
}
 
 
bool AlgorithmAstar::isSuccess(Node *pCurNode)
{
 
    if(pCurNode->nodeState == *m_pTargetState)
    {
        m_success = true;
        buildResult(pCurNode);
    }
 
    return m_success;
}
 
void AlgorithmAstar::buildResult(Node *pCurNode)
{
    m_ListResult.clear();
 
    while(pCurNode != nullptr)
    {
        m_ListResult.push_front(pCurNode->nodeState);
        pCurNode = pCurNode->pParent;
    }
}

Составляется дерево состояний среди которых и ищется "правильная" цепочка.
При этом если изменить эвристическую функцию на Н2, результат будет находиться гораздо быстрее.
0
737 / 704 / 110
Регистрация: 29.05.2015
Сообщений: 4,341
27.01.2017, 09:19
Мдя... без пол-литры тут никак... и чего, она реально решает задачу? То есть если ей задать на вход рисунок 1, то она найдёт последовательность ходов, приводящую к рисунку 2?

А у вас есть рабочий проект с этой штукой? Хотелось бы разобраться, как работает.
Изображения
  
0
 Аватар для andreyananas
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
27.01.2017, 14:38  [ТС]
Цитата Сообщение от alexu_007 Посмотреть сообщение
То есть если ей задать на вход рисунок 1, то она найдёт последовательность ходов, приводящую к рисунку 2?
Не уверен. Теоретически, если решение существует, тогда в итоге должен найти верный путь.
Цитата Сообщение от alexu_007 Посмотреть сообщение
А у вас есть рабочий проект с этой штукой? Хотелось бы разобраться, как работает.
Держи.
Вложения
Тип файла: zip 8-puzzle.zip (245.9 Кб, 5 просмотров)
0
 Аватар для andreyananas
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
27.01.2017, 14:41  [ТС]
Но я не уверен на 100%, что моя реализация алгоритма абсолютно правильная. Потому что некоторые начальные наборы цифр подозрительно долго решает.
С другой стороны, как я понимаю, А* это самый базовый алгоритм информационного поиска и есть намного лучше.
0
737 / 704 / 110
Регистрация: 29.05.2015
Сообщений: 4,341
28.01.2017, 10:42
Ссылки давать нельзя, погугли "Пятнашки « Программы « Сайт Алексея Озерицкого", там решение пятнашек. А раз 4х4 решаются на раз, то и 3х3 тем более.

Я щас пробую эту программу Озерицкого в Qt перетащить, но только начал разбираться пока.
0
 Аватар для andreyananas
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
28.01.2017, 22:12  [ТС]
Цитата Сообщение от alexu_007 Посмотреть сообщение
Ссылки давать нельзя, погугли "Пятнашки « Программы « Сайт Алексея Озерицкого", там решение пятнашек. А раз 4х4 решаются на раз, то и 3х3 тем более.
Пятнашки представляют собой классическую задачу для моделирования эвристических алгоритмов. Моя программа решает ее с помощью алгоритма A*.

Данный алгоритм является эвристической версией алгоритма поиска в ширину на графе. Вершины для обхода выбираются в соответствии с эвристикой — предполагаемым количеством ходов до цели. В этой программе для оценки расстояния до цели я использовал следюущие эвристики: «Манхэттенское расстояние», «Линейный конфликт», «Последний ход», «Угловые фишки»
У меня, по заданию, другая эвристическая функция, а именно: misplaced tiles (ссылка ня мой код) -- это самая не эффективная (хуже только константа) функция. Возможно позже добавлю «Манхэттенское расстояние».

С другой стороны я не исключаю, что допустил ошибку=).

Цитата Сообщение от alexu_007 Посмотреть сообщение
Я щас пробую эту программу Озерицкого в Qt перетащить, но только начал разбираться пока.
Как сделаешь её, выкладываю сюда, заменим.
0
 Аватар для andreyananas
27 / 27 / 11
Регистрация: 15.10.2013
Сообщений: 880
30.01.2017, 01:31  [ТС]
К алгоритму А* добавил эвристическую функцию "манхетенская дистанция". При использовании её, решаемые задачи выполняются мгновенно. Сравнивал на онлайн ресурсах, у них в несколько раз медленнее (наверное из-за того, что я использую С++).
Кому интересно можете скачать (ссылка).

Добавлено через 4 минуты

Не по теме:

Всем спасибо за помощь =)

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
30.01.2017, 01:31

C# игра puzzle bubble
Помогите доработать програму а то у меня не получается: 1. Нада добавить движение шарика по направлении линии при натиску на пробел. ...

8-puzzle (генерация стартового состояния)
Написал программу, которая выполняет поиск решения для задачи 8-пазлов. Тема. Код. Алгоритмы поиска нормально работают, с этим все...

Jigsaw Puzzle а именно наложение картинки на пазл
всем привет хоче сделать игрушку пазл с нарезкой картинки разобрался а вот с наложением этих нарезок на маски пазла проблемка ...

Puzzle Wars - он-лайн игра для тех, кому за тридцать
Расскажу поподробнее об игре. Проект Puzzle Wars основан на механике знакомого многим Match 3 и предназначен для широкого круга...

Groovy Игрушка "puzzle" - логика работает, а изображение не меняется
//puzzle.groovy package groovy import groovy.swing.SwingBuilder import javax.swing.* import java.awt.FlowLayout import...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Новые блоги и статьи
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины". За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html Задача: . . .
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru