..⋯口⋯
实用第一 智慧密集
.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ⋯⋯ , ⋯⋯沪
摘 要 介绍了一种随机生成二维迷宫的方法 , 并用 V C 编程实现 。
关键词 迷宫 , v c
玩过 RPG 游戏的朋友一定遇到过各种各样的迷宫 , 迷宫
道路错综复杂 , 千变万化 , 如 《仙剑奇侠传》 , 那么这些迷宫
是怎样生成的呢? 生成迷宫的算法又是什么呢? 下面就给出一
个随机生成二维迷宫的方法 , 并用 V C 编程实现 。
一 、 随机生成迷宫的方法
迷宫的本质就是一幅地图 , 因此程序的核心问
题
快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题
就是如何
生成一幅二维地图。 步骤如下 : 首先 , 生成地图的框架 , 即定
义地图的大小 , 得到地图的外围边界 ; 其次 , 在图中生成一条
连接起点和终点的通路 , 保证玩家可以走出迷宫 ; 然后 , 保证
地图的强连通性 , 在图中尽可能多地生成一些围墙 , 构成多条
“死” 路 , 用于迷惑玩家 ; 最后 , 用连线的方法画出迷宫。 下
面分别介绍各步骤的实现方法。
1
. 生成地图的框架
普通的地图都是按块来划分的 , 定义一个平面地图的大小
其实只需定义一个二维数组即可 , 比如说定义一个 6 * 4 的地
图 , 那么就得定义一个【4 1【6] 的数组 , 数组的数据
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示地图中
的块 , 再加上地图的边界 , 所 以一个 声ize * xs ize 的地 图由
(
x siz e + 2 ) ’ (ysi
z e + 2 )个块构成 , 如图 l所示 。 为图中每个块
斌一个数值 , 表示块与块之间是否连通 。 外围的块赋值为 -
1
, 表示地图的边界 , 中间的块赋值为 0 , 表示初始状态 。
后点 (x , y) 就从迷宫的起点开始移动 , 上 、 下 、 左 、 右方向
分别由数值 0 、 l 、 2 、 3 表示 , 每走一步的方向由随机数 0 、
1
、
2
、
3 决定 。 如果有路可走 , 即前进方向的块的数值为零 ,
则前进到新的块 , 并令 s 二 s + l , 将 S 赋值给新块 。 如果四周
均已无路可走(四周无数值为零的变量 ) , 则退回到 。一 1 处 ,
寻找 。 一 l 四周的变量还有没有路可走(。一 1 代表来时的路) ,
如找到 , 则 。二 , 一 l , 并且退回先前位置 , 继续找路前进 , 否
则便结束算法 。 如果点(x , y)已经到达终点 , 同样会结束算
法。 图 2 表示了一条按此算法随机生成的通路 , 由图 2 中的阴
影方块表示 , 方块 l为起点 (xl , yl) , 方块 21 为终点 (x2 ,
yZ)
, 数值相差为 1 的方块连通 , 按数值递增 1 的顺序 , 从编
号为 1 的方块到编号为 21 的方块 , 恰好生成一条通路 。
一
1
一
1
。
1
。
1
一
1
一
1
。
1
0 0
一
1
0 0
一
1
’
0 0
一
l
D
.
0
一
1
一
1
一
1
一
l
nUnU一llU工llUnUllU一IIU肠11甘nU11一一U一llUnU11一日一nU
一
1
·
1
圈 1
·
1
。
1
‘.二‘.占..二..二J.几‘孟己
地圈模块设t
圈 2 随机生成的通路
3
. 保证地图的强连通性
当生成一条由起点到终点的随机路线后 , 地图上仍有封闭
的区域 , 为了尽可能多地生成一些 “死” 路 , 用于迷惑玩家 ,
需要生成强连通图。 强连通图的概念是 , 在一个有向图 G 中 ,
对于 G 的任意两个不同的顶点 vi 和 vj , 都存在从 vi 到 vj 以及
从 vj 到 vi 的路径。 因此 , 需要遍历地图上所有未赋值的点 ,
随机地为这些点赋值 , 生成更多的路线 , 注意赋值应大于
1口以) , 以便区分上一步得到的那些表示通路的块 , 如图 3 所
尔。
2
. 生成一条连接起点和终点的通路
如图 2 所示 , 编号为 l 的块表示迷宫的起点 , 编号为 21
的块表示迷宫的终点 , 即玩家需要从地图的右下方走到左上
方 。 设起点的坐标是 ( x l, yl) , 终点的坐标是 (x Z, yZ ) , (x , y )
表示一个在图中移动的点 , (x , y )的初始值等于起点坐标 , 即
x 二 x l , y 二 yl , s 代表点 ( x , y)移动的步数 , S 初始值为 l , 然 图 3 生成强连通路
瑙器污‘动卜
实用第一 智慧密集
..⋯二.⋯沪
示右、下、左、上 * /
xx 二 x + 《r 二 = O》一 《r 二 = 2 );
W o y + 《r 二 二” 一 《r = 二 3) ;
/ , 得到新点 《拟 , Yy } , 该点是随机产生的. 不一定是连通点
* /
w hile《Ma ze 【yy l【联】! 二0 )
/ . 当(xx , yy 》走不通时 , 继续找可以连通的点 , /
王
r == 门nd (l% 4 ;
众 二 x + 《r 二 == O) 一 《r 二 二 2 );
YY == y + 《r == = 1》一 (r == == 3 );
}
X = XX 二y 目W ; S + + ;
/ . 更新移动点的坐标, 增加步数 s 的值 . /
M aze ly ! lx ! 二 民 / , 将 s狱值于新位t ‘ /
}
etse /
. 如果没有连通点 , 则退回到 s 一 1 处, 寻找 s -
1 四周的变份还有没有路可走 * /
《
fo r(i== O二i< 4 ; i+ + )
(
众 二 x + 《i二 二O) 一《i二 二 2 );
W 二y + (i= = 1 ) 一《i二 == 3 );
if《Maz e 【YY 】【众】== == s 一 1》
气
筑 == 众:y 二Yy ; s = M az e 【yl!x l;
brea k;
}
}
if( i= 二引 / . 5 一 1 处也无路可走 , 便结束算法 * /
bre 日k二
)
)
fat U m O:
函
关于工期滞后的函关于工程严重滞后的函关于工程进度滞后的回复函关于征求同志党风廉政意见的函关于征求廉洁自律情况的复函
数 in t * * In itw all (in t , in t ) , 用于初始化迷宫中的围
代码如下 :
CMez e : : tn it协白JI(i爪XS IZ e , in tys iz e
.
W日l七
}甄in·
int
.
infi
.
W妇11二 n . w int ‘ fysiZ e 千1 1;
fo r(i二 O; i < vsize + 1 : i+ + )
W 妇阴川 == n . w intIXS IZe + 1 1;
/ * 为二维数组W a U分配内存 · /
fo r (i二 O: i < ysize + 1 ; i+ + 》
fOr (j
= O; 1< 城Size + 1 ;i+ + )
W 妇Illil ljl ‘0: / , 数组W al!初始值为 O, 表示尚无围墙 · /
f6t u m w 妇I!;
函数 B OOL Init Maz e () , 用于初始化迷宫 , 为迷宫中水平
方向和垂直方向的围墙赋值。 生成迷宫后 , 把表示迷宫的图形
存储为 emf 类型的文件 , e mf (Enh an c ed Me画le )文件是徽软公
司开发的一种 W ind o w s 犯 位扩展图元文件格式 , 扩展名为
.
emf
。 本 程序用 到的操 作 e mf 文件 的 API 函 数有 C二·
a te Enh Me taF il
e
()
,
Mo veT
o E x ()
,
Lin eT O ()
,
Pl 叮E n hM eta File () ,
关于这些函数的用法请参考 《MSD N》 , 在此不再详述 。 实现
的代码如下 :
B 0 0 LCM az e : 二In itM aze ()
《
eu rre n娜 二 x slz e 一 2 ;
eu rre n切 二 ysjz e 一 1 ;
/ * tc u rren你 , eu rre n切 )是起点坐标 * /
HD C hde Em f 二 C『e ate En hM ete File 《NULL. ‘ . m f. Om f尸 ,
NU LL
,
NULL》;
/ . 得到 e m f文件的句柄 , ’e m f. em f’保存迷宫的圈形 . /
日W all 二 !n恻all (YS ize , xs泛e) ; / . 初始化水平方向的圈幼 . /切四. 1! == In it\勺a l一(vsiz e , x s iz e ); z * 初始化垂直方向的圈墙 . /
in t i
: 且二
fo r 《i二 0 : i< x siz e ; i + + 】
HW a ll【i】! 0 1 = 1 ;
for 《i== 0 ; i< ysiz e ; i + + )
功四日!!IOJ 川 二 , ; / * 迷宫的边缘要画线, 表示有圈墙 . /
Recta
n g !e 《hde Em f. 0 . 0 , STEP* xsiz e + 1 , ST EP* ys iz e + 1 );
Se泊ct o bj6Ct (hd e Em f
,
Ge tstoc ko bjec t(BLA CK尹EN》》;
Mov eTo Ex 《hd eEmf , 0 . 0 , N ULL);
U n eTO (hd e Em f
,
STEP
* x siz e + 1
,
0 );
Mov eTo Ex 《hde Em f, 0 , 0 , NU LL》:
Lin eTo 《hd e Em f. 0 . ST EP * ysize + 1 ):
M o v eTo Ex 《hd eEm f, ST EP * x s iz e + 1 , 0 , NU LL》;
Lin eTO {hd e Em f
,
STEP
. x size + 1
,
STEP
* ysiz e + 1 );
Mo v eTo E x (hde Em f
,
0
,
STEP * ys ize + 1
,
NULL) ;
Un eTo (hd e Em f
,
STEP
* x siz e + 1咭STEP* ys iz e + 1 );
/ * 以上几句画出迷宫的外围 * /
/ . 下面的二重循环根据 M aze 数组表示的迷宫中各块的连通
情况 . 画出迷宫内部的围墙 * /
fo r《i二 1 ; i< ysiz e + 1 ; i+ + )
fo r(1二 1 ; 1< x siz e + 1 ; i+ + )
《
in t t 二 a bs(M az e 111 [11 一 M az e 111fi+ 1 1);
if(! (t < 二 1 }} (t 一 10 0 0 ) , 二 M az e lil ljl }It -
1 0 00 二 = Ma z e li】11+ 1 1》)
{
Mov eTO E
x (hd eE m f
,
j* ST EP
,
i* STEP 一 ST EP, NULL};
LineTO 《hde Em f, i* ST EP, i* ST EP》;
if (!功四日1111】11 一 1】》切四日!fl川 i一 1】二 1 ;
}
t == ab s (M a ze ! 11 !i】一 Ma z e li + 1】l川 ;
jf‘! 《t < 二 1 ! 1 (t 一 100 0 ) 二 = Ma z e lil fi】小 -
1 00 0 = = M a z e ! i+ 1 】[川 )
{
娜 2 00 8 . 1