How to resolve the algorithm Maze generation step by step in the REXX programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Maze generation step by step in the REXX programming language

Table of Contents

Problem Statement

Generate and show a maze, using the simple Depth-first search algorithm.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Maze generation step by step in the REXX programming language

Source code in the rexx programming language

/*REXX program generates and displays a  rectangular  solvable maze  (of any size).     */
parse arg rows cols seed .                       /*allow user to specify the maze size. */
if rows='' | rows==','  then rows= 19            /*No rows given?  Then use the default.*/
if cols='' | cols==','  then cols= 19            /* " cols   "  ?    "   "   "     "    */
if datatype(seed, 'W')  then call random ,,seed  /*use a random  seed for repeatability.*/
ht=0;                        @.=0                /*HT= # rows in grid;  @.: default cell*/
call makeRow  '┌'copies("~┬", cols - 1)'~┐'      /*construct the top edge of the maze.  */
                                                 /* [↓]  construct the maze's grid.     */
      do    r=1  for rows;   _=;     __=;      hp= "|";              hj= '├'
         do c=1  for cols;   _= _ || hp'1';    __= __ || hj"~";      hj= '┼';      hp= "│"
         end   /*c*/
                        call makeRow  _'│'       /*construct the right edge of the cells*/
      if r\==rows  then call makeRow __'┤'       /*    "      "    "     "   "  "  maze.*/
      end      /*r*/                             /* [↑]  construct the maze's grid.     */

call makeRow  '└'copies("~┴",  cols - 1)'~┘'     /*construct the bottom edge of the maze*/
r!= random(1, rows) *2;     c!= random(1, cols) *2;      @.r!.c!= 0   /*choose 1st cell.*/
                                                 /* [↓]  traipse through the maze.      */
  do forever;    n= hood(r!, c!);    if n==0  then if \fCell()  then leave  /*¬freecell?*/
  call ?;        @._r._c= 0                      /*get the (next) maze direction to go. */
  ro= r!;        co= c!;     r!= _r;    c!= _c   /*save original maze cell coordinates. */
  ?.zr= ?.zr % 2;            ?.zc= ?.zc % 2      /*get the maze row and cell directions.*/
  rw= ro + ?.zr;             cw= co + ?.zc       /*calculate the next row and column.   */
  @.rw.cw= .                                     /*mark the maze cell as being visited. */
  end   /*forever*/
                                                 /* [↓]  display maze to the terminal.  */
         do     r=1  for ht;            _=
             do c=1  for cols*2 + 1;    _= _ || @.r.c;    end  /*c*/
         if \(r//2)  then _= translate(_, '\', .)                   /*trans to backslash*/
         @.r= _                                                     /*save the row in @.*/
         end   /*r*/

      do #=1  for ht;           _= @.#           /*display the maze to the terminal.    */
      call makeNice                              /*prettify cell corners and dead─ends. */
      _=  changestr( 1 ,  _   , 111     )        /*──────these four ────────────────────*/
      _=  changestr( 0 ,  _   , 000     )        /*───────── statements are ────────────*/
      _=  changestr( . ,  _   , "   "   )        /*────────────── used for preserving ──*/
      _=  changestr('~',  _   , "───"   )        /*────────────────── the aspect ratio. */
      say translate( _ , '─│' , "═|\10" )        /*make it presentable for the screen.  */
      end   /*#*/
  exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
@:       parse arg _r,_c;     return  @._r._c    /*a fast way to reference a maze cell. */
makeRow: parse arg z; ht= ht+1;  do c=1  for length(z); @.ht.c=substr(z,c,1);  end; return
hood:    parse arg rh,ch;     return  @(rh+2,ch)  + @(rh-2,ch)  + @(rh,ch-2)  + @(rh,ch+2)
/*──────────────────────────────────────────────────────────────────────────────────────*/
?:         do forever;  ?.= 0;   ?= random(1, 4);     if ?==1  then ?.zc= -2     /*north*/
                                                      if ?==2  then ?.zr=  2     /* east*/
                                                      if ?==3  then ?.zc=  2     /*south*/
                                                      if ?==4  then ?.zr= -2     /* west*/
           _r= r! + ?.zr;       _c= c! + ?.zc;        if @._r._c == 1    then return
           end   /*forever*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
fCell:     do     r=1  for rows;                rr= r + r
               do c=1  for cols;                         cc= c + c
               if hood(rr,cc)==1  then do;  r!= rr;  c!= cc;   @.r!.c!= 0;  return 1;  end
               end   /*c*/                       /* [↑]  r! and c!  are used by invoker.*/
           end       /*r*/;       return 0
/*──────────────────────────────────────────────────────────────────────────────────────*/
makeNice: width= length(_);     old= # - 1;     new= # + 1;     old_= @.old;   new_= @.new
          if left(_, 2)=='├.'  then _= translate(_, "|", '├')
          if right(_,2)=='.┤'  then _= translate(_, "|", '┤')

             do  k=1  for  width  while #==1;         z= substr(_, k, 1) /*maze top row.*/
             if z\=='┬'                  then iterate
             if substr(new_, k, 1)=='\'  then _= overlay("═", _, k)
             end   /*k*/

             do  k=1  for  width  while #==ht;        z= substr(_, k, 1) /*maze bot row.*/
             if z\=='┴'                  then iterate
             if substr(old_, k, 1)=='\'  then _= overlay("═", _, k)
             end   /*k*/

             do  k=3  to  width-2  by 2  while #//2;  z= substr(_, k, 1) /*maze mid rows*/
             if z\=='┼'   then iterate
             le= substr(_   , k-1, 1)
             ri= substr(_   , k+1, 1)
             up= substr(old_, k  , 1)
             dw= substr(new_, k  , 1)
                    select
                    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== .  & 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)
                    otherwise   nop
                    end   /*select*/
             end          /*k*/;                   return


/*REXX program  generates and displays  a  rectangular  solvable maze  (of any size).   */
parse arg rows cols seed .                       /*allow user to specify the maze size. */
if rows='' | rows==","  then rows= 19            /*No rows given?  Then use the default.*/
if cols='' | cols==","  then cols= 19            /* " cols   "  ?    "   "   "     "    */
if datatype(seed, 'W')  then call random ,,seed  /*use a random  seed for repeatability.*/
ht=0;                        @.=0                /*HT= # rows in grid;  @.: default cell*/
call makeRow '┌'copies("─┬", cols-1)'─┐'         /*construct the  top edge  of the maze.*/

      do    r=1  for rows;   _=;     __=;      hp= "|";              hj= '├'
         do c=1  for cols;   _= _ || hp'1';    __= __ || hj"─";      hj= '┼';      hp= "│"
         end   /*c*/
                        call makeRow  _'│'       /*construct the right edge of the cells*/
      if r\==rows  then call makeRow __'┤'       /*    "      "    "     "   "  "  maze.*/
      end      /*r*/                             /* [↑]  construct the maze's grid.     */

call makeRow '└'copies("─┴", cols-1)'─┘'         /*construct the bottom edge of the maze*/
r!= random(1, rows)*2;    c!= random(1, cols)*2;     @.r!.c!= 0   /*choose the 1st cell.*/
                                                 /* [↓]  traipse through the maze.      */
  do forever;        n= hood(r!, c!)             /*number of free maze cells.           */
  if n==0  then if \fCell()  then leave          /*if no free maze cells left, then done*/
  call ?;            @._r._c= 0                  /*get the (next) maze direction to go. */
  ro= r!;            co= c!;    r!= _r;   c!= _c /*save the original cell coordinates.  */
  ?.zr= ?.zr % 2;    ?.zc= ?.zc % 2              /*get the maze row and cell directions.*/
  rw= ro + ?.zr;     cw= co + ?.zc               /*calculate the next maze row and col. */
  @.rw.cw=.                                      /*mark the maze cell as being visited. */
  end   /*forever*/
                                                 /* [↓]  display maze to the terminal.  */
         do     r=1  for ht;           _=
             do c=1  for cols*2 + 1;   _= _ || @.r.c;   end  /*c*/
         if \(r//2)  then _= translate(_, '\',.) /*translate a  period  to a  backslash.*/
         _=  changestr( 1 ,  _  , 111   )        /*──────these four ────────────────────*/
         _=  changestr( 0 ,  _  , 000   )        /*───────── statements are ────────────*/
         _=  changestr( . ,  _  , "   " )        /*────────────── used for preserving ──*/
         _=  changestr('─',  _  , "───" )        /*────────────────── the aspect ratio. */
         say translate( _ , '│' , "|\10")        /*make it presentable for the screen.  */
         end   /*r*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
@:       parse arg _r,_c;     return  @._r._c    /*a fast way to reference a maze cell. */
makeRow: parse arg z; ht= ht+1;  do c=1  for length(z); @.ht.c=substr(z,c,1);  end; return
hood:    parse arg rh,ch;     return  @(rh+2,ch)  + @(rh-2,ch)  + @(rh,ch-2)  + @(rh,ch+2)
/*──────────────────────────────────────────────────────────────────────────────────────*/
?:         do forever;  ?.= 0;   ?= random(1, 4);     if ?==1  then ?.zc= -2     /*north*/
                                                      if ?==2  then ?.zr=  2     /* east*/
                                                      if ?==3  then ?.zc=  2     /*south*/
                                                      if ?==4  then ?.zr= -2     /* west*/
           _r= r! + ?.zr;       _c= c! + ?.zc;        if @._r._c == 1    then return
           end   /*forever*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
fCell:     do     r=1  for rows;                rr= r + r
               do c=1  for cols;                         cc= c + c
               if hood(rr,cc)==1  then do;  r!= rr;  c!= cc;   @.r!.c!= 0;  return 1;  end
               end   /*c*/                       /* [↑]  r! and c!  are used by invoker.*/
           end       /*r*/;       return 0


/* REXX ***************************************************************
* 04.09.2013 Walter Pachl
**********************************************************************/
Parse Arg imax jmax seed
If imax='' Then imax=10
If jmax='' Then jmax=15
If seed='' Then seed=4711
c='123456789'||,
  'abcdefghijklmnopqrstuvwxyz'||,
  translate('abcdefghijklmnopqrstuvwxyz')
c=copies(c,10)
call random 1,10,seed
id=2*imax+1                         /* vertical dimension of a.i.j   */
jd=2*jmax+1                         /* horizontal dimension of a.i.j */
a.=1                                   /* mark all borders present   */
p.='.'                                 /* Initialize all grid points */
pl.=0                                  /* path list                  */
ii=random(1,imax)                      /* find a start position      */
jj=random(1,jmax)
p=1                                    /* first position             */
na=1                                   /* number of points used      */
Do si=1 To 1000                        /* Do Forever - see Leave     */
  /* Say 'loop' si na                     show progress              */
  Call path ii,jj                /* compute a path starting at ii/jj */
  If na=imax*jmax Then                 /* all points used            */
    Leave                              /* we are done                */
  Parse Value select_next() With ii jj /* get a new start from a path*/
  End

/***************
Do i=1 To imax
  ol=''
  Do j=1 To jmax
    ol=ol||p.i.j
    End
    Say ol
  End
Say ' '
***************/
Call show
/***********************
Do pi=1 To imax*jmax
  Say right(pi,3) pos.pi
  End
***********************/
Exit

path: Procedure Expose p. np. p pl. c a. na imax jmax id jd pos.
/**********************************************************************
* compute a path starting from point (ii,jj)
**********************************************************************/
  Parse Arg ii,jj
  p.ii.jj='1'
  pos.p=ii jj
  Do pp=1 to 50                /* compute a path of maximum length 50*/
    neighbors=neighbors(ii,jj)         /* number of free neighbors   */
    Select
      When neighbors=1 Then            /* just one                   */
        Call advance 1,ii,jj           /* go for it                  */
      When neighbors>0 Then Do         /* more Than 1                */
        ch=random(1,neighbors)         /* choose one possibility     */
        Call advance ch,ii,jj          /* and go for that            */
        End
      Otherwise                        /* none available             */
        Leave
      End
    End
  Return

neighbors: Procedure Expose p. np.  imax jmax neighbors pl.
/**********************************************************************
* count the number of free neighbors of point (i,j)
**********************************************************************/
  Parse Arg i,j
  neighbors=0
  in=i-1; If in>0     Then Call check in,j
  in=i+1; If in<=imax Then Call check in,j
  jn=j-1; If jn>0     Then Call check i,jn
  jn=j+1; If jn<=jmax Then Call check i,jn
  Return neighbors

check: Procedure Expose p. imax jmax np. neighbors pl.
/**********************************************************************
* check if point (i,j) is free and note it as possible successor
**********************************************************************/
  Parse Arg i,j
  If p.i.j='.' Then Do                 /* point is free              */
    neighbors=neighbors+1              /* number of free neighbors   */
    np.neighbors=i j                   /* note it as possible choice */
    End
  Return

advance: Procedure Expose p pos. np. p. c ii jj a. na pl. pos.
/**********************************************************************
* move to the next point of the current path
**********************************************************************/
  Parse Arg ch,pii,pjj
  Parse Var np.ch ii jj
  p=p+1                                /* position number            */
  pos.p=ii jj                          /* note its coordinates       */
  p.ii.jj=substr(c,p,1)                /* mark the point as used     */
  ai=pii+ii                            /* vertical border position   */
  aj=pjj+jj                            /* horizontal border position */
  a.ai.aj=0                            /* tear the border down       */
  na=na+1                              /* number of used positions   */
  z=pl.0+1                             /* add the point to the list  */
  pl.z=ii jj                           /* of follow-up start pos.    */
  pl.0=z
  Return

show: Procedure Expose id jd a.  na
/*********************************************************************
* Show the resulting maze
*********************************************************************/
  say 'mgg 6 18 4711'
  say 'show na='na
  Do i=1 To id
    ol=''
    Do j=1 To jd
      If i//2=1 Then Do                /* odd lines                 */
        If a.i.j=1 Then Do             /* border to be drawn        */
          If j//2=0 Then
            ol=ol||'---'               /* draw the border           */
          Else
            ol=ol'+'
          End
        Else Do                        /* border was torn down      */
          If j//2=0 Then
            ol=ol||'   '               /* blanks instead of border  */
          Else
            ol=ol||'+'
          End
        End
      Else Do                          /* even line                 */
        If a.i.j=1 Then Do
          If j//2=0 Then               /* even column               */
            ol=ol||'   '               /* moving space              */
          Else                         /* odd column                */
            ol=ol||'|'                 /* draw the border           */
          End
        Else                           /* border was torn down      */
          ol=ol||' '                   /* blank instead of border   */
        End
      End
    Select
      When i=6 Then ol=overlay('A',ol,11)
      When i=8 Then ol=overlay('B',ol, 3)
      Otherwise Nop
      End
    Say ol format(i,2)
    End
  Return

select_next: Procedure Expose p. pl. imax jmax
/*********************************************************************
* look for a point to start the nnext path
*********************************************************************/
  Do Until neighbors>0                 /* loop until one is found   */
    n=pl.0                             /* number of points recorded */
    s=random(1,n)                      /* pick a random index       */
    Parse Var pl.s is js               /* its coordinates           */
    neighbors=neighbors(is,js)         /* count free neighbors      */
    If neighbors=0 Then Do             /* if there is none          */
      pl.s=pl.n                        /* remove this point         */
      pl.0=pl.0-1
      End
    End
  Return is js                         /* return the new start point*/


  

You may also check:How to resolve the algorithm Partial function application step by step in the C programming language
You may also check:How to resolve the algorithm Forest fire step by step in the Scala programming language
You may also check:How to resolve the algorithm Dijkstra's algorithm step by step in the Java programming language
You may also check:How to resolve the algorithm Count occurrences of a substring step by step in the Objective-C programming language
You may also check:How to resolve the algorithm Align columns step by step in the MUMPS programming language