home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / rec / games / programm / 5166 < prev    next >
Encoding:
Text File  |  1992-12-23  |  24.8 KB  |  951 lines

  1. Path: sparky!uunet!zaphod.mps.ohio-state.edu!darwin.sura.net!jvnc.net!netnews.upenn.edu!dsinc!ub!toz!cyberman
  2. From: cyberman@toz.buffalo.ny.us (Cyberman)
  3. Newsgroups: rec.games.programmer
  4. Subject: MAze FaQ (Not mine)
  5. Message-ID: <gate.6q67VB1w165w@toz.buffalo.ny.us>
  6. Date: 22 Dec 92 18:41:04 GMT
  7. Lines: 941
  8. X-Maildoor: WaflineMail 1.00r
  9.  
  10. ========================================
  11. Maze FAQ
  12. ========================================
  13.  
  14. Sorry this is NOT an organized FAQ it's still useful though
  15. ------------------------------------------------------------
  16.  
  17. Oh, you're really going to love this one.  It's an obfuscated C code
  18. mazegenerator.  Fun fun fun.  Well, if you can figure it out, there's
  19. youralgorithm.  Fun fun fun.
  20.  
  21. char*M,A,Z,E=40,J[40],T[40];main(C){for(*J=A=scanf(M="%d",&C);
  22. --            E;             J[              E]             =T
  23. [E   ]=  E)   printf("._");  for(;(A-=Z=!Z)  ||  (printf("\n|"
  24. )    ,   A    =              39              ,C             --
  25. )    ;   Z    ||    printf   (M   ))M[Z]=Z[A-(E   =A[J-Z])&&!C
  26. &    A   ==             T[                                  A]
  27. |6<<11<rand()||!C&!Z?J[T[E]=T[A]]=E,J[T[A]=A-Z]=A,"_.":" |"];}
  28.  
  29. Pretty cute, no?
  30.  
  31. --
  32. Brad Threatt | MISSING! Single white male Jesus look-alike in blue
  33.        | Members Only jacket.  Answers to the name 'Dave Gillespie'.
  34. Safe sex is  | Last seen with roller-skating couple in Pasadena.
  35. for wimps.   | If found, please return to the cs10 lab immediately.
  36. ========================================
  37.  
  38.  
  39. In <1992Mar5.210706.24104@wpi.WPI.EDU> rcarter@wpi.WPI.EDU (Randolph
  40. Carter (nee. Joseph H. Allen)) writes:
  41.  
  42.  
  43. >>char*M,A,Z,E=40,J[40],T[40];main(C){for(*J=A=scanf(M="%d",&C);
  44. >>--            E;             J[              E]             =T
  45. >>[E   ]=  E)   printf("._");  for(;(A-=Z=!Z)  ||  (printf("\n|"
  46. >>)    ,   A    =              39              ,C             --
  47. >>)    ;   Z    ||    printf   (M   ))M[Z]=Z[A-(E   =A[J-Z])&&!C
  48. >>&    A   ==             T[                                  A]
  49. >>|6<<11<rand()||!C&!Z?J[T[E]=T[A]]=E,J[T[A]=A-Z]=A,"_.":" |"];}
  50.       ^^
  51. This should be 28 if rand() returns a 32-bit quantity.
  52.  
  53. >>Pretty cute, no?
  54.  
  55. >No style at all.... :-)
  56.  
  57. ========================================
  58.  
  59. >--
  60. >/*  rcarter@wpi.wpi.edu */      /* Amazing */             /* Joseph H.
  61. Allen */
  62. >int
  63. a[1817];main(z,p,q,r){for(p=80;q+p-80;p-=2*a[p])for(z=9;z--;)q=3&(r=time(0)
  64. >+r*57)/7,q=q?q-1?q-2?1-p%79?-1:0:p%79-77?1:0:p<1659?79:0:p>158?-79:0,q?!a[p+q*
  65. 2
  66. >]?a[p+=a[p+=q]=q]=q:0:0;for(;q++-1817;)printf(q%79?"%c":"%c\n","
  67. #"[!a[q-1]]);}
  68.  
  69. Well, it doesn't produce a maze, but try this one...
  70.  
  71. int a=10000,b,c=2800,d,e,f[2801],g;main(){for(;b-c;)f[b++]=a/5;for(;d=0,g=c*2;c
  72. -=14,printf("%.4d",e+d/a),e=d%a)for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);}
  73. (I disclaim any credit for this!)
  74. --
  75. John Brownie
  76. School of Mathematics and Statistics
  77. University of Sydney
  78. Internet: jhb@maths.su.oz.au
  79.  
  80.  
  81.  
  82. ========================================
  83.  
  84. Excerpts from programming: 6-Mar-92 Re: Algorithm to create a m.. Mark
  85. Howell@movies.enet. (5723)
  86.  
  87.  
  88. Here's the single level maze algorithm, solver and printer.
  89.  
  90. /*
  91.  * MazeGen.c -- Mark Howell -- 8 May 1991
  92.  *
  93.  * Usage: MazeGen [width [height [seed]]]
  94.  */
  95. #include <stdio.h>
  96. #include <stdlib.h>
  97. #include <time.h>
  98.  
  99. #define WIDTH 39
  100. #define HEIGHT 11
  101.  
  102. #define UP 0
  103. #define RIGHT 1
  104. #define DOWN 2
  105. #define LEFT 3
  106. #ifdef TRUE
  107. #undef TRUE
  108. #endif /* TRUE */
  109.  
  110. #define TRUE 1
  111.  
  112. #define cell_empty(a) (!(a)->up && !(a)->right && !(a)->down && !(a)->left)
  113.  
  114. typedef struct {
  115.     unsigned int up      : 1;
  116.     unsigned int right   : 1;
  117.     unsigned int down    : 1;
  118.     unsigned int left    : 1;
  119.     unsigned int path    : 1;
  120.     unsigned int visited : 1;
  121. } cell_t;
  122. typedef cell_t *maze_t;
  123.  
  124. void CreateMaze (maze_t maze, int width, int height);
  125. void SolveMaze (maze_t maze, int width, int height);
  126. void PrintMaze (maze_t maze, int width, int height);
  127.  
  128. int main (int argc, char *argv [])
  129. {
  130.     int width = WIDTH;
  131.     int height = HEIGHT;
  132.     maze_t maze;
  133.  
  134.     if (argc >= 2)
  135.         width = atoi (argv [1]);
  136.  
  137.     if (argc >= 3)
  138.         height = atoi (argv [2]);
  139.  
  140.     if (argc >= 4)
  141.         srand (atoi (argv [3]));
  142.     else
  143.         srand ((int) time ((time_t *) NULL));
  144.  
  145.     if (width <= 0 || height <= 0) {
  146.         (void) fprintf (stderr, "Illegal width or height value!\n");
  147.         exit (EXIT_FAILURE);
  148.     }
  149.     maze = (maze_t) calloc (width * height, sizeof (cell_t));
  150.     if (maze == NULL) {
  151.         (void) fprintf (stderr, "Cannot allocate memory!\n");
  152.         exit (EXIT_FAILURE);
  153.     }
  154.     CreateMaze (maze, width, height);
  155.  
  156.     PrintMaze (maze, width, height);
  157.  
  158.     (void) putchar ('\n');
  159.  
  160.     SolveMaze (maze, width, height);
  161.  
  162.     PrintMaze (maze, width, height);
  163.  
  164.     free (maze);
  165.     exit (EXIT_SUCCESS);
  166.  
  167.     return (0);
  168.  
  169. }/* main */
  170.  
  171.  
  172. void CreateMaze (maze_t maze, int width, int height)
  173. {
  174.     maze_t mp, maze_top;
  175.     char paths [4];
  176.     int visits, directions;
  177.  
  178.     visits = width * height - 1;
  179.     mp = maze;
  180.     maze_top = mp + (width * height) - 1;
  181.  
  182.     while (visits) {
  183.         directions = 0;
  184.  
  185.         if ((mp - width) >= maze && cell_empty (mp - width))
  186.             paths [directions++] = UP;
  187.         if (mp < maze_top && ((mp - maze + 1) % width) && cell_empty (mp + 1))
  188.             paths [directions++] = RIGHT;
  189.         if ((mp + width) <= maze_top && cell_empty (mp + width))
  190.             paths [directions++] = DOWN;
  191.         if (mp > maze && ((mp - maze) % width) && cell_empty (mp - 1))
  192.             paths [directions++] = LEFT;
  193.  
  194.         if (directions) {
  195.             visits--;
  196.             directions = ((unsigned) rand () % directions);
  197.  
  198.             switch (paths [directions]) {
  199.                 case UP:
  200.                     mp->up = TRUE;
  201.                     (mp -= width)->down = TRUE;
  202.                     break;
  203.                 case RIGHT:
  204.                     mp->right = TRUE;
  205.                     (++mp)->left = TRUE;
  206.                     break;
  207.                 case DOWN:
  208.                     mp->down = TRUE;
  209.                     (mp += width)->up = TRUE;
  210.                     break;
  211.                 case LEFT:
  212.                     mp->left = TRUE;
  213.                     (--mp)->right = TRUE;
  214.                     break;
  215.                 default:
  216.                     break;
  217.             }
  218.         } else {
  219.             do {
  220.                 if (++mp > maze_top)
  221.                     mp = maze;
  222.             } while (cell_empty (mp));
  223.         }
  224.     }
  225. }/* CreateMaze */
  226.  
  227.  
  228. void SolveMaze (maze_t maze, int width, int height)
  229. {
  230.     maze_t *stack, mp = maze;
  231.     int sp = 0;
  232.  
  233.     stack = (maze_t *) calloc (width * height, sizeof (maze_t));
  234.     if (stack == NULL) {
  235.         (void) fprintf (stderr, "Cannot allocate memory!\n");
  236.         exit (EXIT_FAILURE);
  237.     }
  238.     (stack [sp++] = mp)->visited = TRUE;
  239.  
  240.     while (mp != (maze + (width * height) - 1)) {
  241.  
  242.         if (mp->up && !(mp - width)->visited)
  243.             stack [sp++] = mp - width;
  244.         if (mp->right && !(mp + 1)->visited)
  245.             stack [sp++] = mp + 1;
  246.         if (mp->down && !(mp + width)->visited)
  247.             stack [sp++] = mp + width;
  248.         if (mp->left && !(mp - 1)->visited)
  249.             stack [sp++] = mp - 1;
  250.  
  251.         if (stack [sp - 1] == mp)
  252.             --sp;
  253.  
  254.         (mp = stack [sp - 1])->visited = TRUE;
  255.     }
  256.     while (sp--)
  257.         if (stack [sp]->visited)
  258.             stack [sp]->path = TRUE;
  259.  
  260.     free (stack);
  261.  
  262. }/* SolveMaze */
  263.  
  264.  
  265. void PrintMaze (maze_t maze, int width, int height)
  266. {
  267.     int w, h;
  268.     char *line, *lp;
  269.  
  270.     line = (char *) calloc ((width + 1) * 2, sizeof (char));
  271.     if (line == NULL) {
  272.         (void) fprintf (stderr, "Cannot allocate memory!\n");
  273.         exit (EXIT_FAILURE);
  274.     }
  275.     maze->up = TRUE;
  276.     (maze + (width * height) - 1)->down = TRUE;
  277.  
  278.     for (lp = line, w = 0; w < width; w++) {
  279.         *lp++ = '+';
  280.         if ((maze + w)->up)
  281.             *lp++ = ((maze + w)->path) ? '.' : ' ';
  282.         else
  283.             *lp++ = '-';
  284.     }
  285.     *lp++ = '+';
  286.     (void) puts (line);
  287.     for (h = 0; h < height; h++) {
  288.         for (lp = line, w = 0; w < width; w++) {
  289.             if ((maze + w)->left)
  290.                 *lp++ = ((maze + w)->path && (maze + w - 1)->path) ? '.' : ' ';
  291.             else
  292.                 *lp++ = '|';
  293.             *lp++ = ((maze + w)->path) ? '.' : ' ';
  294.         }
  295.         *lp++ = '|';
  296.         (void) puts (line);
  297.         for (lp = line, w = 0; w < width; w++) {
  298.             *lp++ = '+';
  299.             if ((maze + w)->down)
  300.                 *lp++ = ((maze + w)->path && (h == height - 1 ||
  301.                          (maze + w + width)->path)) ? '.' : ' ';
  302.             else
  303.  
  304.                 *lp++ = '-';
  305.         }
  306.         *lp++ = '+';
  307.         (void) puts (line);
  308.         maze += width;
  309.     }
  310.     free (line);
  311.  
  312. }/* PrintMaze */
  313.  
  314.  
  315.  
  316. ========================================
  317.  
  318.  
  319. Excerpts from programming: 6-Mar-92 Re: Algorithm to create a m.. "Jon
  320. C. R. Bennett"@andr (4255)
  321.  
  322.  
  323. gillies@m.cs.uiuc.edu (Don Gillies) writes:
  324. > grid.  Mark each square in the grid with a unique number.  Make a list
  325.  
  326. what you want to do is make each grid in the maze into a set.
  327.  
  328. >
  329. >     rooms = n*n         /* each spot in the grid is a unique room */
  330. >
  331. >     repeat
  332. >         pick a random wall without replacement.
  333. >         if the numbers X and Y in the grid on both sides of the wall
  334. >             are different --
  335. >                 delete the wall and use a recursive depth
  336. >                 first search or brute-force loop to replace
  337. >                 all Y in the grid with X's.
  338.         what you do here is instead
  339.         pick a wall
  340.         if the rooms on either side of the wall belong to differnent sets
  341.                delete the wall
  342.                union the two sets together.
  343.  
  344. the rest is the same
  345.  
  346.  
  347. the brute force solution runs in O(n^2) this runs in O(n) (where n is the
  348. number of grids) so if you had a 100 x 100 maze, this method takes 10,000
  349. time steps, the brute force could take as many as 100,000,000 steps.
  350.  
  351. jon
  352.  
  353. p.s. below you will find some code to generate a maze this way
  354.  
  355.  
  356. ---------------------------------------------------
  357. /* maze.c   a maze generator
  358.    Jon Bennett
  359.         jcrb@cs.cmu.edu
  360.    */
  361.  
  362. /* the maze is generated by making a list of all the internal hedges
  363.    and randomizing it, then going lineraly through the list, we take a
  364.    hedge and se if the maze squares adjacent to it are already connected
  365.    (with find) is not the we connect them (with link), this prevents us
  366.    from creating a maze with a cycle because we will not link two maze
  367.    squares that are already connect by some path */
  368. #include <stdio.h>
  369.  
  370. #define DOWN 1
  371. #define RIGHT 2
  372.  
  373. struct maze_loc{
  374.     int rank;
  375.     int x,y;
  376.     struct maze_loc *ptr;
  377. };
  378. struct hedge_loc{
  379.     int x,y,pos,on;
  380. };
  381.  
  382. struct maze_loc *maze;
  383. struct hedge_loc *hedge;
  384. struct hedge_loc **hedge_list;
  385.  
  386. void link(a,b)
  387.  struct maze_loc *a,*b;
  388. {
  389.     if(a->rank == b->rank){
  390.         a->ptr=b;
  391.         b->rank++;
  392.         return;
  393.     }
  394.     if(a->rank > b->rank){
  395.         b->ptr=a;
  396.         return;
  397.     }
  398.     a->ptr=b;
  399. }
  400. struct maze_loc *find(a)
  401.  struct maze_loc *a;
  402. {
  403.     if(a != a->ptr){
  404.         a->ptr = find(a->ptr);
  405.     }
  406.     return a->ptr;
  407. }
  408.  
  409. main(argc,argv)
  410.  int argc;
  411.  char **argv;
  412. {
  413.     int x,y,i,j,k,l,tmp;
  414.     struct maze_loc *a,*b;
  415.     struct hedge_loc *htmp;
  416.  
  417.     if(argc!=3) exit(1);
  418.  
  419.     srandom(time(0));
  420.     x=atoi(argv[1]);
  421.     y=atoi(argv[2]);
  422.  
  423.     /*malloc the maze and hedges */
  424.     maze=(struct maze_loc *)malloc(sizeof(struct maze_loc)*x*y);
  425.     hedge=(struct hedge_loc *)malloc(sizeof(struct
  426. hedge_loc)*((x*(y-1))+((x-1)*y)));
  427.     hedge_list=(struct hedge_loc **)malloc(sizeof(struct hedge_loc
  428. *)*((x*(y-1))+((x-1)*y)));
  429.  
  430.     /*init maze*/
  431.  
  432.     for(j=0;j<y;j++){
  433.         for(i=0;i<x;i++){
  434.             maze[x*j+i].x = i;
  435.             maze[x*j+i].y = j;
  436.             maze[x*j+i].ptr = &maze[x*j+i];
  437.             maze[x*j+i].rank=0;
  438.         }
  439.     }
  440.  
  441.     /*init hedges*/
  442.     for(j=0;j<(y-1);j++){
  443.         for(i=0;i<x;i++){
  444.             hedge[x*j+i].x = i;
  445.             hedge[x*j+i].y = j;
  446.             hedge[x*j+i].pos=DOWN;
  447.             hedge[x*j+i].on=1;
  448.             hedge_list[x*j+i]= &hedge[x*j+i];
  449.         }
  450.     }
  451.     k=x*(y-1);
  452.  
  453.     for(j=0;j<y;j++){
  454.         for(i=0;i<(x-1);i++){
  455.             hedge[k+(x-1)*j+i].x = i;
  456.             hedge[k+(x-1)*j+i].y = j;
  457.             hedge[k+(x-1)*j+i].pos=RIGHT;
  458.             hedge[k+(x-1)*j+i].on=1;
  459.             hedge_list[k+(x-1)*j+i]= &hedge[k+(x-1)*j+i];
  460.         }
  461.     }
  462.  
  463.     k=(x*(y-1))+((x-1)*y);
  464.  
  465.     /*randomize hedges*/
  466.     for(i=(k-1);i>0;i--){
  467.         htmp=hedge_list[i];
  468.         j=random()%i;
  469.         hedge_list[i]=hedge_list[j];
  470.         hedge_list[j]=htmp;
  471.     }
  472.     fflush(stdout);
  473.  
  474.     l=k;
  475.  
  476.     /*create maze*/
  477.     for(i=0;i<l;i++){
  478.         j=hedge_list[i]->x;
  479.         k=hedge_list[i]->y;
  480.         a=find(&maze[x*k+j]);
  481.         if(hedge_list[i]->pos==DOWN){
  482.             b=find(&maze[x*(k+1)+j]);
  483.         } else {
  484.             b=find(&maze[x*k+j+1]);
  485.         }
  486.         if(a!=b){
  487.             link(a,b);
  488.             hedge_list[i]->on=0;
  489.         }
  490.     }
  491.  
  492.     printf("+");
  493.     for(i=0;i<x;i++){
  494.         printf("-+");
  495.     }
  496.     printf("\n");
  497.  
  498.     l=x*(y-1);
  499.  
  500.     for(j=0;j<y;j++){
  501.         printf("|");
  502.         for(i=0;i<(x-1);i++){
  503.             if(hedge[l+(x-1)*j+i].on){
  504.                printf(" |");
  505.             } else {
  506.                printf("  ");
  507.             }
  508.         }
  509.         printf(" |\n|");
  510.         if(j<(y-1)){
  511.             for(i=0;i<x;i++){
  512.                if(hedge[j*x+i].on){
  513.                    printf("--");
  514.                } else {
  515.                    printf(" -");
  516.                }
  517.             }
  518.             printf("\n");
  519.         }
  520.  
  521.     }
  522.  
  523.     for(i=0;i<x;i++){
  524.         printf("-+");
  525.     }
  526.     printf("\n");
  527.  
  528. }
  529. ========================================
  530.  
  531.  
  532.  
  533. Excerpts from programming: 9-Mar-92 Re: Algorithm to create a m.. Don
  534. Gillies@m.cs.uiuc.ed (609)
  535.  
  536. Here is another algorithm I just thought of -- how well does it work?
  537.  
  538. 1.  create a GRAPH with n*n nodes.
  539. 2.  for each node in the graph create 4 edges, linking it to the
  540.     node in the north, south, east, and west direction.
  541. 3.  Assign a random weight to every edge.
  542. 4.  Run a minimum spanning tree algorithm (take your choice
  543.     from any algorithms textbook) to produce a graph.  A minimum
  544.     spanning tree has a path from every node to every other node,
  545.     and no cycles, hence, it corresponds to a perfect maze.
  546.  
  547. Don Gillies - gillies@cs.uiuc.edu - University of Illinois at Urbana-Champaign
  548.  
  549.  
  550.  
  551.  
  552. ========================================
  553.  
  554.  
  555.  
  556.  
  557.  
  558. Excerpts from programming: 8-Apr-92 re mazes Chris_Okasaki@LOCH.MESS. (5437)
  559.  
  560. Thanks for the messages.  FYI, here is the maze tutorial I used to send out.
  561.  
  562. Chris
  563. --------------
  564. This seems to come up every couple of months, doesn't it?  Maybe we
  565. should make a FAQL for this group...
  566.  
  567. Anyway, maze generation--a topic near and dear to my heart!  I'm going
  568. to describe the three most common methods.  Note that these will all
  569. generate mazes without loops or rooms or anything like that.  Restricting
  570. a maze to be a tree (in the graph-theoretical sense of the term) simplifies
  571. things immensely.  Mazes with loops are much harder to generate automatically
  572. in any nice way.  Perhaps the best way is start out generating a tree and
  573. then knock a couple of extra walls (all the algorithms start out with all
  574. walls present and then knock out walls as necessary).
  575.  
  576. Finally, note that all of these techniques are based on well-known graph
  577. algorithms.  This isn't surprising since what is being generated is
  578. really nothing more than a spanning tree.
  579.  
  580.  
  581. Technique #1: Depth-first search
  582.  
  583. 1. Pick a random starting location as the "current cell" and mark it
  584.    as "visited".  Also, initialize a stack of cells to empty (the stack
  585.    will be used for backtracking).  Initialize VISITED (the number of
  586.    visited cells) to 1.
  587. 2. While VISITED < the total number of cells, do the following:
  588.      If the current cell has any neighbors which haven't yet been visited,
  589.        pick one at random.  Push the current cell on the stack and set the
  590.        current cell to be the new cell, marking the new cell as visited.
  591.        Knock out the wall between the two cells.  Increment VISITED.
  592.      If all of the current cell's neighbors have already been visited, then
  593.        backtrack.  Pop the previous cell off the stack and make it the current
  594.        cell.
  595.  
  596.  
  597. This algorithm is probably the simplest to implement, but it has a problem
  598. in that there are many mazes which it cannot generate.  In particular, it will
  599. continue generating one branch of the maze as long as there are unvisited cells
  600. in the area instead of being able to give up and let the unvisited cells get
  601. used by a different branch.  This can be partially remedied by allowing the
  602. algorithm to randomly backtrack even when there are unvisited neighbors, but
  603. this creates the possibility of (potentially large) dead spaces in the
  604. maze.  For some applications, such as dungeon creation, this behavior
  605. might be desirable.  A refinement which cuts down on the amount of dead space
  606. is to vary the probability of backtracking as an increasing function on the
  607. number of iterations since the last backtrack.
  608.  
  609.  
  610.  
  611. Technique #2: Prim's Algorithm
  612. 1. Maintain three sets of cells: IN, OUT, and FRONTIER.  Initially, choose
  613.    one cell at random and place it in IN.  Place all of the cell's neighbors in
  614.    FRONTIER and all remaining cells in OUT.
  615. 2. While FRONTIER is not empty do the following:  Remove one cell at random
  616.    from FRONTIER and place it in IN.  If the cell has any neighbors in
  617.    OUT, remove them from OUT and place them in FRONTIER.  The cell is
  618.    guaranteed to have at least one neighbor in IN (otherwise it would
  619.    not have been in FRONTIER); pick one such neighbor at random and connect
  620.    it to the new cell (ie knock out a wall).
  621.  
  622. This algorithm works by growing a single tree (without concentrating
  623. on any one particular branch like the previous algorithm).  An interesting
  624. variation on this algorithm is to run two (or more) instances of it
  625. at once, starting in different locations and generating non-interesecting
  626. trees.  This can be useful, for instance, for generating multiple disjoint
  627. areas on a single level of a dungeon (perhaps connected by secret doors
  628. or perhaps requiring adventurers to blast through walls themselves).
  629.  
  630.  
  631. Technique #3: Kruskal's Algorithm
  632.  
  633. This is perhaps the most advanced of the maze generation algorithms,
  634. requiring some knowledge of the union-find algorithm.  It is also the
  635. most fun to watch in progress!
  636.  
  637. Basically what the union-find algorithm does is give you a FAST
  638. implementation of equivalence classes where you can do two things:
  639. FIND which equivalence class a given object belongs to, or UNION
  640. two equivalance classes into a single class.  Any moderately advanced
  641. book on algorithms and data structures will have more details.
  642. In this algorithm, the objects will be cells in the maze, and two
  643. objects will be in the same equivalence class iff they are (perhaps
  644. indirectly) connected.
  645.  
  646. 1. Initialize the union-find structures so that every cell is in
  647.    its own equivalence class.  Create a set containing all the interior
  648.    walls of the maze (ie those walls which lie between neighboring cells).
  649.    Set COUNT to the number of cells.  (COUNT is the number of connected
  650.    components in the maze).
  651. 2. While COUNT > 1 do the following:
  652.      Remove a wall from the set of walls at random.  If the two cells
  653.      that this wall separates are already connected (test by doing a FIND
  654.      on each), then do nothing; otherwise, connect the two cells (by
  655.      UNIONing them and decrementing COUNT) and knock out the wall.
  656.  
  657.  
  658.  
  659. Note that none of these algorithms make any assumptions about the topology
  660. of the maze.  They will work with 2-d or 3-d grids, toroids, hexagons,
  661. whatever.  However, in the more highly connected topologies (such as 3-d
  662. grids), the deficiencies of the first algorithm will become even more apparent
  663. (it will tend to produce long, winding paths with very little branching).
  664.  
  665.  
  666. Have fun with these!
  667.  
  668. Chris
  669.  
  670.  
  671. ================================
  672. /*
  673.  * maz.c - generate a maze
  674.  *
  675.  * algorithm posted to rec.games.programmer by jallen@ic.sunysb.edu
  676.  * program cleaned and reorganized by mzraly@ldbvax.dnet.lotus.com
  677.  *
  678.  * don't make people pay for this, or I'll jump up and down and
  679.  * yell and scream and embarass you in front of your friends...
  680.  *
  681.  * compile: cc -o maz -DDEBUG maz.c
  682.  *
  683.  */
  684. #include <stdio.h>
  685.  
  686. static int      multiple = 57;  /* experiment with this? */
  687. static int      offset = 1;     /* experiment with this? */
  688.  
  689. #ifdef __STDC__
  690. int maze(char maz[], int y, int x, char vc, char hc, char fc);
  691. void mazegen(int pos, char maz[], int y, int x, int rnd);
  692. #else
  693. int maze();
  694. void mazegen();
  695. #endif
  696.  
  697. /*
  698.  * maze() : generate a random maze of size (y by x) in maz, using vc as the
  699.  * vertical character, hc as the horizontal character, and fc as the floor
  700.  * character
  701.  *
  702.  * maz is an array that should already have its memory allocated - you could
  703.  * malloc a char string if you like.
  704.  */
  705. #ifdef __STDC__
  706. int maze(char maz[], int y, int x, char vc, char hc, char fc)
  707. #else
  708. int maze(maz, y, x, vc, hc, fc)
  709. char            maz[], vc, hc, fc;
  710. int             y, x;
  711. #endif
  712. {
  713.    int             i, yy, xx;
  714.    int             max = (y * x);
  715.    int             rnd = time(0L);
  716.  
  717.    /* For now, return error on even parameters */
  718.    /* Alternative is to decrement evens by one */
  719.    /* But really that should be handled by caller */
  720.    if (!(y & 1) | !(x & 1))
  721.       return (1);
  722.  
  723.    /* I never assume... */
  724.    for (i = 0; i < max; ++i)
  725.       maz[i] = 0;
  726.  
  727.    (void) mazegen((x + 1), maz, y, x, rnd);
  728.  
  729.    /* Now replace the 1's and 0's with appropriate chars */
  730.    for (yy = 0; yy < y; ++yy) {
  731.       for (xx = 0; xx < x; ++xx) {
  732.          i = (yy * x) + xx;
  733.  
  734.          if (yy == 0 || yy == (y - 1))
  735.             maz[i] = hc;
  736.          else if (xx == 0 || xx == (x - 1))
  737.             maz[i] = vc;
  738.          else if (maz[i] == 1)
  739.             maz[i] = fc;
  740.          else if (maz[i - x] != fc && maz[i - 1] == fc
  741.                  && (maz[i + x] == 0 || (i % x) == (y - 2)))
  742.             maz[i] = vc;
  743.          else
  744.             maz[i] = hc;       /* for now... */
  745.       }
  746.    }
  747.    return (0);
  748. }
  749.  
  750.  
  751. /*
  752.  * mazegen : do the recursive maze generation
  753.  *
  754.  */
  755. #ifdef __STDC__
  756. void mazegen(int pos, char maz[], int y, int x, int rnd)
  757. #else
  758. void
  759. mazegen(pos, maz, y, x, rnd)
  760.    int             pos, y, x, rnd;
  761.    char            maz[];
  762. #endif
  763. {
  764.    int             d, i, j;
  765.  
  766.    maz[pos] = 1;
  767.    while (d = (pos <= x * 2 ? 0 : (maz[pos - x - x] ? 0 : 1))
  768.           | (pos >= x * (y - 2) ? 0 : (maz[pos + x + x] ? 0 : 2))
  769.           | (pos % x == x - 2 ? 0 : (maz[pos + 2] ? 0 : 4))
  770.           | (pos % x == 1 ? 0 : (maz[pos - 2] ? 0 : 8))) {
  771.  
  772.       do {
  773.          rnd = (rnd * multiple + offset);
  774.          i = 3 & (rnd / d);
  775.       } while (!(d & (1 << i)));
  776.  
  777.       switch (i) {
  778.       case 0:
  779.          j = -x;
  780.          break;
  781.       case 1:
  782.          j = x;
  783.          break;
  784.       case 2:
  785.          j = 1;
  786.          break;
  787.       case 3:
  788.          j = -1;
  789.          break;
  790.       default:
  791.          break;
  792.       }
  793.  
  794.       maz[pos + j] = 1;
  795.  
  796.       mazegen(pos + 2 * j, maz, y, x, rnd);
  797.    }
  798.  
  799.    return;
  800. }
  801. #ifdef DEBUG
  802. #define MAXY 24
  803. #define MAXX 80
  804.  
  805. #ifdef __STDC__
  806. main(int argc, char *argv[])
  807. #else
  808. main(argc, argv)
  809.    int             argc;
  810.    char           *argv[];
  811. #endif
  812. {
  813.    extern int      optind;
  814.    extern char    *optarg;
  815.    int             x = 79;
  816.    int             y = 23;
  817.    char            hor = '-';
  818.    char            ver = '|';
  819.    char            flo = ' ';
  820.    char            maz[MAXY * MAXX];
  821.    int             i;
  822.  
  823.    while ((i = getopt(argc, argv, "h:v:f:y:x:m:o:")) != EOF)
  824.       switch (i) {
  825.       case 'h':
  826.          hor = *optarg;
  827.          break;
  828.       case 'v':
  829.          ver = *optarg;
  830.          break;
  831.       case 'f':
  832.          flo = *optarg;
  833.          break;
  834.       case 'y':
  835.          y = atoi(optarg);
  836.          break;
  837.       case 'x':
  838.          x = atoi(optarg);
  839.          break;
  840.       case 'm':
  841.          multiple = atoi(optarg);
  842.          break;
  843.       case 'o':
  844.          offset = atoi(optarg);
  845.          break;
  846.       case '?':
  847.       default:
  848.          (void) fprintf(stderr, "usage: maz [xyhvfmo]\n");
  849.          break;
  850.       }
  851.  
  852.    if (maze(maz, y, x, ver, hor, flo) == 0) {
  853.       for (i = 0; i < (x * y); ++i) {
  854.          (void) putchar(maz[i]);
  855.          if (((i + 1) % x) == 0)
  856.             (void) putchar('\n');
  857.       }
  858.    } else {
  859.       (void) fprintf(stderr, "Couldn't make the maze\n");
  860.    }
  861.  
  862.    exit(0);
  863. }
  864. #endif DEBUG
  865.  
  866.  
  867.          hor = *optarg;
  868.  
  869.          break;
  870.  
  871.       case 'v':
  872.  
  873.          ver = *optarg;
  874.  
  875.          break;
  876.  
  877.       case 'f':
  878.  
  879.          flo = *optarg;
  880.  
  881.          break;
  882.  
  883.       case 'y':
  884.  
  885.          y = atoi(optarg);
  886.  
  887.          break;
  888.  
  889.       case 'x':
  890.  
  891.          x = atoi(optarg);
  892.  
  893.          break;
  894.  
  895.       case 'm':
  896.  
  897.          multiple = atoi(optarg);
  898.  
  899.          break;
  900.  
  901.       case 'o':
  902.  
  903.          offset = atoi(optarg);
  904.  
  905.          break;
  906.  
  907.       case '?':
  908.  
  909.       default:
  910.  
  911.          (void) fprintf(stderr, "usage: maz [xyhvfmo]\n");
  912.  
  913.          break;
  914.  
  915.       }
  916.  
  917.  
  918.  
  919.    if (maze(maz, y, x, ver, hor, flo) == 0) {
  920.  
  921.       for (i = 0; i < (x * y); ++i) {
  922.  
  923.          (void) putchar(maz[i]);
  924.  
  925.          if (((i + 1) % x) == 0)
  926.  
  927.             (void) putchar('\n');
  928.  
  929.       }
  930.  
  931.    } else {
  932.  
  933.       (void) fprintf(stderr, "Couldn't make the maze\n");
  934.  
  935.    }
  936.  
  937.  
  938.  
  939.    exit(0);
  940.  
  941. }
  942.  
  943. #endif DEBUG
  944.  
  945.  
  946.  
  947. ... This BBS has achieved Air superiority.
  948. ---
  949.  * Blue Wave/QWK v2.11 *
  950.                                                                                                
  951.