Mam stół (tablica 2d), c x r. Musisz wygenerować losowy wzorzec połączonych komórek w środku. Bez samokrytycyzmu i bez ruchów ukośnych. Zobacz powiązane zdjęcie na przykład. ex. 1 с = 6, r = 7, wzór jest pokazany w liczbach.jaki jest najlepszy sposób wygenerowania losowego wzoru wewnątrz tabeli
Napisałem do tego funkcję i działa dobrze, ale szukam ciężkiej optymalizacji. W poniższym kodzie widać, że jeśli wzór przechodzi w ślepy zaułek, po prostu odbudowuje się od samego początku. Jest to bardzo nieefektywne, jeśli długość wzoru jest bliska lub równa liczbie komórek, c * r (42 w przykładzie). Potrzebne jest więc pewne inteligentne rozwiązanie, takie jak przesuwanie całego wzoru symetrycznie, gdy zabraknie mu możliwych ruchów lub dodanie funkcji analitycznych do funkcji, aby nigdy nie znalazły się w ślepych uliczkach. Ponownie, dla niskich wartości c, r i patternLength mój przykład działa dobrze, ale szukam algorytmicznej doskonałości i wysokiej wydajności nawet na dość wysokich liczbach.
function ClassLogic:generatePattern()
--[[ subfunctions ]]
--choosing next point for the pattern
local move = function(seq)
--getting the last sequence point
local last = seq[#seq]
-- checking the nearness of walls
local
wallLeft,
wallRight,
wallUp,
wallDown =
(last.c==1),
(last.c==config.tableSize.c),
(last.r==1),
(last.r==config.tableSize.r)
-- checking the nearness of already sequenced points
local
spLeft,
spRight,
spUp,
spDown =
(utilities.indexOfTable(seq, { c = last.c - 1, r = last.r })~=-1),
(utilities.indexOfTable(seq, { c = last.c + 1, r = last.r })~=-1),
(utilities.indexOfTable(seq, { c = last.c, r = last.r - 1 })~=-1),
(utilities.indexOfTable(seq, { c = last.c, r = last.r + 1 })~=-1)
local leftRestricted = (wallLeft or spLeft)
local rightRestricted = (wallRight or spRight)
local upRestricted = (wallUp or spUp)
local downRestricted = (wallDown or spDown)
if (leftRestricted and rightRestricted and upRestricted and downRestricted) then
-- dead end
print('d/e')
return nil
else
-- go somewhere possible
local possibleDirections = {}
if (not leftRestricted) then possibleDirections[#possibleDirections+1] = 1 end
if (not rightRestricted) then possibleDirections[#possibleDirections+1] = 2 end
if (not upRestricted) then possibleDirections[#possibleDirections+1] = 3 end
if (not downRestricted) then possibleDirections[#possibleDirections+1] = 4 end
local direction = possibleDirections[math.random(1, #possibleDirections)]
if (direction==1) then
--next point is left
return { c = last.c - 1, r = last.r }
elseif (direction==2) then
--next point is right
return { c = last.c + 1, r = last.r }
elseif (direction==3) then
--next point is up
return { c = last.c, r = last.r - 1 }
elseif (direction==4) then
--next point is down
return { c = last.c, r = last.r + 1 }
end
end
end
--[[ subfunctions end ]]
-- choose random entry point
local entry = { c = math.random(1, config.tableSize.c),
r = math.random(1, config.tableSize.r) }
-- start points sequence
local pointSequence = { [1] = entry }
-- building the pattern
local succeed = false
while (not succeed) do
for i = 2, self.patternLength do
local nextPoint = move(pointSequence)
if (nextPoint~=nil) then
pointSequence[i] = nextPoint
if (i==self.patternLength) then succeed = true end
else
pointSequence = { [1] = entry }
break
end
end
end
return pointSequence
end
Wszelkie pomysły lub podejścia do tego, jak mogłoby to zostać zrealizowane, byłyby wysoko cenione. Może jakiś rekurencyjny backtracker, algorytm ścieżki lub algorytm "spacer"?
Jeśli osiągnęły ślepy zaułek można użyć https://en.wikipedia.org/wiki/Backtracking ponownie cofnąć czynności zamiast począwszy od samego początku. – MrSmith42
Czy musi być idealnie przypadkowa wśród wszystkich takich spacerów? Większość "poprawek, które będą nieco większe", nie gwarantuje tego. – btilly
@ MrSmith42 Tak, myślałem o tym. Wydaje się jednak, że wymaga to dość inteligentnej analizy. Ile operacji należy wykonać? Czy to gwarantuje, że wzór będzie wyglądał dobrze po tym? Które kierunki powinny być użyte zamiast tego (czy algorytm powinien zapamiętać wybory)? Itd. Może to poważnie wpłynąć na wydajność. (c = 1000, r = 1000, patternLength = 1000000, i musimy obliczyć wszystkie możliwe rozwiązania). W rzeczywistości, jeśli patternLength == c * r lub bardzo blisko niego, myślę, że to powinno być udoskonalone, a wzorzec powinien działać z pewnymi korektami losowymi do _avoid_ ślepych zaułków zamiast z użyciem cofnięć. – Aleksei