// Алгоритм A*
load_array %map C:\Users\abc\Desktop\map1.txt // массив карта
load_array %coord C:\Users\abc\Desktop\coord1.txt // координаты точек
set $start A // обозначение точки A в массиве
set $ending B // обозначение точки B в массиве
// 0 - ходы только по вертикали и горизонтали, 1 - по диагонали тоже
set #angle 0
set #logmap 1 // выводить в лог карту
set #readmap 1 // выводить ходы в лог
set #skipstep 0 // 0 - не пропускать ходы, 1 - пропускать. Нужно, если ширина препятствия меньше ширины клетки, на которую можно сделать ход.
set #click 1 // делать ходы, клик по координатам точек.
set #send 0 // делать ходы, нажатия клавииш Up, Down, Left, Right
set #hint 1 // показывать количество проверенных точек
set #showpoint 0 // показывать проверенные точки (клик по ним)
set #wait 30 // пауза между нажатиями клавиш Up, Down, Left, Right
// остальное менять не нужно
// направление движения
init_arr %vector (1) -1 -1 0 1 1 1 0 -1 // x
init_arr %vector (2) 0 1 1 1 0 -1 -1 -1 // y
set #handle workwindow
if workwindow = 0
Log Не сделана привязка
Log Скрипт остановлен
stop_script
end_if
if size(%map) = 0
Log Массив с картой не найден.
Log Скрипт остановлен
stop_script
end_if
if size(%coord) = 0
Log Массив с координатами не найден.
Log Скрипт остановлен
stop_script
end_if
log clear
log mode compact
set size(%tmp)
set size(%open)
set size(%close)
set size(%curr)
set size(%resultarray)
set #width size(%map[])
set #height size(%map)
set %sizemap indexof (%map (0))
set #sizemap size(%sizemap) + 1
// Позиция конечной точки на карте
set %ending indexof (%map ($ending))
// Позиция начальной точки на карте
set %start indexof (%map ($start))
// если точка A или B не найдены
if size(%ending) = 0 or size(%start) = 0
if size(%start) = 0
log Точка A не найдена
else
log Точка B не найдена
end_if
log Скрипт остановлен
end_script
end_if
// F, G, H, Направление_движения, Текущая клетка(X Y), Текущая клетка(X:Y), Родительская клетка (X Y)
init_arr %open (1) 0 0 0 0 %start [1 1] %start [1 2] %start [1 1]:%start [1 2] %start [1 1] %start [1 2]
while 1 = 1
sort_array %open // сортировка по наименьшему F
set #sizeclose size(%close) + 1
init_arr %curr (1) %open [1 1] %open [1 2] %open [1 3] %open [1 4] %open [1 5] %open [1 6] %open [1 7] %open [1 8] %open [1 9] // текущая клетка
init_arr %close (#sizeclose) %open [1 1] %open [1 2] %open [1 3] %open [1 4] %open [1 5] %open [1 6] %open [1 7] %open [1 8] %open [1 9] // добавить в закрытый список
if #showpoint = 1
left %coord[%curr[1 5] %curr[1 6]]
wait 1
end_if
delete_array %open -1 // удалить с открытого списка
// для каждой из 8 клеток просчёт хода
for #i 1 8
if #angle = 1 or mod(#i 2) = 1 // если ходы по диагонали допустимы или проверяется ход не по диагонали
set #x %curr [1 5] + %vector [1 #i]
set #y %curr [1 6] + %vector [2 #i]
init_arr %tmp (1) #x : #y
// поиск клетки в закрытом списке
set %resultclose indexof (%close (%tmp[1]))
if #x > 0 and #y > 0 and #x <= #height and #y <= #width // проверка не вышли ли за пределы массива
if (%map [#x #y] = 0 or %map [#x #y] = $ending) and size(%resultclose) = 0 // (если на клетку возможен ход или она является конечной) и не находится в закрытом списке
set %resultopen indexof (%open (%tmp[1])) // Если клетка еще не в открытом списке, то добавляем ее туда.
if size( %resultopen) = 0
set #sizeopen size(%open) + 1
if mod(#i 2) = 1
set #g %curr [1 2] + 10 // стоимость G
else
set #g %curr [1 2] + 14
end_if
set #h (abs(eval(#x - %ending [1 1])) + abs(eval(#y - %ending [1 2]))) * 10 // стоимость H
set #f #g + #h // стоимость F
init_arr %open (#sizeopen) #f #g #h #i #x #y %tmp[1] %curr [1 5] %curr [1 6]
else
// если клетка уже в открытом списке
set #tmp %resultopen [1 1] // позиция клетки в открытом списке
set #g1 %open[#tmp 2] // стоимость G клетки находящейся в открытом списке
if mod(#i 2) = 1
set #g %curr [1 2] + 10 // стоимость G текущей клетки + стоимость хода на клетку находящуюся в открытом списке
else
set #g %curr [1 2] + 14
end_if
if #g < #g1 // если стоимость хода дешевле
// меняем стоимость хода клетки находящейся в открытом списке
// меняем родителя клетки на текущую
set #h (abs(eval(#x - %ending [1 1])) + abs(eval(#y - %ending [1 2]))) * 10
set #f #g + #h
init_arr %open (#tmp) #f #g #h #i #x #y %tmp[1] %curr [1 5] %curr [1 6]
end_if
end_if
end_if
end_if
end_if
end_for
// если конечная клетка добавлена в закрытый список или все точки проверены
if (%curr [1 5] = %ending [1 1] and %curr [1 6] = %ending [1 2]) or size(%open) = 0
if %curr [1 5] != %ending [1 1] and %curr [1 6] != %ending [1 2]
log Вариантов хода нет
end_script
end_if
// проходим весь путь от точки B до точки A и записываем путь в массив
set size(%tmp)
init_arr %tmp (1) %close [size(%close) 8] %close [size(%close) 9]
while %tmp [size(%tmp) 1] != %start [1 1] or %tmp [size(%tmp) 2] != %start [1 2]
set %pathAB indexof (%close (%tmp [size(%tmp) 1]:%tmp [size(%tmp) 2]))
set #zz size(%tmp) + 1
init_arr %tmp (#zz) %close [%pathAB [1 1] 8] %close [%pathAB [1 1] 9] %close [%pathAB [1 1] 4]
end_while
set #z 0
set delimiter ' '
for #i size(%tmp) 1 -1
set #z #z + 1
init_arr %resultarray (#z) %tmp [#i]
end_for
set delimiter
// save_array %open C:\Users\abc\Desktop\open.txt // открытый список
// save_array %close C:\Users\abc\Desktop\close.txt // закрытый список
// save_array %resultarray C:\Users\abc\Desktop\resultarray.txt // массив с индексами нужных точек находящихся в массиве %map
log На поиск хода затрачено: timer мсек
// Вывод карты
if #logmap = 1
gosub logmap
end_if
// Вывод в лог ходов
if #readmap = 1
gosub readmap
end_if
// Сделать ход
if #click = 1
gosub hod
end_if
end_script
end_if
if #hint = 1
hint Проверено size(%close) из #sizemap точек.
end_if
end_while
end_script
:logmap
for #i 1 size(%map)
log %map [#i]
end_for
return
:readmap
set workwindow #handle
wait 500
showwindow #handle
wait 500
set #tmpi size(%resultarray) - 1
for #i 1 size(%resultarray)
if (#skipstep = 0) or (mod (#i 2) = 0 or #tmpi = #i)
switch %resultarray [#i 3]
case 1: log Вверх
if #send = 1
send {Up}
wait #wait
end_if
break
case 2: log Вверх-Вправо
if #send = 1
send {Up}
wait #wait
send {Right}
wait #wait
end_if
break
case 3: log Вправо
if #send = 1
send {Right}
wait #wait
end_if
break
case 4: log Вниз-Вправо
if #send = 1
send {Down}
wait #wait
send {Right}
wait #wait
end_if
break
case 5: log Вниз
if #send = 1
send {Down}
wait #wait
end_if
break
case 6: log Вниз-Влево
if #send = 1
send {Down}
wait #wait
send {Left}
wait #wait
end_if
break
case 7: log Влево
if #send = 1
send {Left}
wait #wait
end_if
break
case 8: log Вверх-Влево
if #send = 1
send {Up}
wait #wait
send {Left}
wait #wait
end_if
break
end_switch
end_if
end_for
return
:hod
if #showpoint = 1
alarm
set showscriptprocessing 1
log Путь найден. Скрипт на паузе.
log Для вывода пути снять скрипт с паузы.
pause_script
set showscriptprocessing 0
end_if
showwindow #handle
wait 500
if #skipstep = 0
for #i 2 size(%resultarray) // делать все ходы
kleft %coord[%resultarray [#i 1] %resultarray [#i 2]]
// log %coord[%resultarray [#i 1] %resultarray [#i 2]]
wait 1
end_for
else
for #i 3 size(%resultarray) 2 // пропускать не нужные ходы
kleft %coord[%resultarray [#i 1] %resultarray [#i 2]]
// log %coord[%resultarray [#i 1] %resultarray [#i 2]]
wait 1
end_for
end_if
return
Жухала
Адаптировать такое на какую нибудь рогрпг аля дьяблы что бы искал кротчайший путь по карте до выхода их подземелья. Все проходящие игру на скоростью сдохнут от зависти.
Все конечно здорово, но для второй карты минута с лишним расчет. Встроить в пилот было бы замечательно. Да и предусмотреть бы возможность сохранения результата.
сам когда-то задавался данной задачей, но что-то заглохло все.
В состоянии ли данная реализация выдать путь для некоторого набора вейпонитов?
Т.е. есть некоторый набор точек с указанием к каким точкам из них можно добраться.
2 2 5
3 2 5
3 3 3
3 4 1
2 4
Красавчик.
Свитч полностью дублируется. Так имхо чуть короче.
for #i 1 size(%resultarray)
// #skipstep = 0 // показывать все ходы
// mod (#i 2) = 0 or #tmpi = #i // пропускать не нужные ходы
if (#skipstep = 0) or (mod (#i 2) = 0 or #tmpi = #i)
switch %resultarray [#i 3]
...
end_switch
end_if
end_for
Вы же понимаете что вам для нормальной работы этого алгоритма в пилоте нужно так-же правила передвижения от ноде к ноде знать.
Мож для какого-нибудь 2Д лабиринта где только стенка и не стенка есть и сойдет, а все остальное... я не вижу как можно обобщить это и вшить в пилот. Тут для каждой игры свои правила будут.
Черные линии некоторая координатная сетка. Задача добраться из синего в красный. Предполагается, что цена пути помимо значения расстояния может дополнительны иметь модификатор (на некоторых локациях невозможно использовать ездовых животных, например), либо задан константой (частные случаи).
Эскизы прикрепленных изображений
Пока черновой вариант. Путь считается только по расстоянию.
// Алгоритм A*
load_array %map C:\Users\abc\Desktop\map.txt // массив карта
load_array %coord C:\Users\abc\Desktop\coord.txt // координаты точек
set $start 4 // начальная точка
set $ending 1 // конечная
set #click 0 // делать ходы, клик по координатам точек. Нужна привязка в paint.
if size(%map) = 0
Log Массив с картой не найден.
Log Скрипт остановлен
stop_script
end_if
if size(%coord) = 0
Log Массив с координатами не найден.
Log Скрипт остановлен
stop_script
end_if
log clear
log mode compact
set size(%tmp)
set size(%open)
set size(%close)
set size(%curr)
set size(%resultarray)
// Позиция конечной точки на карте
for #i 1 size(%map)
if %map[#i 1] = $ending
set %ending [1 1] $ending
break
end_if
end_for
// Позиция начальной точки на карте
set %start [1 1] 7
for #i 1 size(%map)
if %map[#i 1] = $start
set %start [1 1] $start
break
end_if
end_for
// F, G, H, Текущая клетка, Родительская клетка, Текущая клетка:Родительская клетка
init_arr %open (1) 0 0 0 %start [1 1] %start [1 1] %start [1 1]:%start [1 1]
while 1 = 1
sort_array %open // сортировка по наименьшему F
set #sizeclose size(%close) + 1
init_arr %curr (1) %open [1 1] %open [1 2] %open [1 3] %open [1 4] %open [1 5] %open [1 6] // текущая клетка
init_arr %close (#sizeclose) %open [1 1] %open [1 2] %open [1 3] %open [1 4] %open [1 5] %open [1 6] // добавить в закрытый список
delete_array %open -1 // удалить с открытого списка
for #t 2 size(%map[1]) // проверяем все точки, в которые можно дойти из текущей
set #tmp %map [%curr[1 4] #t]
if #tmp != 0
set #x %map [%curr[1 4] #t] // текущая точка // %curr[1 4] - родитель
init_arr %tmp (1) #x : %curr [1 4]
set #sizeopen size(%open) + 1
set #g %curr [1 2] + round(point_distance(%coord[%curr [1 4] 1] %coord[#x 1])) // стоимость G
set #h round(point_distance(%coord[$ending 1] %coord[#x 1])) // стоимость H
set #f #g + #h // стоимость F
init_arr %tmp (1) #x : %curr [1 4]
init_arr %open (#sizeopen) #f #g #h #x %curr [1 4] %tmp [1]
else
break
end_if
end_for
if size(%open) = 0 or %curr [1 4] = %ending [1 1] // если открытый список пуст или конечная точка найдена
set size(%tmp)
set #tmp %curr [1 4]
if %curr [1 4] = %ending [1 1] // если конечная точка найдена
set #z #z + 1
set %tmp [#z] #tmp
// идём от конечной точки к начальной
while #tmp != $start
for #i 1 size(%close)
if %close [#i 4] = #tmp
set #zz #zz + 1
set #tmp %close[#i 5]
set #z #z + 1
set %tmp [#z] #tmp
break
end_if
end_for
end_while
// переворачиваем путь
set #z 0
for #i size(%tmp) 1 -1
set #z #z + 1
set %resultarray [#z] %tmp[#i 1]
end_for
// вывод в лог пути
for #i 1 size(%resultarray)
log %resultarray [#i] %coord[%resultarray [#i]]
if #click = 1
kleft %coord[%resultarray [#i]]
end_if
end_for
else
log Ходов нет
end_if
end_script
end_if
end_while
end_script
--lua
log ("clear") log ("mode compact")
-- ходы по диагонали, 0 - нет, 1 - да
angle = 0
-- параметры findcolor
find = {29, 25, 522, 516, 10, 10, "(0-16777215)", "%arr"}
-- создание карты
function Create_Map(startX, startY, endX, endY, stepX, stepY, color, array)
local z = 0
local a = findcolor(startX, startY, endX, endY, stepX, stepY, "(0-16777215)", "%arr")
if #arr > 0 then
local map = {}
for i = 1, ((endY - startY) / stepY) + 1 do
map[i] = {}
for j = 1, ((endX - startX) / stepX) + 1 do
z = z + 1
if tonumber(arr[z][3]) == 0 then
map[i][j] = {1, arr[z][1], arr[z][2]}
elseif tonumber(arr[z][3]) == 255 then
map[i][j] = {"A", arr[z][1], arr[z][2]}
elseif tonumber(arr[z][3]) == 16711680 then
map[i][j] = {"B", arr[z][1], arr[z][2]}
else
map[i][j] = {0, arr[z][1], arr[z][2]}
end
end
end
return map
end
end
-- поиск в массиве A и B
function index_of_A_B(arr, text)
local result = {}
for i = 1, #arr do
for j = 1, #arr[i] do
if arr[i][j][1] == text then
table.insert(result, {i, j})
end
end
end
return result
end
-- поиск в массиве
function index_of(arr, text)
local result = {}
for i = 1, #arr do
for j = 1, #arr[i] do
if arr[i][j] == text then
table.insert(result, {i, j})
end
end
end
return result
end
-- A*
function A_star(map)
local g, g1, h, f, tmp = 0, 0, 0, 0, 0
local open, close, curr, index, resultclose, resultopen, vector = {}, {}, {}, {}, {}, {}, {}
table.insert(vector, {-1, -1, 0, 1, 1, 1, 0, -1})
table.insert(vector, {0, 1, 1, 1, 0, -1, -1, -1})
table.insert(open, {0, 0, 0, 0, start [1][1], start [1][2], start [1][1]..":"..start [1][2], start [1][1], start [1][2]})
while 1 == 1 do
table.sort (open, function (a, b) return (a[1] < b[1]) end)
curr [1] = {open [1][1], open [1][2], open [1][3], open [1][4], open [1][5], open [1][6], open [1][7], open [1][8], open [1][9]}
table.insert(close, {open [1][1], open [1][2], open [1][3], open [1][4], open [1][5], open [1][6], open [1][7], open [1][8], open [1][9]})
table.remove (open, 1)
for i = 1, 8 do
if angle == 1 or i%2 == 1 then
local x, y = curr[1][5] + vector[1][i], curr[1][6] + vector[2][i]
resultclose = index_of(close, x..":"..y)
if x > 0 and y > 0 and x <= #map[i] and y <= #map then
if (map[x][y][1] == 0 or map[x][y][1] == "B") and #resultclose == 0 then
resultopen = index_of(open, x..":"..y)
if #resultopen == 0 then
if i%2 == 1 then g = curr[1][2] + 10 else g = curr[1][2] + 14 end
h = (math.abs(x - ending[1][1]) + math.abs(y - ending[1][2])) * 10
f = g + h
table.insert(open, {f, g, h, i, x, y, x..":"..y, curr[1][5], curr[1][6]})
else
tmp = resultopen [1][1]
g1 = open[tmp][2]
if i%2 == 1 then g = curr[1][2] + 10 else g = curr[1][2] + 14 end
if g < g1 then
h = (math.abs(x - ending[1][1]) + math.abs(y - ending[1][2])) * 10
f = g + h
table.insert(open, {f, g, h, i, x, y, x..":"..y, curr[1][5], curr[1][6]})
end
end
end
end
end
end
if (curr [1][5] == ending [1][1] and curr [1][6] == ending [1][2]) or #open == 0 then
break
end
end
local pathAB, tmp, path = {}, {}, {}
tmp [1] = {ending[1][1], ending[1][2]}
table.insert(tmp, {close[#close][8], close[#close][9], close[#close][4]})
while tmp[#tmp][1] ~= start[1][1] or tmp[#tmp][2] ~= start[1][2] do
pathAB = index_of(close, tmp[#tmp][1]..":"..tmp[#tmp][2])
table.insert (tmp, {close[pathAB[1][1]][8], close[pathAB[1][1]][9], close[pathAB[1][1]][4]})
end
for i = #tmp, 1, -1 do
table.insert (path, {map[tmp[i][1]][tmp[i][2]][2], map[tmp[i][1]][tmp[i][2]][3]})
end
return path
end
-- создание карты
map = Create_Map(find[1],find[2],find[3],find[4],find[5],find[6],find[7],find[8])
-- поиск точки A в массиве map
start = {}
start = index_of_A_B(map, "A")
-- поиск точки B в массиве map
ending = {}
ending = index_of_A_B(map, "B")
-- поиск пути
if #start > 0 and #ending > 0 then
path = {}
path = A_star(map)
-- ход
for i = 1, #path do
kleft (path[i][1], path[i][2])
end
elseif #start == 0 then
log ("Точка A не найдена")
else
log ("Точка B не найдена")
end
Производительность тестил?
--lua
log ("clear") log ("mode compact")
-- ходы по диагонали, 0 - нет, 1 - да
angle = 0
-- параметры findcolor
find = {29, 25, 522, 516, 10, 10, "(0-16777215)", "%arr"}
-- создание карты
function Create_Map(startX, startY, endX, endY, stepX, stepY, color, array)
local z = 0
local a = findcolor(startX, startY, endX, endY, stepX, stepY, "(0-16777215)", "%arr")
if #arr > 0 then
local map = {}
for i = 1, ((endY - startY) / stepY) + 1 do
map[i] = {}
for j = 1, ((endX - startX) / stepX) + 1 do
z = z + 1
if tonumber(arr[z][3]) == 0 then
map[i][j] = {1, arr[z][1], arr[z][2]}
elseif tonumber(arr[z][3]) == 255 then
map[i][j] = {"A", arr[z][1], arr[z][2]}
-- точка A в массиве map
start = {}
start[1] = {i, j}
elseif tonumber(arr[z][3]) == 16711680 then
map[i][j] = {"B", arr[z][1], arr[z][2]}
-- точка A в массиве map
ending = {}
ending[1] = {i, j}
else
map[i][j] = {0, arr[z][1], arr[z][2]}
end
end
end
return map
end
end
-- поиск в массиве
function index_of(arr, text)
local result = {}
for i = 1, #arr do
if arr[i][7] == text then
table.insert(result, {i, 7})
end
end
return result
end
-- A*
function A_star(map)
local g, g1, h, f, tmp = 0, 0, 0, 0, 0
local open, close, curr, index, resultclose, resultopen, vector = {}, {}, {}, {}, {}, {}, {}
table.insert(vector, {-1, -1, 0, 1, 1, 1, 0, -1})
table.insert(vector, {0, 1, 1, 1, 0, -1, -1, -1})
table.insert(open, {0, 0, 0, 0, start [1][1], start [1][2], start [1][1]..":"..start [1][2], start [1][1], start [1][2]})
while 1 == 1 do
table.sort (open, function (a, b) return (a[1] < b[1]) end)
curr [1] = {open [1][1], open [1][2], open [1][3], open [1][4], open [1][5], open [1][6], open [1][7], open [1][8], open [1][9]}
table.insert(close, {open [1][1], open [1][2], open [1][3], open [1][4], open [1][5], open [1][6], open [1][7], open [1][8], open [1][9]})
table.remove (open, 1)
for i = 1, 8 do
if angle == 1 or i%2 == 1 then
local x, y = curr[1][5] + vector[1][i], curr[1][6] + vector[2][i]
resultclose = index_of(close, x..":"..y)
if x > 0 and y > 0 and x <= #map[i] and y <= #map then
if (map[x][y][1] == 0 or map[x][y][1] == "B") and #resultclose == 0 then
resultopen = index_of(open, x..":"..y)
if #resultopen == 0 then
if i%2 == 1 then g = curr[1][2] + 10 else g = curr[1][2] + 14 end
h = (math.abs(x - ending[1][1]) + math.abs(y - ending[1][2])) * 10
f = g + h
table.insert(open, {f, g, h, i, x, y, x..":"..y, curr[1][5], curr[1][6]})
else
tmp = resultopen [1][1]
g1 = open[tmp][2]
if i%2 == 1 then g = curr[1][2] + 10 else g = curr[1][2] + 14 end
if g < g1 then
h = (math.abs(x - ending[1][1]) + math.abs(y - ending[1][2])) * 10
f = g + h
table.insert(open, {f, g, h, i, x, y, x..":"..y, curr[1][5], curr[1][6]})
end
end
end
end
end
end
if (curr [1][5] == ending [1][1] and curr [1][6] == ending [1][2]) or #open == 0 then
break
end
end
local pathAB, tmp, path = {}, {}, {}
tmp [1] = {ending[1][1], ending[1][2]}
table.insert(tmp, {close[#close][8], close[#close][9], close[#close][4]})
while tmp[#tmp][1] ~= start[1][1] or tmp[#tmp][2] ~= start[1][2] do
pathAB = index_of(close, tmp[#tmp][1]..":"..tmp[#tmp][2])
table.insert (tmp, {close[pathAB[1][1]][8], close[pathAB[1][1]][9], close[pathAB[1][1]][4]})
end
for i = #tmp, 1, -1 do
table.insert (path, {map[tmp[i][1]][tmp[i][2]][2], map[tmp[i][1]][tmp[i][2]][3]})
end
return path
end
-- создание карты
map = Create_Map(find[1],find[2],find[3],find[4],find[5],find[6],find[7],find[8])
-- поиск пути
if #start > 0 and #ending > 0 then
path = {}
path = A_star(map)
-- ход
for i = 1, #path do
kleft (path[i][1], path[i][2])
end
elseif #start == 0 then
log ("Точка A не найдена")
else
log ("Точка B не найдена")
end
-- поиск в массиве
function index_of(arr, text)
local result = {}
for i = 1, #arr do
for j = 1, #arr[i] do
if arr[i][j] == text then
table.insert(result, {i, j})
end
end
end
return result
end
Вроде понял.
--lua
time_start = os.clock()
-- какой-то код
time_end = os.clock() - time_start
log (time_end) -- время выполнения
--lua
time_start = os.clock()
log ("clear") log ("mode compact")
-- ходы по диагонали, 0 - нет, 1 - да
angle = 0
-- параметры findcolor
find = {5, 5, 620, 620, 1, 1, "(0-16777215)", "%arr"} -- большой лабиринт
--find = {29, 25, 522, 516, 10, 10, "(0-16777215)", "%arr"} -- маленький лабиринт
-- создание карты
function Create_Map(startX, startY, endX, endY, stepX, stepY, color, array)
local z = 0
local a = findcolor(startX, startY, endX, endY, stepX, stepY, "(0-16777215)", "%arr")
if #arr > 0 then
local map = {}
for i = 1, ((endY - startY) / stepY) + 1 do
map[i] = {}
for j = 1, ((endX - startX) / stepX) + 1 do
z = z + 1
if tonumber(arr[z][3]) == 0 then
map[i][j] = {1, arr[z][1], arr[z][2]}
elseif tonumber(arr[z][3]) == 255 then
map[i][j] = {"A", arr[z][1], arr[z][2]}
-- точка A в массиве map
start = {}
start[1] = {i, j}
elseif tonumber(arr[z][3]) == 16711680 then
map[i][j] = {"B", arr[z][1], arr[z][2]}
-- точка A в массиве map
ending = {}
ending[1] = {i, j}
else
map[i][j] = {0, arr[z][1], arr[z][2]}
end
end
end
return map
end
end
-- A*
function A_star(map)
local g, g1, h, f, tmp = 0, 0, 0, 0, 0
local open, close, curr, index, resultclose, resultopen, vector, close_map, open_map = {}, {}, {}, {}, {}, {}, {}, {}, {}
for i = 1, #map do
close_map [i] = {}
end
for i = 1, #map do
open_map [i] = {}
for j = 1, #map [i] do
open_map[i][j] = {}
end
end
table.insert(vector, {-1, -1, 0, 1, 1, 1, 0, -1})
table.insert(vector, {0, 1, 1, 1, 0, -1, -1, -1})
table.insert(open, {0, 0, 0, 0, start [1][1], start [1][2], start [1][1]..":"..start [1][2], start [1][1], start [1][2]})
while 1 == 1 do
table.sort (open, function (a, b) return (a[1] < b[1]) end)
curr [1] = {open [1][1], open [1][2], open [1][3], open [1][4], open [1][5], open [1][6], open [1][7], open [1][8], open [1][9]}
table.insert(close, {open [1][1], open [1][2], open [1][3], open [1][4], open [1][5], open [1][6], open [1][7], open [1][8], open [1][9]})
close_map [open [1][5]][open [1][6]] = 1
table.remove (open, 1)
for i = 1, 8 do
if angle == 1 or i%2 == 1 then
local x, y = curr[1][5] + vector[1][i], curr[1][6] + vector[2][i]
if x > 0 and y > 0 and x <= #map[i] and y <= #map then
if (map[x][y][1] == 0 or map[x][y][1] == "B") and close_map[x][y] == nil then
if open_map[x][y][1] == nil then
if i%2 == 1 then g = curr[1][2] + 10 else g = curr[1][2] + 14 end
h = (math.abs(x - ending[1][1]) + math.abs(y - ending[1][2])) * 10
f = g + h
table.insert(open, {f, g, h, i, x, y, x..":"..y, curr[1][5], curr[1][6]})
open_map[x][y] = {i, curr[1][5], curr[1][6]}
else
g1 = open_map[x][y][2]
if i%2 == 1 then g = curr[1][2] + 10 else g = curr[1][2] + 14 end
if g < g1 then
h = (math.abs(x - ending[1][1]) + math.abs(y - ending[1][2])) * 10
f = g + h
table.insert(open, {f, g, h, i, x, y, x..":"..y, curr[1][5], curr[1][6]})
open_map[x][y] = {i, curr[1][5], curr[1][6]}
end
end
end
end
end
end
if (curr [1][5] == ending [1][1] and curr [1][6] == ending [1][2]) or #open == 0 then
break
end
end
local pathAB, tmp, path = {}, {}, {}
tmp [1] = {ending[1][1], ending[1][2]}
table.insert(tmp, {close[#close][8], close[#close][9], close[#close][4]})
while tmp[#tmp][1] ~= start[1][1] or tmp[#tmp][2] ~= start[1][2] do
table.insert (tmp,{open_map[tmp[#tmp][1]][tmp[#tmp][2]][2],open_map[tmp[#tmp][1]][tmp[#tmp][2]][3], open_map[tmp[#tmp][1]][tmp[#tmp][2]][1]})
end
for i = #tmp, 1, -1 do
table.insert (path, {map[tmp[i][1]][tmp[i][2]][2], map[tmp[i][1]][tmp[i][2]][3], map[tmp[i][1]][tmp[i][2]][1]})
end
return path
end
-- создание карты
map = Create_Map(find[1],find[2],find[3],find[4],find[5],find[6],find[7],find[8])
time_create_map = os.clock() - time_start
log ("Создание карты:".." "..time_create_map)
-- поиск пути
if #start > 0 and #ending > 0 then
path = {}
path = A_star(map)
time_create_path = os.clock() - time_start - time_create_map
log ("Поиск пути:".." "..time_create_path)
-- ход
for i = 1, #path do
kleft (path[i][1], path[i][2])
end
time_paint_path = os.clock() - time_start - time_create_path - time_create_map
log ("Рисование маршрута:".." "..time_paint_path)
log ("Всего затрачено времени:".." "..time_create_map + time_create_path + time_paint_path)
elseif #start == 0 then
log ("Точка A не найдена")
else
log ("Точка B не найдена")
end
На асме невозможно написать коряво,ибо кто пишет на асме не могут писать коряво. А если написано коряво, то это написано не на асме.
Да и как бы асм тут причем ? Тем более в контексте пилота и луа.
думал на ссд будет быстрее, оказалось ниочинь)
Маршрут рисует на 2сек быстрее
Диск не влияет. Скорее всего только процессор, хотя тоже не понятно.
Создаётся и рисуется карта одинаково по времени, а вот поиск пути отличается:
i7 2600k 4.4 Ггц (разгон с 3.4 Ггц), ddr3 1600, win7 = 13 секунд.
i7 7700k 4.2 Ггц, dd4 2133, win10 = 4 секунды.
Прикольно...а можно ли подобрать путь к выходам?
https://pp.userapi.com/c840138/v840138958/93b29/bQx9dXpJQyM.jpg
http://www.policyalmanac.org/games/aStarTutorial_rus.htm - ОПИСАНИЕ НЕ ДОСТУПНО!
В bmp или png картинку лабиринта скиньте.
пытался для игры сделать поиск пути и получилась прикольная штука, он не ищет кратчайший путь, просто пробегает по дорожке, пока примитивно но всё же
--lua
local startX, startY = 960, 520 --начало пути
local nextX, nextY = 960, 520 --начало пути
local ending = 0
local fat = 5 -- "толщина дорожки"
local pcolor = 0 -- цвет дорожки (как запихнуть в переменную набор цветов или диапазон я не знаю)
move (startX, startY)
wait (50)
kleft_down (startX, startY)
repeat
local path = findcolor(startX - fat, startY - fat, startX + fat, startY + fat, pcolor, '%p', 2, -1, 0)
if path then
for i = 1, path do
dist = math.sqrt((nextX - p[i][1])^2 + (nextY - p[i][2])^2)
if i == 1 then
max = dist
end
if max <= dist then
max = dist
nextX2 = p[i][1]
nextY2 = p[i][2]
end
end
nextX, nextY = startX, startY
startX, startY = nextX2, nextY2
ending = math.sqrt((startX - nextX)^2 + (startY - nextY)^2)
move (startX, startY)
end
until ending < max * 0.4 --должен дойти до конца дорожки
Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)