作业内容三选一,感觉迷宫还行,可以做做,发现迷宫的恰当表示和随机生成有学问啊
迷宫生成是将迷宫全部初始化为墙,然后打通墙,制造迷宫的过程
递归回溯算法
递归分割算法
随机Prim算法
Kruskal算法
这篇博客有动图可以帮助理解 迷宫生成
这里使用Prim算法
这里的随机使一般的最小生成树Prim算法有所区别,该如何随机选择墙打通呢?
void srand(unsigned int seed) 播种由函数 rand 使用的随机数发生器。
int rand(void) 返回一个范围在 0 到 RAND_MAX 之间的伪随机数。
使用时间作为种子
srand(time(NULL));
srand ((int) time ((time_t *) NULL));
设迷宫宽为width,高为height
表示迷宫一般是使用 \(width * height\) 大小的矩阵来表示,一个单元表示迷宫的通路与否。
如 11 * 4
.*****...**
..**...*.*.
*.*..*.*.*.
*....***...
.表示通路
*或者#表示障碍
但是为了更好的表示迷宫,表示迷宫与通路的关系,方便我们观看
使用 墙 + 单元 的方式来表示迷宫
则还需一圈外围围住迷宫的围墙
可以上下左右的走
总共需要 \((2*width + 1)*(2*height + 1)\) 大小的内存来表示
如 4 * 2
+-+-+-+-+
| | | | |
+-+-+-+-+
| | | | |
+-+-+-+-+
空格为一个迷宫单元,其他为墙
可以上下左右,且对角线的走
这样可以表示单元的上下左右与对角线的通路情况,虽然丑
很明显,一个九宫格,周围八个都是墙,中间是迷宫的单元
总共需要\((3 * height) * (3 * width)\) 大小的内存
如3 * 3
/=\/=\/=\
| || || |
\=/\=/\=/
/=\/=\/=\
| || || |
\=/\=/\=/
/=\/=\/=\
| || || |
\=/\=/\=/
主要有三种解法
这里使用的深度优先搜索 ( DFS )
一条路走到黑,走不动就返回,直到走到终点
DFS就不作过多陈述
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | |
+ +-+-+-+ + +-+ + +-+-+ + +-+ + +-+ +-+-+ + + +-+ + + + + +-+ +-+-+-+-+-+-+ + +
| | | | | | | | | | | | | | | | | | | | |
+-+ + + + +-+ + +-+-+ +-+-+-+-+-+ + + +-+-+ +-+ +-+ +-+ +-+-+-+ + + +-+-+-+ + +
| | | | | | | | | | | | | | | | | | | | | |
+ +-+ + +-+ + + + + +-+ + + + + +-+-+-+-+ +-+ + + +-+ +-+ +-+ +-+ + + +-+ +-+-+
| | | | | | | | | | | | | | | | | | | | | | |
+ +-+-+ +-+-+-+ +-+ + + +-+-+-+ +-+ + +-+-+ +-+-+ + + + +-+-+ + +-+ + + +-+ + +
| | | | | | | | | | | | | | | | | | | |
+-+-+-+-+-+-+ + + +-+-+ +-+-+-+-+ + + +-+-+-+ +-+-+ + +-+-+ +-+-+-+-+ +-+ + + +
| | | | | | | | | | | | | | | | |
+ +-+-+-+-+-+ +-+-+ +-+-+ + +-+-+ + + +-+-+ + + + + +-+-+ +-+-+-+-+ + + + +-+ +
| | | | | | | | | | | | | | | | | | | |
+-+-+ + +-+-+-+-+ +-+-+ +-+ + + +-+-+-+-+-+-+-+ +-+-+ + +-+-+ + + +-+ + +-+ + +
| | | | | | | | | | | | | | | | | | |
+-+ + + + + + + +-+-+ +-+ +-+ +-+-+ +-+-+ + +-+-+ + +-+-+-+ + + +-+-+-+ + +-+-+
| | | | | | | | | | | | | | | | | | | | |
+ +-+ + +-+-+-+ + + +-+ +-+ +-+-+ + +-+ + +-+-+-+ + +-+ +-+-+-+-+ +-+-+-+ +-+ +
| | | | | | | | | | | | | | | | | | | |
+-+-+-+ +-+ +-+-+ + +-+ + +-+ + +-+-+ + +-+-+ + +-+-+-+-+ + + + + + + +-+-+ + +
| | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+.+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|. | | | | |....... | |...| | | |
+.+-+-+-+ + +-+ + +-+-+ + +-+ + +-+.+-+-+.+ + +-+ +.+.+ + +-+ +-+-+-+-+-+-+ + +
|...|...| | | | | | |...|.....| | | |.|...| | | | | |
+-+.+.+.+ +-+ + +-+-+ +-+-+-+-+-+.+ +.+-+-+ +-+ +-+.+-+.+-+-+-+ + + +-+-+-+ + +
|...|.|.| | | | | | |...| |.....| | |...|...| | | |.....| |
+.+-+.+.+-+ + + + + +-+ + + + +.+-+-+-+-+.+-+ + +.+-+.+-+ +-+ +-+ + +.+-+.+-+-+
|.....|.| | | | | | | |. |.....| | |.| |... | | | |.|...|...|
+ +-+-+.+-+-+-+ +-+ + + +-+-+-+.+-+ +.+-+-+ +-+-+.+ + +.+-+-+ + +-+ +.+.+-+.+.+
| |.......| | | |.........| | |. |.....| | |.....| | |.|...|.|.|
+-+-+-+-+-+-+.+ + +-+-+.+-+-+-+-+ + +.+-+-+-+.+-+-+ + +-+-+.+-+-+-+-+.+-+.+.+.+
| .| |.....|...| | |.......|.| | | |.........|.| |...|.|
+ +-+-+-+-+-+.+-+-+.+-+-+.+.+-+-+ + + +-+-+.+.+ + + +-+-+ +-+-+-+-+.+.+ + +-+.+
| | |.....|.......|.| | | |...| | | | | |...|.| | |.|
+-+-+ + +-+-+-+-+.+-+-+ +-+.+ + +-+-+-+-+-+-+-+ +-+-+ + +-+-+ + +.+-+.+ +-+ +.+
| | | | |.....| |...| | | | | | | | |.....| |.....|
+-+ + + + + + + +-+-+.+-+.+-+ +-+-+ +-+-+ + +-+-+ + +-+-+-+ + + +-+-+-+ +.+-+-+
| | | | | | | |...|...| | | | | | | | | |.| |
+ +-+ + +-+-+-+ + + +-+.+-+.+-+-+ + +-+ + +-+-+-+ + +-+ +-+-+-+-+ +-+-+-+.+-+ +
| | | | | |...|...| | | | | | | | | | |...| |
+-+-+-+ +-+ +-+-+ + +-+ +.+-+.+ +-+-+ + +-+-+ + +-+-+-+-+ + + + + + + +-+-+.+ +
| | | |..... | | | | | | |...|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+.+
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define WIDTH 39
#define HEIGHT 11
#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3
#ifdef TRUE
#undef TRUE
#endif /* TRUE */
#define TRUE 1
#define cell_empty(a) (!(a)->up && !(a)->right && !(a)->down && !(a)->left)
typedef struct {
unsigned int up : 1;//占一位
unsigned int right : 1;
unsigned int down : 1;
unsigned int left : 1;
unsigned int path : 1;
unsigned int visited : 1;
}cell;
typedef cell * maze_p;
void CreateMaze (maze_p maze, int width, int height);
void SolveMaze (maze_p maze, int width, int height);
void PrintMaze (maze_p maze, int width, int height);
int SolveMazeRec (maze_p maze, maze_p mp, int width, int height);
int main (int argc, char *argv [])
{
int width = WIDTH;
int height = HEIGHT;
maze_p maze;
if (argc >= 2)
width = atoi (argv [1]);//atoi函数, 将一个字符串转化为整数
if (argc >= 3)
height = atoi (argv [2]);
if (argc >= 4)
srand (atoi (argv [3]));//随机种子
else
srand ((int) time ((time_t *) NULL));// 用系统时初始化随机种子
if (width <= 0 || height <= 0)
{
(void) fprintf (stderr, "Illegal width or height value!\n");//错误输出流
exit (EXIT_FAILURE);
}
maze = (maze_p) calloc (width * height, sizeof (cell));//申请迷宫大小
if (maze == NULL) //申请失败
{
(void) fprintf (stderr, "Cannot allocate memory!\n");//错误输出流
exit (EXIT_FAILURE);//宏定义的常量,是1;EXIT_SUCCESS 0
}
CreateMaze (maze, width, height);//随机生成迷宫
PrintMaze (maze, width, height);//打印迷宫
(void) puts("\n\nThe solve of maze:\n");
//SolveMaze (maze, width, height);//解决迷宫
SolveMazeRec (maze, maze, width, height);
PrintMaze (maze, width, height);//打印迷宫
free (maze);//释放
exit (EXIT_SUCCESS);
return (0);
}/* main */
void CreateMaze (maze_p maze, int width, int height)
{
maze_p mp, maze_pop;
char paths [4];
int visits, directions;
visits = width * height - 1;//去掉
mp = maze;
maze_pop = mp + (width * height) - 1;//右下角终点
while (visits)
{
directions = 0;
// 指针比大小,其实就是地址的比较
if ((mp - width) >= maze && cell_empty (mp - width))
paths [directions ++] = UP;
if (mp < maze_pop && ((mp - maze + 1) % width) && cell_empty (mp + 1))//判断是不是最右
paths [directions ++] = RIGHT;
if ((mp + width) <= maze_pop && cell_empty (mp + width))
paths [directions ++] = DOWN;
if (mp > maze && ((mp - maze) % width) && cell_empty (mp - 1)) //判断是不是最左
paths [directions ++] = LEFT;
//在mp可选择的路中随机一个
if (directions)
{
visits--;
directions = ((unsigned) rand () % directions);
switch (paths [directions])
{
case UP:
mp->up = TRUE;//标记这个cell向上走
(mp -= width)->down = TRUE;//相反,走过去的cell标记为向下走
break;
case RIGHT:
mp->right = TRUE;
(++mp)->left = TRUE;
break;
case DOWN:
mp->down = TRUE;
(mp += width)->up = TRUE;
break;
case LEFT:
mp->left = TRUE;
(--mp)->right = TRUE;
break;
default:
break;
}
} else //没有可走的cell
{
do
{
if (++mp > maze_pop)//超过了就回到起点
mp = maze;
} while (cell_empty (mp)); // 找到一个已被打通的cell
}
}
}/* CreateMaze */
int SolveMazeRec (maze_p maze, maze_p mp, int width, int height)
{
mp->visited = TRUE;
if(mp == (maze + (width * height) - 1))
{
mp->path = TRUE;
return 0;
}
for(int sel = UP; sel <= LEFT; sel ++ )
{
switch(sel)
{
case UP:
if (mp->up && !(mp - width)->visited)
{
if( ! SolveMazeRec (maze, mp - width, width, height) )
{
mp->path = TRUE;
return 0;
}
}
break;
case RIGHT:
if (mp->right && !(mp + 1)->visited)
{
if( ! SolveMazeRec (maze, mp + 1, width, height) )
{
mp->path = TRUE;
return 0;
}
}
break;
case DOWN:
if (mp->down && !(mp + width)->visited)
{
if( ! SolveMazeRec (maze, mp + width, width, height) )
{
mp->path = TRUE;
return 0;
}
}
break;
case LEFT:
if (mp->left && !(mp - 1)->visited)
{
if( ! SolveMazeRec (maze, mp - 1, width, height) )
{
mp->path = TRUE;
return 0;
}
}
break;
default:
break;
}
}
return 1;
}
void SolveMaze (maze_p maze, int width, int height)
{
maze_p *stack, mp = maze;
int sp = 0;
stack = (maze_p *) calloc (width * height, sizeof (maze_p));
if (stack == NULL)
{
(void) fprintf (stderr, "Cannot allocate memory!\n");
exit (EXIT_FAILURE);
}
// 起点已访问
(stack [sp++] = mp)->visited = TRUE;
while (mp != (maze + (width * height) - 1)) //没到终点
{
if (mp->up && !(mp - width)->visited)//可走上,上没去过
stack [sp++] = mp - width;
if (mp->right && !(mp + 1)->visited)
stack [sp++] = mp + 1;
if (mp->down && !(mp + width)->visited)
stack [sp++] = mp + width;
if (mp->left && !(mp - 1)->visited)
stack [sp++] = mp - 1;
if (stack [sp - 1] == mp)
--sp;//如果走到头了,那就回去一步
(mp = stack [sp - 1])->visited = TRUE;//两步
}
while (sp--)//遍历一遍,标记为路径
if (stack [sp]->visited)
stack [sp]->path = TRUE;
free (stack);
}/* SolveMaze */
void PrintMaze (maze_p maze, int width, int height)
{
int w, h;
char *line, *lp;
line = (char *) calloc ((width + 1) * 2, sizeof (char));
if (line == NULL)
{
(void) fprintf (stderr, "Cannot allocate memory!\n");
exit (EXIT_FAILURE);
}
maze->up = TRUE;
(maze + (width * height) - 1)->down = TRUE;
// 第一行
for (lp = line, w = 0; w < width; w++)
{
*lp++ = '+';
if ((maze + w)->up) //如果为出迷宫路径,则为 . ,否则为 空
*lp++ = ((maze + w)->path) ? '.' : ' ';
else
*lp++ = '-';
}
//一行 长 2*width + 1
*lp++ = '+';
(void) puts (line);
//system("pause");
for (h = 0; h < height; h++)//
{
for (lp = line, w = 0; w < width; w++)
{
if ((maze + w)->left)
*lp++ = ((maze + w)->path && (maze + w - 1)->path) ? '.' : ' ';
else
*lp++ = '|';//墙
*lp++ = ((maze + w)->path) ? '.' : ' ';
}
*lp++ = '|';
(void) puts (line);
for (lp = line, w = 0; w < width; w++)
{
*lp++ = '+';
if ((maze + w)->down)
*lp++ = ((maze + w)->path && (h == height - 1 ||
(maze + w + width)->path)) ? '.' : ' ';
else
*lp++ = '-';
}
*lp++ = '+';
(void) puts (line);
maze += width;
}
free (line);
}/* PrintMaze */
/ \/=\/=\/=\/=\/=\/=\/=\/=\/=\/=\
| || || || || || || || |
\=/ =/\ /\= \=/\=/ =/\ / /\=/\ /
/= /=\/ \/=\ =\/= /=\/ / \/=\/ \
| || || || || || || |
\ \ /\=/\ \=/\=/\=/\=/\=/\ /\ /
/ \ \/=\/ \ =\/=\/=\/=\/=\/ \/ \
| || || || || || || || || |
\= \=/ / =/\=/\ \=/ =/\= = \=/
/=\ = / /=\/=\/ \ = /=\/= =\ =\
| || || || || || || || |
\= = \= =/\ /\ \= \=/\=/\= \ /
/= =\ = =\/ \/ \ =\ =\/=\/=\ \
| || || || || || || || || |
\=/\=/\=/\=/\=/\=/\=/\=/\=/\=/\ /
/.\/=\/=\/=\/=\/=\/=\/=\/=\/=\/=\
|....||....|| || ||....||.|| || |
\=/.=/\./\=.\=/\=/.=/\./../\=/\ /
/=./=\/.\/=\.=\/=./=\/../.\/=\/ \
|. ||....||....|| ||.||....|| |
\. \ /\=/\. \=/\=/\=/\=/\=/\./\ /
/.\ \/=\/.\ =\/=\/=\/=\/=\/.\/ \
|.|| ||.||.|| || || ||....||. |
\=.\=/../.=/\=/\ \=/.=/\=..= \=/
/=\.=./../=\/=\/ \ =./=\/=..=\ =\
| ||.||.|| || ||.......||.|| |
\= = \= =/\ /\ \= \=/\=/\=.\ /
/= =\ = =\/ \/ \ =\ =\/=\/=\. \
| || || || || || || || ||.|
\=/\=/\=/\=/\=/\=/\=/\=/\=/\=/\./
/*
* @Author: Az1r
* @Date: 2022-09-30 20:47:13
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define WIDTH 9
#define HEIGHT 5
#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3
#define UL 4
#define UR 5
#define DL 6
#define DR 7
#ifdef TRUE
#undef TRUE
#endif /* TRUE */
#define TRUE 1
#define cell_empty(a) (!(a)->up && !(a)->right && !(a)->down && !(a)->left && !(a)->ul && !(a)->ur && !(a)->dl && !(a)->dr)
typedef struct {
unsigned int up : 1;//表示占1位
unsigned int right : 1;
unsigned int down : 1;
unsigned int left : 1;
unsigned int ul : 1;
unsigned int ur : 1;
unsigned int dl : 1;
unsigned int dr : 1;
unsigned int path : 1;
unsigned int visited : 1;
}cell;
typedef cell * maze_p;
void CreateMaze (maze_p maze, int width, int height);
void PrintMaze (maze_p maze, int width, int height);
int SolveMazeRec (maze_p maze, maze_p mp, int width, int height);//递归版
void SolveMaze (maze_p maze, int width, int height);//非递归版
int main (int argc, char *argv [])
{
int width = WIDTH;
int height = HEIGHT;
int select = 0;
maze_p maze;
if (argc >= 2)
width = atoi (argv [1]);//atoi函数,字符串转整数
if (argc >= 3)
height = atoi (argv [2]);
if (argc >= 4)
srand (atoi (argv [3]));//随机种子
else
srand ((int) time ((time_t *) NULL));//以时间作为随机种子
if(argc >= 5)
{
select = atoi (argv [4]);
}
if (width <= 0 || height <= 0)
{
(void) fprintf (stderr, "Illegal width or height value!\n");//error输出流
exit (EXIT_FAILURE);
}
maze = (maze_p) calloc (width * height, sizeof (cell));
if (maze == NULL)
{
(void) fprintf (stderr, "Cannot allocate memory!\n");
exit (EXIT_FAILURE);//内置的宏定义EXIT_SUCCESS 0 ,EXIT_FAILURE 1
}
CreateMaze (maze, width, height);//随机生成迷宫
PrintMaze (maze, width, height);//打印
(void) puts("\n\n");
if(select == 0)
{
SolveMaze (maze, width, height);
}else
{
SolveMazeRec (maze, maze, width, height);
}
/*
随机生成迷宫的算法为prim算法,prim算法是最小生成树算法
所以,每个迷宫单元都是连通的
那么入口到出口一定存在一条通路
若不算故意重复走的路径,那么这条通路是唯一的
则,也是最短的
*/
PrintMaze (maze, width, height);
free (maze);//释放
exit (EXIT_SUCCESS);
return (0);
}/* main */
void CreateMaze (maze_p maze, int width, int height)
{
maze_p mp, maze_pop;
char paths [8];
int visits, directions;
visits = width * height - 1;//除去入口
mp = maze;
maze_pop = mp + (width * height) - 1;// 出口
while (visits)
{
directions = 0;
//找墙的过程
if ((mp - width) >= maze && cell_empty (mp - width))//若可以打通上面的墙,下同理
paths [directions ++] = UP;
if (mp < maze_pop && ((mp - maze + 1) % width) && cell_empty (mp + 1))
paths [directions ++] = RIGHT;
if ((mp + width) <= maze_pop && cell_empty (mp + width))
paths [directions ++] = DOWN;
if (mp > maze && ((mp - maze) % width) && cell_empty (mp - 1))
paths [directions ++] = LEFT;
if ((mp - 1 - width) >= maze && ((mp - maze) % width) && mp > (maze + width - 1) && cell_empty (mp - 1 - width))
paths [directions ++] = UL;
if ((mp + 1 - width) > maze && ((mp - maze + 1) % width) && mp > (maze + width - 1) && cell_empty (mp + 1 - width))
paths [directions ++] = UR;
if ((mp - 1 + width) < maze_pop && ((mp - maze) % width) && mp <= (maze_pop - width) && cell_empty (mp - 1 + width))
paths [directions ++] = DL;
if ((mp + 1 + width) <= maze_pop && ((mp - maze + 1) % width) && mp <= (maze_pop - width) && cell_empty (mp + 1 + width))
paths [directions ++] = DR;
// 随机的过程
if (directions)
{
visits--;
directions = ((unsigned) rand () % directions);
switch (paths [directions])
{
case UP:
mp->up = TRUE; //该单元上墙打通
(mp -= width)->down = TRUE;//该单元上面的单元,下墙打通
break; //以下同理
case RIGHT:
mp->right = TRUE;
(++mp)->left = TRUE;
break;
case DOWN:
mp->down = TRUE;
(mp += width)->up = TRUE;
break;
case LEFT:
mp->left = TRUE;
(--mp)->right = TRUE;
break;
case UL:
mp->ul = TRUE;
(mp -= width + 1)->dr = TRUE;
break;
case UR:
mp->ur = TRUE;
(mp -= width - 1)->dl = TRUE;
break;
case DL:
mp->dl = TRUE;
(mp += width - 1)->ur = TRUE;
break;
case DR:
mp->dr = TRUE;
(mp += width + 1)->ul = TRUE;
break;
default:
break;
}
} else //没有符合条件的墙
{
do
{
if (++mp > maze_pop)//超过了出口,就再从入口找起
mp = maze;
} while (cell_empty (mp)); // 符合条件
}
}
}/* CreateMaze */
int SolveMazeRec (maze_p maze, maze_p mp, int width, int height)
{
mp->visited = TRUE;
if(mp == (maze + (width * height) - 1))//可以走到出口就是0
{
mp->path = TRUE;
return 0;
}
for(int sel = UP; sel <= DR; sel ++ )
{
switch(sel)
{
case UP:
if (mp->up && !(mp - width)->visited)//可以走上,下同
{
if( ! SolveMazeRec (maze, mp - width, width, height) )
{
mp->path = TRUE;
return 0;
}
}
break;
case RIGHT:
if (mp->right && !(mp + 1)->visited)
{
if( ! SolveMazeRec (maze, mp + 1, width, height) )
{
mp->path = TRUE;
return 0;
}
}
break;
case DOWN:
if (mp->down && !(mp + width)->visited)
{
if( ! SolveMazeRec (maze, mp + width, width, height) )
{
mp->path = TRUE;
return 0;
}
}
break;
case LEFT:
if (mp->left && !(mp - 1)->visited)
{
if( ! SolveMazeRec (maze, mp - 1, width, height) )
{
mp->path = TRUE;
return 0;
}
}
break;
case UL:
if (mp->ul && !(mp - 1 - width)->visited)
{
if( ! SolveMazeRec (maze, mp - 1 - width, width, height))
{
mp->path = TRUE;
return 0;
}
}
break;
case UR:
if (mp->ur && !(mp + 1 - width)->visited)
{
if( ! SolveMazeRec (maze, mp + 1 - width, width, height))
{
mp->path = TRUE;
return 0;
}
}
break;
case DL:
if (mp->dl && !(mp - 1 + width)->visited)
{
if (! SolveMazeRec (maze, mp - 1 + width, width, height))
{
mp->path = TRUE;
return 0;
}
}
break;
case DR:
if (mp->dr && !(mp + 1 + width)->visited)
{
if (! SolveMazeRec (maze, mp + 1 + width, width, height))
{
mp->path = TRUE;
return 0;
}
}
break;
default:
break;
}
}
return 1;
}
void SolveMaze (maze_p maze, int width, int height)
{
maze_p *stack, mp = maze;
int sp = 0;
stack = (maze_p *) calloc (width * height, sizeof (maze_p));
if (stack == NULL)
{
(void) fprintf (stderr, "Cannot allocate memory!\n");
exit (EXIT_FAILURE);
}
//入口走过了
(stack [sp++] = mp)->visited = TRUE;
while (mp != (maze + (width * height) - 1)) //出口
{
if (mp->up && !(mp - width)->visited)//判断是否可走,且是否走过;下面同理
stack [sp++] = mp - width;
if (mp->right && !(mp + 1)->visited)
stack [sp++] = mp + 1;
if (mp->down && !(mp + width)->visited)
stack [sp++] = mp + width;
if (mp->left && !(mp - 1)->visited)
stack [sp++] = mp - 1;
if (mp->ul && !(mp - 1 - width)->visited)
stack [sp++] = mp - 1 - width;
if (mp->ur && !(mp + 1 - width)->visited)
stack [sp++] = mp + 1 -width;
if (mp->dl && !(mp - 1 + width)->visited)
stack [sp++] = mp - 1 + width;
if (mp->dr && !(mp + 1 + width)->visited)
stack [sp++] = mp + 1 + width;
if (stack [sp - 1] == mp)
--sp;//无路可走,那就回退
(mp = stack [sp - 1])->visited = TRUE;//这其实是两步
}
while (sp--)//回退栈,栈中保存的符合条件的即为路径
if (stack [sp]->visited)
stack [sp]->path = TRUE;
free (stack);
}/* SolveMaze */
void PrintMaze (maze_p maze, int width, int height)
{
int w, h;
char *line, *lp;
line = (char *) calloc ((width + 1) * 3, sizeof (char));
if (line == NULL)
{
(void) fprintf (stderr, "Cannot allocate memory!\n");
exit (EXIT_FAILURE);
}
maze->up = TRUE;
(maze + (width * height) - 1)->down = TRUE;
//system("pause");
for (h = 0; h < height; h++)
{
for (lp = line, w = 0; w < width; w++) //上层
{
if ((maze + w)->ul)//若墙通,则要么走过,要么没走
*lp++ = ((maze + w)->path && (maze + w - 1 - width)->path) ? '.' : ' ';
else //墙不通则打印墙
*lp++ = '/';
if ((maze + w)->up)
*lp++ = ((maze + w)->path && ((maze + w - width)->path || h == 0) )? '.' : ' ';
else
*lp++ = '=';
if ((maze + w)->ur)
*lp++ = ((maze + w)->path && (maze + w + 1 - width)->path) ? '.' : ' ';
else
{
*lp++ = '\\';
}
}
(void) puts (line);
for (lp = line, w = 0; w < width; w++) //中层
{
if ((maze + w)->left)
*lp++ = ((maze + w)->path && (maze + w - 1)->path) ? '.' : ' ';
else
*lp++ = '|';
*lp++ = ((maze + w)->path) ? '.' : ' ';
if ((maze + w)->right)
*lp++ = ((maze + w)->path && (maze + w + 1)->path) ? '.' : ' ';
else
*lp++ = '|';
}
(void) puts (line);
for (lp = line, w = 0; w < width; w++) //单元的下层围墙
{
if ((maze + w)->dl)
*lp++ = ((maze + w)->path && (maze + w - 1 + width)->path) ? '.' : ' ';
else
{
*lp++ = '\\';
}
if ((maze + w)->down)
*lp++ = ((maze + w)->path && ( (maze + w + width)->path || (h + 1) == height) ) ? '.' : ' ';
else
*lp++ = '=';
if ((maze + w)->dr)
*lp++ = ((maze + w)->path && (maze + w + 1 + width)->path) ? '.' : ' ';
else
{
*lp++ = '/';
}
}
(void) puts (line);
maze += width;
}
free (line);
}/* PrintMaze */
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
由于fast-stemmer的问题,我很难安装我想要的任何rubygem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。