⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 maze-faq

📁 迷宫
💻
📖 第 1 页 / 共 2 页
字号:
        }    }    /*init hedges*/    for(j=0;j<(y-1);j++){        for(i=0;i<x;i++){            hedge[x*j+i].x = i;            hedge[x*j+i].y = j;            hedge[x*j+i].pos=DOWN;            hedge[x*j+i].on=1;            hedge_list[x*j+i]= &hedge[x*j+i];        }    }    k=x*(y-1);    for(j=0;j<y;j++){        for(i=0;i<(x-1);i++){            hedge[k+(x-1)*j+i].x = i;            hedge[k+(x-1)*j+i].y = j;            hedge[k+(x-1)*j+i].pos=RIGHT;            hedge[k+(x-1)*j+i].on=1;            hedge_list[k+(x-1)*j+i]= &hedge[k+(x-1)*j+i];        }    }    k=(x*(y-1))+((x-1)*y);    /*randomize hedges*/    for(i=(k-1);i>0;i--){        htmp=hedge_list[i];        j=random()%i;        hedge_list[i]=hedge_list[j];        hedge_list[j]=htmp;    }    fflush(stdout);    l=k;    /*create maze*/    for(i=0;i<l;i++){        j=hedge_list[i]->x;        k=hedge_list[i]->y;        a=find(&maze[x*k+j]);        if(hedge_list[i]->pos==DOWN){            b=find(&maze[x*(k+1)+j]);        } else {            b=find(&maze[x*k+j+1]);        }        if(a!=b){            link(a,b);            hedge_list[i]->on=0;        }    }    printf("+");    for(i=0;i<x;i++){        printf("-+");    }    printf("\n");    l=x*(y-1);    for(j=0;j<y;j++){        printf("|");        for(i=0;i<(x-1);i++){            if(hedge[l+(x-1)*j+i].on){               printf(" |");            } else {               printf("  ");            }        }        printf(" |\n|");        if(j<(y-1)){            for(i=0;i<x;i++){               if(hedge[j*x+i].on){                   printf("--");               } else {                   printf(" -");               }            }            printf("\n");        }    }    for(i=0;i<x;i++){        printf("-+");    }    printf("\n");}========================================Excerpts from programming: 9-Mar-92 Re: Algorithm to create a m.. DonGillies@m.cs.uiuc.ed (609)Here is another algorithm I just thought of -- how well does it work?1.  create a GRAPH with n*n nodes.2.  for each node in the graph create 4 edges, linking it to the    node in the north, south, east, and west direction.3.  Assign a random weight to every edge.4.  Run a minimum spanning tree algorithm (take your choice    from any algorithms textbook) to produce a graph.  A minimum    spanning tree has a path from every node to every other node,    and no cycles, hence, it corresponds to a perfect maze.Don Gillies - gillies@cs.uiuc.edu - University of Illinois at Urbana-Champaign========================================Excerpts from programming: 8-Apr-92 re mazes Chris_Okasaki@LOCH.MESS. (5437)Thanks for the messages.  FYI, here is the maze tutorial I used to send out.Chris--------------This seems to come up every couple of months, doesn't it?  Maybe weshould make a FAQL for this group...Anyway, maze generation--a topic near and dear to my heart!  I'm goingto describe the three most common methods.  Note that these will allgenerate mazes without loops or rooms or anything like that.  Restrictinga maze to be a tree (in the graph-theoretical sense of the term) simplifiesthings immensely.  Mazes with loops are much harder to generate automaticallyin any nice way.  Perhaps the best way is start out generating a tree andthen knock a couple of extra walls (all the algorithms start out with allwalls present and then knock out walls as necessary).Finally, note that all of these techniques are based on well-known graphalgorithms.  This isn't surprising since what is being generated isreally nothing more than a spanning tree.Technique #1: Depth-first search1. Pick a random starting location as the "current cell" and mark it   as "visited".  Also, initialize a stack of cells to empty (the stack   will be used for backtracking).  Initialize VISITED (the number of   visited cells) to 1.2. While VISITED < the total number of cells, do the following:     If the current cell has any neighbors which haven't yet been visited,       pick one at random.  Push the current cell on the stack and set the       current cell to be the new cell, marking the new cell as visited.       Knock out the wall between the two cells.  Increment VISITED.     If all of the current cell's neighbors have already been visited, then       backtrack.  Pop the previous cell off the stack and make it the current       cell.This algorithm is probably the simplest to implement, but it has a problemin that there are many mazes which it cannot generate.  In particular, it willcontinue generating one branch of the maze as long as there are unvisited cellsin the area instead of being able to give up and let the unvisited cells getused by a different branch.  This can be partially remedied by allowing thealgorithm to randomly backtrack even when there are unvisited neighbors, butthis creates the possibility of (potentially large) dead spaces in themaze.  For some applications, such as dungeon creation, this behaviormight be desirable.  A refinement which cuts down on the amount of dead spaceis to vary the probability of backtracking as an increasing function on thenumber of iterations since the last backtrack.Technique #2: Prim's Algorithm1. Maintain three sets of cells: IN, OUT, and FRONTIER.  Initially, choose   one cell at random and place it in IN.  Place all of the cell's neighbors in   FRONTIER and all remaining cells in OUT.2. While FRONTIER is not empty do the following:  Remove one cell at random   from FRONTIER and place it in IN.  If the cell has any neighbors in   OUT, remove them from OUT and place them in FRONTIER.  The cell is   guaranteed to have at least one neighbor in IN (otherwise it would   not have been in FRONTIER); pick one such neighbor at random and connect   it to the new cell (ie knock out a wall).This algorithm works by growing a single tree (without concentratingon any one particular branch like the previous algorithm).  An interestingvariation on this algorithm is to run two (or more) instances of itat once, starting in different locations and generating non-interesectingtrees.  This can be useful, for instance, for generating multiple disjointareas on a single level of a dungeon (perhaps connected by secret doorsor perhaps requiring adventurers to blast through walls themselves).Technique #3: Kruskal's AlgorithmThis is perhaps the most advanced of the maze generation algorithms,requiring some knowledge of the union-find algorithm.  It is also themost fun to watch in progress!Basically what the union-find algorithm does is give you a FASTimplementation of equivalence classes where you can do two things:FIND which equivalence class a given object belongs to, or UNIONtwo equivalance classes into a single class.  Any moderately advancedbook on algorithms and data structures will have more details.In this algorithm, the objects will be cells in the maze, and twoobjects will be in the same equivalence class iff they are (perhapsindirectly) connected.1. Initialize the union-find structures so that every cell is in   its own equivalence class.  Create a set containing all the interior   walls of the maze (ie those walls which lie between neighboring cells).   Set COUNT to the number of cells.  (COUNT is the number of connected   components in the maze).2. While COUNT > 1 do the following:     Remove a wall from the set of walls at random.  If the two cells     that this wall separates are already connected (test by doing a FIND     on each), then do nothing; otherwise, connect the two cells (by     UNIONing them and decrementing COUNT) and knock out the wall.Note that none of these algorithms make any assumptions about the topologyof the maze.  They will work with 2-d or 3-d grids, toroids, hexagons,whatever.  However, in the more highly connected topologies (such as 3-dgrids), the deficiencies of the first algorithm will become even more apparent(it will tend to produce long, winding paths with very little branching).Have fun with these!Chris================================/* * maz.c - generate a maze * * algorithm posted to rec.games.programmer by jallen@ic.sunysb.edu * program cleaned and reorganized by mzraly@ldbvax.dnet.lotus.com * * don't make people pay for this, or I'll jump up and down and * yell and scream and embarass you in front of your friends... * * compile: cc -o maz -DDEBUG maz.c * */#include <stdio.h>static int      multiple = 57;  /* experiment with this? */static int      offset = 1;     /* experiment with this? */#ifdef __STDC__int maze(char maz[], int y, int x, char vc, char hc, char fc);void mazegen(int pos, char maz[], int y, int x, int rnd);#elseint maze();void mazegen();#endif/* * maze() : generate a random maze of size (y by x) in maz, using vc as the * vertical character, hc as the horizontal character, and fc as the floor * character * * maz is an array that should already have its memory allocated - you could * malloc a char string if you like. */#ifdef __STDC__int maze(char maz[], int y, int x, char vc, char hc, char fc)#elseint maze(maz, y, x, vc, hc, fc)char            maz[], vc, hc, fc;int             y, x;#endif{   int             i, yy, xx;   int             max = (y * x);   int             rnd = time(0L);   /* For now, return error on even parameters */   /* Alternative is to decrement evens by one */   /* But really that should be handled by caller */   if (!(y & 1) | !(x & 1))      return (1);   /* I never assume... */   for (i = 0; i < max; ++i)      maz[i] = 0;   (void) mazegen((x + 1), maz, y, x, rnd);   /* Now replace the 1's and 0's with appropriate chars */   for (yy = 0; yy < y; ++yy) {      for (xx = 0; xx < x; ++xx) {         i = (yy * x) + xx;         if (yy == 0 || yy == (y - 1))            maz[i] = hc;         else if (xx == 0 || xx == (x - 1))            maz[i] = vc;         else if (maz[i] == 1)            maz[i] = fc;         else if (maz[i - x] != fc && maz[i - 1] == fc                 && (maz[i + x] == 0 || (i % x) == (y - 2)))            maz[i] = vc;         else            maz[i] = hc;       /* for now... */      }   }   return (0);}/* * mazegen : do the recursive maze generation * */#ifdef __STDC__void mazegen(int pos, char maz[], int y, int x, int rnd)#elsevoidmazegen(pos, maz, y, x, rnd)   int             pos, y, x, rnd;   char            maz[];#endif{   int             d, i, j;   maz[pos] = 1;   while (d = (pos <= x * 2 ? 0 : (maz[pos - x - x] ? 0 : 1))          | (pos >= x * (y - 2) ? 0 : (maz[pos + x + x] ? 0 : 2))          | (pos % x == x - 2 ? 0 : (maz[pos + 2] ? 0 : 4))          | (pos % x == 1 ? 0 : (maz[pos - 2] ? 0 : 8))) {      do {         rnd = (rnd * multiple + offset);         i = 3 & (rnd / d);      } while (!(d & (1 << i)));      switch (i) {      case 0:         j = -x;         break;      case 1:         j = x;         break;      case 2:         j = 1;         break;      case 3:         j = -1;         break;      default:         break;      }      maz[pos + j] = 1;      mazegen(pos + 2 * j, maz, y, x, rnd);   }   return;}#ifdef DEBUG#define MAXY 24#define MAXX 80#ifdef __STDC__main(int argc, char *argv[])#elsemain(argc, argv)   int             argc;   char           *argv[];#endif{   extern int      optind;   extern char    *optarg;   int             x = 79;   int             y = 23;   char            hor = '-';   char            ver = '|';   char            flo = ' ';   char            maz[MAXY * MAXX];   int             i;   while ((i = getopt(argc, argv, "h:v:f:y:x:m:o:")) != EOF)      switch (i) {      case 'h':         hor = *optarg;         break;      case 'v':         ver = *optarg;         break;      case 'f':         flo = *optarg;         break;      case 'y':         y = atoi(optarg);         break;      case 'x':         x = atoi(optarg);         break;      case 'm':         multiple = atoi(optarg);         break;      case 'o':         offset = atoi(optarg);         break;      case '?':      default:         (void) fprintf(stderr, "usage: maz [xyhvfmo]\n");         break;      }   if (maze(maz, y, x, ver, hor, flo) == 0) {      for (i = 0; i < (x * y); ++i) {         (void) putchar(maz[i]);         if (((i + 1) % x) == 0)            (void) putchar('\n');      }   } else {      (void) fprintf(stderr, "Couldn't make the maze\n");   }   exit(0);}#endif DEBUG

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -