Maze generation: Difference between revisions

m
→‎{{header|Tcl}}: more tinkering, making this code a class
m (→‎{{header|Tcl}}: tinkering)
m (→‎{{header|Tcl}}: more tinkering, making this code a class)
Line 234:
=={{header|Tcl}}==
{{trans|Javascript}}
<lang tcl>package require TclOO; # Or Tcl 8.56
 
# Helper to pick a random number
proc rand n {expr {int(rand() * $n)}}
# Helper to pick a random element of a list
proc pick list {lindex $list [rand [llength $list]]}
lindex $list [rand [llength $list]]
}
# Helper _function_ to index into a list of lists
proc tcl::mathfunc::idx {v x y} {lindex $v $x $y}
# Helper to write into a list of lists (with offsets)
proc unvisited= {x y value} {
upvar 1 unvisited u
lset u [expr {$x+1}] [expr {$y+1}] $value
}
 
oo::class create maze {
# Maze builder; returns a dictionary
variable x y horiz verti
proc maze {y x} {
constructor {width height} {
set n [expr {$x * $y - 1}]
set y $width
if {$n < 0} {error "illegal maze dimensions"}
set x $height
set horiz [set verti [lrepeat [expr {$x+1}] [lrepeat [expr {$y+1}] 0]]]
 
set unvisited [lrepeat [expr {$x+2}] [lrepeat [expr {$y+2}] 0]]
lappend stack [ set heren [list [randexpr {$x] [rand* $y]] - 1}]
for if {set$n j< 0} {$jerror <"illegal $x}maze {incr jdimensions"} {
forset horiz {[set kverti 0}[lrepeat [expr {$kx+1}] <[lrepeat [expr {$y+1}] {incr k} {0]]]
set unvisited= $j $k[lrepeat [expr {$herex+2}] ne[lrepeat [listexpr {$jy+2}] $k0]}]
# Helper to write into a list of lists (with offsets)
proc unvisited= {x y value} {
upvar 1 unvisited u
lset u [expr {$x+1}] [expr {$y+1}] $value
}
 
}
lappend stack [set here [list [rand $x] [rand $y]]]
for {set j while0} {0$j < $nx} {incr j} {
for {set nk [expr0} {$xk *< $y} -{incr 1k}] {
lassign $here hx hy
unvisited= $j $k [expr {$here ne [list $j $k]}]
set neighbours {}
foreach {dx dy} {1 0 0 1 -1 0 0 -1} {
if {idx($unvisited, $hx+$dx+1, $hy+$dy+1)} {
lappend neighbours [list [expr {$hx+$dx}] [expr {$hy+$dy}]]
}
}
if {[llength $neighbours]} {
while {0 < $n} {
lassign [set here [pick $neighbours]] nx ny
unvisited=lassign $nxhere $nyhx 0hy
ifset neighbours {$nx == $hx} {
foreach {dx dy} {1 0 0 1 -1 0 0 -1} {
lset horiz $nx [expr {min($ny, $hy)}] 1
if {idx($unvisited, $hx+$dx+1, $hy+$dy+1)} {
lappend neighbours [list [expr {$hx+$dx}] [expr {$hy+$dy}]]
}
}
if {[llength $neighbours]} {
lassign [set here [pick $neighbours]] nx ny
unvisited= $nx $ny 0
if {$nx == $hx} {
lset horiz $nx [expr {min($ny, $hy)}] 1
} else {
lset verti [expr {min($nx, $hx)}] $ny 1
}
lappend stack $here
incr n -1
} else {
set here [lindex $stack end]
lset verti [expr {min($nx, $hx)}] $ny 1
set stack [lrange $stack 0 end-1]
}
lappend stack $here
incr n -1
} else {
set here [lindex $stack end]
set stack [lrange $stack 0 end-1]
}
}
return [dict create x $x y $y horiz $horiz verti $verti]
}
 
# Maze displayer; takes a maze dictionary, returns a string
proc display method view {m} {
set text {}
dict with m {
for {set j 0} {$j < $x*2+1} {incr j} {
set line {}
Line 315 ⟶ 317:
}
}
return [join $text \n]
}
return [join $text \n]
}
 
# Demonstration
putsmaze [displaycreate [mazem 11 8]]</lang>
puts [m view]</lang>
Output:
<pre>
Anonymous user