Skip to content

Instantly share code, notes, and snippets.

@Koshimizu-Takehito
Created July 7, 2024 04:38
Show Gist options
  • Save Koshimizu-Takehito/cce43b17f91bc71b0ef855c279b69316 to your computer and use it in GitHub Desktop.
Save Koshimizu-Takehito/cce43b17f91bc71b0ef855c279b69316 to your computer and use it in GitHub Desktop.
穴掘り法(Aldous-Broder Algorithm)を使用した迷路生成ロジック
import SwiftUI
import Observation
struct ContentView: View {
@State private var model = MazeObject(width: 39, height: 39)
@State private var resetID = UUID()
@State private var disabled = false
var body: some View {
VStack {
Circle()
.foregroundStyle(BackgroundStyle())
.overlay {
Grid(alignment: .center, horizontalSpacing: 0, verticalSpacing: 0) {
ForEach(0..<model.width, id: \.self) { i in
GridRow(alignment: .center) {
ForEach(0..<model.height, id: \.self) { j in
model.grid[i][j] ? Color.white : Color.black
}
}
}
}
}
.task(id: resetID) {
await model.generate()
disabled = false
}
.padding()
Button("Reset") {
disabled = true
resetID = .init()
}
.font(.title2)
.fontWeight(.semibold)
.disabled(disabled)
}
}
}
/// 穴掘り法(Aldous-Broder Algorithm)を使用した迷路生成ロジック
@MainActor
@Observable
final class MazeObject {
let width: Int
let height: Int
var grid: [[Bool]]
init(width: Int, height: Int) {
self.width = width
self.height = height
grid = Array(repeating: Array(repeating: false, count: width), count: height)
}
func generate() async {
await MainActor.run {
grid = Array(repeating: Array(repeating: false, count: width), count: height)
}
let start = SIMD2(
(Int.random(in: 0..<(width / 2)) * 2) + 1,
(Int.random(in: 0..<(height / 2)) * 2) + 1
)
var stack = [SIMD2<Int>]()
stack.append(start)
await MainActor.run {
grid[start] = true
}
let directions: [SIMD2] = [.init(0, 2), .init(2, 0), .init(0, -2), .init(-2, 0)]
while !stack.isEmpty {
let current = stack.last!
var moved = false
for direction in directions.shuffled() {
let next = current + direction
if isValid(next) {
await MainActor.run {
grid[next] = true
grid[current + direction / 2] = true
}
stack.append(next)
moved = true
break
}
}
if !moved {
stack.removeLast()
}
}
}
func isValid(_ cell: SIMD2<Int>) -> Bool {
if cell.x > 0 && cell.x < width-1 && cell.y > 0 && cell.y < height-1 {
return !grid[cell]
}
return false
}
}
extension SIMD2<Int> {
static func+(_ lhs: Self, _ rhs: Self) -> Self {
.init(lhs.x + rhs.x, lhs.y + rhs.y)
}
static func/(_ lhs: Self, _ rhs: Int) -> Self {
.init(lhs.x / rhs, lhs.y / rhs)
}
}
extension [[Bool]] {
subscript(_ p: SIMD2<Int>) -> Bool {
get { self[p.y][p.x] }
set { self[p.y][p.x] = newValue }
}
}
#Preview {
ContentView()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment