Maze generation: Difference between revisions
Content added Content deleted
m (→simpler version of above: changed the wording in the REXX section header.) |
m (→{{header|REXX}}: added/changed whitespace and comments, simplified some statements.) |
||
Line 4,513: | Line 4,513: | ||
In order to preserve the aspect ratio (for most display terminals), several '''changestr''' invocations and |
In order to preserve the aspect ratio (for most display terminals), several '''changestr''' invocations and |
||
<br>some other instructions were added to increase the horizontal dimension (cell size). |
<br>some other instructions were added to increase the horizontal dimension (cell size). |
||
<lang rexx>/*REXX program |
<lang rexx>/*REXX program generates and displays a rectangular solvable maze (any size).*/ |
||
height=0; @.=0 /*default for all cells visited.*/ |
height=0; @.=0 /*default for all cells visited. */ |
||
parse arg rows cols seed . /*allow user to specify maze size*/ |
parse arg rows cols seed . /*allow user to specify the maze size. */ |
||
if rows='' | rows==',' then rows=19 /*No rows given? |
if rows='' | rows==',' then rows=19 /*No rows given? Then use the default.*/ |
||
if cols='' | cols==',' then cols=19 /* |
if cols='' | cols==',' then cols=19 /* " cols " ? " " " " */ |
||
if seed\=='' then call random ,,seed /*use a seed for repeatability. |
if seed\=='' then call random ,,seed /*use a random seed for repeatability.*/ |
||
call buildRow '┌'copies('~┬',cols-1)'~┐' /* |
call buildRow '┌'copies('~┬',cols-1)'~┐' /*construct top edge of the maze. */ |
||
/* |
/* [↓] construct the maze's grid. */ |
||
do r=1 for rows; _=; __=; hp= '|'; hj='├' |
do r=1 for rows; _=; __=; hp= '|'; hj='├' |
||
do c=1 for cols; _= _||hp'1'; __=__||hj'~'; hj='┼'; hp='│' |
do c=1 for cols; _= _||hp'1'; __=__||hj'~'; hj='┼'; hp='│' |
||
end /*c*/ |
end /*c*/ |
||
call buildRow _'│' |
call buildRow _'│' /*construct the right edge of cells.*/ |
||
if r\==rows then call buildRow __'┤' |
if r\==rows then call buildRow __'┤' /* " " " " " maze. */ |
||
end /*r*/ |
end /*r*/ |
||
call buildRow '└'copies('~┴',cols-1)'~┘' /* |
call buildRow '└'copies('~┴',cols-1)'~┘' /*construct the bottom maze edge.*/ |
||
r!=random(1,rows)*2; c!=random(1,cols)*2; @.r!.c!=0 /*choose 1st cell*/ |
r!=random(1,rows)*2; c!=random(1,cols)*2; @.r!.c!=0 /*choose the 1st cell.*/ |
||
/* [↓] traipse through the maze.*/ |
/* [↓] traipse through the maze. */ |
||
do forever; n=hood(r!,c!); if n==0 then if \ |
do forever; n=hood(r!,c!); if n==0 then if \fCell() then leave |
||
call ?; @._r._c=0 /*get the (next) direction to go.*/ |
call ?; @._r._c=0 /*get the (next) maze direction to go. */ |
||
ro=r!; co=c!; r!=_r; c!=_c /*save original cell coordinates.*/ |
ro=r!; co=c!; r!=_r; c!=_c /*save original maze cell coordinates. */ |
||
?.zr=?.zr%2; ?.zc=?.zc%2 /*get the row and cell directions*/ |
?.zr=?.zr%2; ?.zc=?.zc%2 /*get the maze row and cell directions.*/ |
||
rw=ro+?.zr; cw=co+?.zc /*calculate the next row and |
rw=ro+?.zr; cw=co+?.zc /*calculate the next row and column. */ |
||
@.rw.cw= |
@.rw.cw=. /*mark the maze cell as being visited. */ |
||
end /*forever*/ |
end /*forever*/ |
||
do r=1 for height; |
do r=1 for height; _= /*display the maze. */ |
||
do c=1 for cols*2 + 1; |
do c=1 for cols*2 + 1; _=_ || @.r.c; end /*c*/ |
||
if \(r//2) then _=translate(_, '\', |
if \(r//2) then _=translate(_, '\', .) /*trans to backslash*/ |
||
@.r=_ /*save the row in @.*/ |
@.r=_ /*save the row in @.*/ |
||
end /*r*/ |
end /*r*/ |
||
do #=1 for height; _=@.# /*display maze to the terminal. */ |
do #=1 for height; _=@.# /*display maze to the terminal. */ |
||
call makeNice /*make some cell corners prettier*/ |
call makeNice /*make some cell corners prettier*/ |
||
_=changestr(1,_,111) /*these four ────────────────────*/ |
|||
_=changestr( |
_=changestr(1,_,111) /*──────these four ────────────────────*/ |
||
_=changestr( |
_=changestr(0,_,000) /*───────── statements are ────────────*/ |
||
_=changestr( |
_=changestr( . ,_," ") /*────────────── used for preserving ──*/ |
||
_=changestr('~',_,"───") /*────────────────── the aspect ratio. */ |
|||
say translate(_, '─│', "═|\10") /*make it presentable for screen.*/ |
say translate(_, '─│', "═|\10") /*make it presentable for the screen. */ |
||
end /*#*/ |
end /*#*/ |
||
exit /*stick a fork in it, we're done.*/ |
exit /*stick a fork in it, we're all done. */ |
||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────@ subroutine────────────────────────*/ |
|||
@: parse arg _r,_c; return @._r._c /*a fast way to reference a cell.*/ |
@: parse arg _r,_c; return @._r._c /*a fast way to reference a maze cell. */ |
||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────? subroutine────────────────────────*/ |
|||
?: do forever; ?.=0; ?=random(1,4); if ?==1 then ?.zc=-2 /*north*/ |
?: do forever; ?.=0; ?=random(1,4); if ?==1 then ?.zc=-2 /*north*/ |
||
if ?==2 then ?.zr= |
if ?==2 then ?.zr= 2 /* east*/ |
||
if ?==3 then ?.zc= |
if ?==3 then ?.zc= 2 /*south*/ |
||
if ?==4 then ?.zr=-2 /* west*/ |
if ?==4 then ?.zr=-2 /* west*/ |
||
_r=r!+?.zr; _c=c!+?.zc; if @._r._c==1 then return |
_r=r!+?.zr; _c=c!+?.zc; if @._r._c==1 then return |
||
end /*forever*/ |
end /*forever*/ |
||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────BUILDROW subroutine─────────────────*/ |
|||
buildRow: parse arg z; height=height+1; width=length(z) |
buildRow: parse arg z; height=height+1; width=length(z) |
||
do c=1 for width; @.height.c=substr(z,c,1); end; return |
do c=1 for width; @.height.c=substr(z,c,1); end; return |
||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────FCELL subroutine────────────────────*/ |
|||
fCell: do r=1 for rows; rr=r+r |
|||
do c=1 for cols; |
do c=1 for cols; cc=c+c |
||
if hood( |
if hood(rr,cc)==1 then do; r!=rr; c!=cc; @.r!.c!=0; return 1; end |
||
end /*c*/ |
end /*c*/ |
||
end /*r*/ |
end /*r*/ /* [↑] r! & c! are used by invoker.*/ |
||
return 0 |
return 0 |
||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────HOOD subroutine─────────────────────*/ |
|||
hood: parse arg rh,ch; return @(rh+2,ch)+@(rh-2,ch)+@(rh,ch-2)+@(rh,ch+2) |
hood: parse arg rh,ch; return @(rh+2,ch) + @(rh-2,ch) + @(rh,ch-2) + @(rh,ch+2) |
||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────MAKENICE subroutine─────────────────*/ |
|||
makeNice: width=length(_); old=#-1; new=#+1; old_=@.old; new_=@.new |
makeNice: width=length(_); old=#-1; new=#+1; old_=@.old; new_=@.new |
||
if left(_,2) =='├ |
if left(_,2) =='├.' then _=translate(_, '|', "├") |
||
if right(_,2)==' |
if right(_,2)=='.┤' then _=translate(_, '|', "┤") |
||
/* [↓] handle the top grid row.*/ |
/* [↓] handle the top grid row.*/ |
||
do k=1 for width while #==1; z=substr(_,k,1) /*maze top row.*/ |
do k=1 for width while #==1; z=substr(_,k,1) /*maze top row.*/ |
||
if z\=='┬' then iterate |
if z\=='┬' then iterate |
||
if substr(new_,k,1)=='\' then _=overlay('═',_,k) |
if substr(new_,k,1)=='\' then _=overlay('═',_,k) |
||
end /*k*/ |
end /*k*/ |
||
do k=1 for width while #==height; z=substr(_,k,1) /*maze bot row.*/ |
do k=1 for width while #==height; z=substr(_,k,1) /*maze bot row.*/ |
||
if z\=='┴' then iterate |
if z\=='┴' then iterate |
||
if substr(old_,k,1)=='\' then _=overlay('═',_,k) |
if substr(old_,k,1)=='\' then _=overlay('═',_,k) |
||
end /*k*/ |
end /*k*/ |
||
/* [↓] handle the mid grid rows*/ |
/* [↓] handle the mid grid rows*/ |
||
do k=3 to width-2 by 2 while #//2; z=substr(_,k,1) /*maze mid rows*/ |
do k=3 to width-2 by 2 while #//2; z=substr(_,k,1) /*maze mid rows*/ |
||
if z\=='┼' then iterate |
if z\=='┼' then iterate |
||
le=substr(_,k-1,1) |
le=substr(_,k-1,1) |
||
ri=substr(_,k+1,1) |
ri=substr(_,k+1,1) |
||
up=substr(old_,k,1) |
up=substr(old_,k,1) |
||
dw=substr(new_,k,1) |
dw=substr(new_,k,1) |
||
select |
select |
||
when le== |
when le== . & ri== . & up=='│' & dw=='│' then _=overlay('|',_,k) |
||
when le=='~' & ri=='~' & up=='\' & dw=='\' then _=overlay('═',_,k) |
when le=='~' & ri=='~' & up=='\' & dw=='\' then _=overlay('═',_,k) |
||
when le=='~' & ri=='~' & up=='\' & dw=='│' then _=overlay('┬',_,k) |
when le=='~' & ri=='~' & up=='\' & dw=='│' then _=overlay('┬',_,k) |
||
when le=='~' & ri=='~' & up=='│' & dw=='\' then _=overlay('┴',_,k) |
when le=='~' & ri=='~' & up=='│' & dw=='\' then _=overlay('┴',_,k) |
||
when le=='~' & ri== |
when le=='~' & ri== . & up=='\' & dw=='\' then _=overlay('═',_,k) |
||
when le== |
when le== . & ri=='~' & up=='\' & dw=='\' then _=overlay('═',_,k) |
||
when le== |
when le== . & ri== . & up=='│' & dw=='\' then _=overlay('|',_,k) |
||
when le== |
when le== . & ri== . & up=='\' & dw=='│' then _=overlay('|',_,k) |
||
when le== |
when le== . & ri=='~' & up=='\' & dw=='│' then _=overlay('┌',_,k) |
||
when le== |
when le== . & ri=='~' & up=='│' & dw=='\' then _=overlay('└',_,k) |
||
when le=='~' & ri== |
when le=='~' & ri== . & up=='\' & dw=='│' then _=overlay('┐',_,k) |
||
when le=='~' & ri== |
when le=='~' & ri== . & up=='│' & dw=='\' then _=overlay('┘',_,k) |
||
when le=='~' & ri== |
when le=='~' & ri== . & up=='│' & dw=='│' then _=overlay('┤',_,k) |
||
when le== |
when le== . & ri=='~' & up=='│' & dw=='│' then _=overlay('├',_,k) |
||
otherwise nop |
otherwise nop |
||
end /*select*/ |
end /*select*/ |
||
end /*k*/ |
end /*k*/ |
||
return</lang> |
return</lang> |
||
Some older REXXes don't have a '''changestr''' BIF, so one is included here ──► [[CHANGESTR.REX]]. |
Some older REXXes don't have a '''changestr''' BIF, so one is included here ──► [[CHANGESTR.REX]]. |
||
<br><br> |
<br><br> |
||
Line 4,671: | Line 4,672: | ||
The above REXX version had a quite of bit of code to "dress up" the maze presentation, |
The above REXX version had a quite of bit of code to "dress up" the maze presentation, |
||
<br>so a slimmed down version was included here. |
<br>so a slimmed down version was included here. |
||
<lang rexx>/*REXX program |
<lang rexx>/*REXX program generates and displays a rectangular solvable maze (any size).*/ |
||
height=0; @.=0 /*default for all cells visited.*/ |
height=0; @.=0 /*default for all cells visited. */ |
||
parse arg rows cols seed . /*allow user to specify maze size*/ |
parse arg rows cols seed . /*allow user to specify the maze size. */ |
||
if rows='' | rows==',' then rows=19 /*No rows given? |
if rows='' | rows==',' then rows=19 /*No rows given? Then use the default.*/ |
||
if cols='' | cols==',' then cols=19 /* |
if cols='' | cols==',' then cols=19 /* " cols " ? " " " " */ |
||
if seed\=='' then call random ,,seed /*use a seed for repeatability. |
if seed\=='' then call random ,,seed /*use a random seed for repeatability.*/ |
||
call buildRow '┌'copies('─┬',cols-1)'─┐' /*build the top edge of maze.*/ |
call buildRow '┌'copies('─┬',cols-1)'─┐' /*build the top edge of the maze. */ |
||
/* |
/* [↓] construct the maze's grid. */ |
||
do r=1 for rows; _=; __=; hp= '|'; hj='├' |
do r=1 for rows; _=; __=; hp= '|'; hj='├' |
||
do c=1 for cols; _= _||hp'1'; __=__||hj'─'; hj='┼'; hp='│' |
do c=1 for cols; _= _||hp'1'; __=__||hj'─'; hj='┼'; hp='│' |
||
end /*c*/ |
end /*c*/ |
||
call buildRow _'│' /*build right edge of cells.*/ |
call buildRow _'│' /*build the right edge of cells. */ |
||
if r\==rows then call buildRow __'┤' /* " " " " maze.*/ |
if r\==rows then call buildRow __'┤' /* " " " " " maze. */ |
||
end /*r*/ |
end /*r*/ |
||
call buildRow '└'copies('─┴',cols-1)'─┘' /* |
call buildRow '└'copies('─┴',cols-1)'─┘' /*construct the bottom maze edge. */ |
||
r!=random(1,rows)*2; c!=random(1,cols)*2; @.r!.c!=0 /*choose 1st cell*/ |
r!=random(1,rows)*2; c!=random(1,cols)*2; @.r!.c!=0 /*choose the 1st cell.*/ |
||
/* [↓] traipse through the maze.*/ |
/* [↓] traipse through the maze. */ |
||
do forever; n=hood(r!,c!); if n==0 then if \ |
do forever; n=hood(r!,c!); if n==0 then if \fCell() then leave |
||
call ?; @._r._c=0 /*get the (next) direction to go.*/ |
call ?; @._r._c=0 /*get the (next) maze direction to go. */ |
||
ro=r!; co=c!; r!=_r; c!=_c /*save original cell coordinates.*/ |
ro=r!; co=c!; r!=_r; c!=_c /*save the original cell coordinates. */ |
||
?.zr=?.zr%2; ?.zc=?.zc%2 /*get the row and cell directions*/ |
?.zr=?.zr%2; ?.zc=?.zc%2 /*get the maze row and cell directions.*/ |
||
rw=ro+?.zr; cw=co+?.zc /*calculate the next row and col.*/ |
rw=ro+?.zr; cw=co+?.zc /*calculate the next maze row and col. */ |
||
@.rw.cw= |
@.rw.cw=. /*mark the maze cell as being visited. */ |
||
end /*forever*/ |
end /*forever*/ |
||
do r=1 for height; _= /*display the maze. */ |
do r=1 for height; _= /*display the maze. */ |
||
do c=1 for cols*2 + 1; _=_ || @.r.c; end /*c*/ |
do c=1 for cols*2 + 1; _=_ || @.r.c; end /*c*/ |
||
if \(r//2) then _=translate(_, '\', |
if \(r//2) then _=translate(_, '\', .) /*trans to backslash*/ |
||
_=changestr(1,_,111) /* |
_=changestr(1,_,111) /*──────these four ────────────────────*/ |
||
_=changestr(0,_,000) /* |
_=changestr(0,_,000) /*───────── statements are ────────────*/ |
||
_=changestr( |
_=changestr( . ,_," ") /*────────────── used for preserving ──*/ |
||
_=changestr('─',_,"───") /* |
_=changestr('─',_,"───") /*────────────────── the aspect ratio. */ |
||
say translate(_,'│',"|\10") /*make it presentable for screen.*/ |
say translate(_,'│',"|\10") /*make it presentable for the screen. */ |
||
end /*r*/ |
end /*r*/ |
||
exit /*stick a fork in it, we're done.*/ |
exit /*stick a fork in it, we're all done. */ |
||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────@ subroutine────────────────────────*/ |
|||
@: parse arg _r,_c; return @._r._c /*a fast way to reference a cell.*/ |
@: parse arg _r,_c; return @._r._c /*a fast way to reference a maze cell. */ |
||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────? subroutine────────────────────────*/ |
|||
?: do forever; ?.=0; ?=random(1,4); if ?==1 then ?.zc=-2 /*north*/ |
?: do forever; ?.=0; ?=random(1,4); if ?==1 then ?.zc=-2 /*north*/ |
||
if ?==2 then ?.zr= |
if ?==2 then ?.zr= 2 /* east*/ |
||
if ?==3 then ?.zc= |
if ?==3 then ?.zc= 2 /*south*/ |
||
if ?==4 then ?.zr=-2 /* west*/ |
if ?==4 then ?.zr=-2 /* west*/ |
||
_r=r!+?.zr; _c=c!+?.zc; if @._r._c==1 then return |
|||
end /*forever*/ |
|||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────BUILDROW subroutine─────────────────*/ |
|||
buildRow: parse arg z; height=height+1; width=length(z) |
buildRow: parse arg z; height=height+1; width=length(z) |
||
do c=1 for width; @.height.c=substr(z,c,1); end; return |
do c=1 for width; @.height.c=substr(z,c,1); end; return |
||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────FCELL subroutine────────────────────*/ |
|||
fCell: do r=1 for rows; rr=r+r |
|||
do c=1 for cols; |
do c=1 for cols; cc=c+c |
||
if hood( |
if hood(rr,cc)==1 then do; r!=rr; c!=cc; @.r!.c!=0; return 1; end |
||
end /*c*/ |
end /*c*/ |
||
end /*r*/ |
end /*r*/ /* [↑] r! & c! are used by invoker.*/ |
||
return 0 |
return 0 |
||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────HOOD subroutine─────────────────────*/ |
|||
hood: parse arg rh,ch; return @(rh+2,ch)+@(rh-2,ch)+@(rh,ch-2)+@(rh,ch+2)</lang> |
hood: parse arg rh,ch; return @(rh+2,ch) + @(rh-2,ch) + @(rh,ch-2) + @(rh,ch+2)</lang> |
||
'''output''' when using the input: <tt> 10 10 </tt> |
'''output''' when using the input: <tt> 10 10 </tt> |
||
<pre> |
<pre> |