Roblox · Дополнительное
Каждый раз новый лабиринт: скрипт сам ставит стены так, что от входа до выхода всегда есть путь. Дошёл до выхода — +1 в таблице и новый лабиринт.
Синим — что нужно создать.
Workspace └─ Maze (Model) ├─ Floor (Part) — пол: размер = Cells × CellSize ├─ Entrance (Part) — площадка у входа ├─ Finish (Part) — выход, CanCollide выкл. ├─ Walls (Folder) — стены создаёт скрипт ├─ Configuration (Configuration) — Cells, CellSize, WallHeight └─ MazeServer (Script)
Где: Workspace → Maze · Script
Зачем: Строит лабиринт и пересобирает после выхода.
-- игроки
local Players = game:GetService("Players")
-- модель Maze
local maze = script.Parent
-- Cells, CellSize, WallHeight
local config = maze:WaitForChild("Configuration")
-- пол — по нему считаются клетки
local floor = maze:WaitForChild("Floor")
-- выход
local finish = maze:WaitForChild("Finish")
-- куда вернуть после выхода
local entrance = maze:WaitForChild("Entrance")
-- папка стен
local walls = maze:WaitForChild("Walls")
-- лабиринт пересобирается
local busy = false
-- стена по координатам относительно центра пола
local function Wall(x, z, sizeX, sizeZ)
-- высота
local h = config.WallHeight.Value
-- деталь
local wall = Instance.new("Part")
-- не падает
wall.Anchored = true
-- размер
wall.Size = Vector3.new(sizeX, h, sizeZ)
-- стоит на полу
wall.CFrame = floor.CFrame * CFrame.new(x, floor.Size.Y / 2 + h / 2, z)
-- кирпич
wall.Material = Enum.Material.Brick
-- цвет
wall.Color = Color3.fromRGB(150, 90, 70)
-- в папку
wall.Parent = walls
-- конец функции
end
-- новый лабиринт
local function Generate()
-- старые стены убираем
walls:ClearAllChildren()
-- клеток в ряду и размер клетки
local n, s = config.Cells.Value, config.CellSize.Value
-- посещена ли клетка, есть ли стена справа и снизу
local visited, right, down = {}, {}, {}
-- каждый столбец
for x = 1, n do
-- пустые
visited[x], right[x], down[x] = {}, {}, {}
-- сначала все стены стоят
for z = 1, n do right[x][z], down[x][z] = true, true end
-- конец перебора
end
-- путь копателя: начинаем с угла
local stack = {{1, 1}}
-- угол посещён
visited[1][1] = true
-- пока есть куда возвращаться
while #stack > 0 do
-- где копатель
local x, z = stack[#stack][1], stack[#stack][2]
-- непосещённые соседи
local options = {}
-- четыре стороны
for _, d in ipairs({{1, 0}, {-1, 0}, {0, 1}, {0, -1}}) do
-- сосед
local nx, nz = x + d[1], z + d[2]
-- в лабиринте и не посещён
if nx >= 1 and nx <= n and nz >= 1 and nz <= n and not visited[nx][nz] then table.insert(options, {nx, nz}) end
-- конец перебора
end
-- тупик
if #options == 0 then
-- шаг назад
table.remove(stack)
-- можно копать
else
-- случайный сосед
local nx, nz = table.unpack(options[math.random(1, #options)])
-- ломаем стену между клетками
if nx > x then right[x][z] = false elseif nx < x then right[nx][z] = false elseif nz > z then down[x][z] = false else down[x][nz] = false end
-- сосед посещён
visited[nx][nz] = true
-- копатель идёт туда
table.insert(stack, {nx, nz})
-- конец проверки
end
-- конец цикла: все клетки соединены
end
-- половина лабиринта
local half = n * s / 2
-- каждая клетка
for x = 1, n do
-- …
for z = 1, n do
-- центр клетки
local cx, cz = (x - 0.5) * s - half, (z - 0.5) * s - half
-- стена справа
if right[x][z] and x < n then Wall(cx + s / 2, cz, 1, s + 1) end
-- стена снизу
if down[x][z] and z < n then Wall(cx, cz + s / 2, s + 1, 1) end
-- внешняя стена сверху; в первой клетке — вход
if z == 1 and x ~= 1 then Wall(cx, -half, s + 1, 1) end
-- внешняя стена снизу; в последней — выход
if z == n and x ~= n then Wall(cx, half, s + 1, 1) end
-- конец строки
end
-- левая внешняя стена
Wall(-half, (x - 0.5) * s - half, 1, s + 1)
-- правая внешняя стена
Wall(half, (x - 0.5) * s - half, 1, s + 1)
-- конец перебора
end
-- выход — за последней клеткой
finish.CFrame = floor.CFrame * CFrame.new(half - s / 2, floor.Size.Y / 2 + 0.6, half + s / 2)
-- конец функции
end
-- кто-то дошёл
finish.Touched:Connect(function(hit)
-- игрок
local player = Players:GetPlayerFromCharacter(hit.Parent)
-- не игрок или уже пересобираем
if not player or busy then return end
-- один раз
busy = true
-- таблица справа
local stats = player:FindFirstChild("leaderstats") or Instance.new("Folder")
-- имя
stats.Name = "leaderstats"
-- в игрока
stats.Parent = player
-- пройдено лабиринтов
local mazes = stats:FindFirstChild("Mazes") or Instance.new("IntValue")
-- имя
mazes.Name = "Mazes"
-- в таблицу
mazes.Parent = stats
-- +1
mazes.Value += 1
-- всех, кто внутри, — ко входу
for _, other in ipairs(Players:GetPlayers()) do
-- ко входу
if other.Character then other.Character:PivotTo(entrance.CFrame + Vector3.new(0, 3, 0)) end
-- конец перебора
end
-- новый лабиринт
Generate()
-- пауза
task.wait(1)
-- готов
busy = false
-- конец функции
end)
-- первый лабиринт при запуске
Generate()Запусти Play (или Run) и убедись: