& D& c9 y, F& U8 F, p
主要逻辑为: , w% |: e9 a( K/ i( e7 jwhile(search(0)!=search(aa*aa-1))//主要思路 / F: ^/ l4 B+ V5 \ {% Q2 u- h( e; n/ J$ H1 H, w& @7 S
var num = parseInt(Math.random() * aa*aa );//产生一个小于196的随机数; P( f4 _; Y( X5 F* h
var neihbour=getnei(num); $ P, M" E1 z4 G2 W F- R if(search(num)==search(neihbour)){continue;}5 H% p9 D1 T5 `, f1 x P) l
else//不在一个上/ Q7 R6 {2 E% V
{ W9 U. U0 }) h8 Y8 u0 ^' S isling[num][neihbour]=1;isling[neihbour][num]=1;1 ]: Q' H& y; T7 o9 n5 F
drawline(num,neihbour);//划线 " S) L; z' C. X- f8 p/ t8 H5 a9 A union(num,neihbour);. ]/ d! j: E# t' L
+ o1 o H4 @+ z8 Z } ( h0 Z! a3 `- d, m } : _3 ^! A: \% ?% D; e 5 e2 ]- G% l, m8 e' p7 p) ?$ o/ R* _9 }+ o; b {
那么在前面的代码为 : A5 A& ?0 x; g, K<!DOCTYPE html>! }. O+ w8 ~% D) `- t% w8 ?! E$ ^
<html>1 w: x6 V2 R$ F1 |3 L
<head>& i7 ]: i1 K/ `5 x% e" u( Z
<title>MyHtml.html</title> $ p6 t$ w3 T! C* R- N2 p% M
</head> % O% Z) o3 u I* a# _ <body>+ u. Z P# J) O6 a' b2 i+ e0 `, ~2 t
<canvas id="mycanvas" width="600px" height="600px"></canvas> 6 H4 `' O6 B2 P% A3 A2 Z7 A/ m$ a& R I2 l/ m- h( H
</body>1 i& a+ a4 }0 w
<script type="text/javascript">% d7 l2 F/ N- |7 B
//自行添加上面代码 i6 Y0 e/ J2 ]( B8 r9 H7 i2 L; b // var mymap=new Array(36);7 y* c) U6 Q( h+ D* L
// for(var i=0;i<36;i++) ' ?, F; [. p$ ~1 l // {mymap=-1;}: U3 k7 ~( Z- [5 \
function getnei(a)//获得邻居号 random 1 z! u$ U( M5 A% K7 a { 7 a( C0 \1 x1 ? a' c+ E var x=parseInt(a/aa);//要精确成整数0 O! ^! r; x1 q, z9 V Y
var y=a%aa; V: P2 X$ w: c$ @ var mynei=new Array();//储存邻居 4 k3 c8 u/ x" y$ H; P if(x-1>=0){mynei.push((x-1)*aa+y);}//上节点! \+ J" q! T3 P6 R7 L
if(x+1<14){mynei.push((x+1)*aa+y);}//下节点 2 V6 Y. i3 }6 w* Y if(y+1<14){mynei.push(x*aa+y+1);}//有节点0 A4 w3 x" ^2 f
if(y-1>=0){mynei.push(x*aa+y-1);}//下节点% X3 @/ v- h; v' H5 p2 i
var ran=parseInt(Math.random() * mynei.length ); : S1 R0 m& @' R/ a5 R( x; T* ]6 r9 ~9 U return mynei[ran]; 4 ~" s. X) N% [ * |8 M- }0 `& o, R6 Z1 Q } & M; A0 ^3 s# ~8 }+ l$ Z1 T/ K function search(a)//找到根节点 l1 h4 |. M2 C2 d9 H { & p0 t4 s# I! \8 e% s if(tree[parseInt(a/aa)][a%aa]>0)//说明是子节点0 G" @9 y* O; n' r& L( Q
{ : U) I, P) u8 V; C& v( M return search(tree[parseInt(a/aa)][a%aa]);//不能压缩路径路径压缩3 w5 H' E8 n% D( I ^0 X
} # _1 p: P! l1 e else9 B. f* u" R b/ C+ a: ^) O" [- P: B
return a;* u3 W7 O+ D; P2 p
}) ~: k/ i5 v/ D2 @8 F( V; _
function value(a)//找到树的大小 ( ^+ q" r/ V1 G" i {6 ]7 t2 L1 h" n8 _2 |8 I* A
if(tree[parseInt(a/aa)][a%aa]>0)//说明是子节点 3 g' f. U/ T" y3 A* H) ?7 f, ` {' J' x' o7 a% ~) K0 N1 Q
return tree[parseInt(a/aa)][a%aa]=value(tree[parseInt(a/aa)][a%aa]);//不能路径压缩 / ~/ c7 P4 P7 k" C1 P6 P } ) w4 P0 [& z3 B/ ` else ; q4 x" L6 t3 U* x3 u return -tree[parseInt(a/aa)][a%aa];, u% _# D% X! t* s3 [$ U0 j) {8 d
} p4 i( Z) y6 _5 \ v
function union(a,b)//合并! N( A; T# P6 k. }
{% `& W) S9 _2 f2 K0 U4 w7 W! ]. C( x
var a1=search(a);//a根 / D; Q; W% S% C var b1=search(b);//b根 ! C+ |4 P& ^/ k2 R if(a1==b1){} % S8 a9 l# {0 q; e1 p else ) a5 ?% A& i5 I% Q {5 `) Z1 P/ K2 w. U( e6 Q4 F4 I
if(tree[parseInt(a1/aa)][a1%aa]<tree[parseInt(b1/aa)][b1%aa])//这个是负数(),为了简单减少计算,不在调用value函数 8 D2 c* K. E3 F {$ i4 Y, } ]6 Z) `
tree[parseInt(a1/aa)][a1%aa]+=tree[parseInt(b1/aa)][b1%aa];//个数相加 注意是负数相加! v/ ^0 h9 C; s1 I, w V+ E8 u2 D
tree[parseInt(b1/aa)][b1%aa]=a1; //b树成为a树的子树,b的根b1直接指向a;- R' ]+ x: _, E$ P0 Z
}$ D8 J7 }2 ?: E, Y T' d
else- Z3 Y0 M, ?: Q( \% I
{3 y7 ]& A+ E7 A' j0 B0 Z$ S
tree[parseInt(b1/aa)][b1%aa]+=tree[parseInt(a1/aa)][a1%aa];8 G, l5 \3 E0 J p, S0 O$ R' u" ^5 _
tree[parseInt(a1/aa)][a1%aa]=b1;//a所在树成为b所在树的子树 - N6 |4 j# R4 L6 e# ^/ {( R }; O1 \' X9 _3 u" k+ R
}, a/ f7 ~( i5 a4 A
} 6 U. F; I' W- I3 A. h# J+ M0 s, p z* X) c8 }4 K6 }% _5 W
function drawline(a,b)//划线,要判断是上下还是左右 7 I8 ~$ P" |+ b% e0 _+ x {6 [2 j/ Z$ O5 {
$ u2 G/ w1 G% V; h& c8 W
var x1=parseInt(a/aa);5 v% D; {1 }3 c: V+ i+ f; o8 u
var y1=a%aa; ' l1 S1 W1 o7 Y) }- d, s var x2=parseInt(b/aa); 7 P3 ~- m0 U+ I2 C( z0 P' U var y2=b%aa; * o& d6 J9 P: K/ u/ @8 d" k$ `
var x3=(x1+x2)/2; [. {' P" N% T0 B; |
var y3=(y1+y2)/2;0 d' ~0 Z" R7 q, T, e# }
if(x1-x2==1||x1-x2==-1)//左右方向的点 需要上下划线8 b+ h* J% s/ A& Z$ k
{" e7 @# i# N2 p! ]9 i
//alert(x1);7 S! w2 v, G$ L% ~- Y
// context.beginPath();7 Y+ q x: x4 }8 j
context.strokeStyle = 'white';, O6 z- Q' L$ J3 c' g" B
// context.moveTo(30+x3*30,y3*30+15);// . B$ r1 g" I* `; W: ~ // context.lineTo(30+x3*30,y3*30+45);7 H; l2 A* g: P3 _9 V
context.clearRect(29+x3*30, y3*30+16,2,28);2 {' i A0 T2 F
// context.stroke(); 2 E2 x5 \' s& P5 [6 m }5 u' ~2 C# _' ~0 c& u( E3 K
else) W2 [5 U. i. ]
{ % H O/ p' R: p // context.beginPath(); 7 O1 Q( `; X" x/ E5 \' }) | context.strokeStyle = 'white'; G' L# e" S$ o# M0 j0 U
// context.moveTo(x3*30+15,30+y3*30);// 2 q# V3 E. Y+ Z# O3 c e0 u // context.lineTo(45+x3*30,30+y3*30); - q1 _* B1 @" l5 C0 S- r context.clearRect(x3*30+16, 29+y3*30,28,2); % a1 i) i, O' B4 e // context.stroke(); 3 x2 l1 c" m$ E! f G" `5 ?) X }$ f; J* K% y1 u0 h: @7 y; v
}$ B2 B$ t. l, i: I1 J
3 O R0 U) w: T/ M, @7 X while(search(0)!=search(aa*aa-1))//主要思路 1 U- l+ L) @, U. f# X* l { * ^/ b, n4 z$ Q; f var num = parseInt(Math.random() * aa*aa );//产生一个小于196的随机数 1 a7 A, V/ s' N2 { var neihbour=getnei(num); $ }1 e, a4 ]7 w( y, R' | if(search(num)==search(neihbour)){continue;}% V4 ^6 W* k8 [+ X! e$ [: K
else//不在一个上 x- _% R& C- E; L x5 r, `% z
{ - R q. i7 n9 V! K1 p: \8 J# m; ?# O isling[num][neihbour]=1;isling[neihbour][num]=1;+ b2 S$ Y+ S Y* k# x
drawline(num,neihbour);//划线* g; u) M# ?" S9 Z9 g8 Y* q
union(num,neihbour);8 {9 L9 r/ L6 w" d: O) A
3 b. r: x D8 c. W8 ]' V7 _% K% e
} % W( A2 F- C5 n. Y: }9 g- I. A }( X6 d) b; @5 e: q: f: `- j
</script> B7 ]+ t: w* d. _
</html> 1 F" C' W7 k3 X ) W( w: z" m8 A; P! d ! m. [0 z! O' M: e" L& E实现效果:5 R P. C e) z+ \ a: }6 Y# c
2 ^- E0 i; F9 C- x$ f# T0 N e
- f; O: ^, }+ N$ m$ w5 h" g5 E
, a& R7 M8 o Z2 V% e% Z
; a2 j6 ~ [/ d5 c方块移动 " O) l* d% G, b! b. I) y* W7 G( ~ R
这部分我采用的方法不是动态真的移动,而是一格一格的跳跃。也就是当走到下一个格子将当前格子的方块擦掉,在移动的那个格子中再画一个方块。选择方块是因为方块更方便擦除,可以根据像素大小精准擦除。 p9 H: @, f; R
" V& \( Z( s4 @ ]# P; Q
另外,再移动中要注意不能穿墙、越界。那么怎么判断呢?很好办,我们再前面会判断两个格子是否联通,如果不连通我们将把这个墙拆开。再拆的时候把这个墙的时候记录这两点拆墙可走即可(数组): f: r, s7 v- J8 ]% W
! ?3 F. p$ p" _3 ]. ^
另外,事件的监听上下左右查一查就可以得到,添加按钮对一些事件监听,这些不是最主要的。2 X. Q5 Y; y7 f, l r+ P z8 k) b9 r
2 L$ b3 Y/ S+ n2 X- m! p5 B- }0 m
为了丰富游戏可玩性,将方法封装,可以设置关卡(只需改变迷宫大小)。这样就可以实现通关了。另外,如果写成动态存库那就更好了。 + R% \8 ~$ S" C) n
! s# E" H( y, Q
6 O. E: B5 @! [* D # h2 [" s7 p, F. r8 r. V- M———————————————— $ \* r; `% Y9 X1 c( S% b版权声明:本文为CSDN博主「Big sai」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。: C. w4 P7 t" R5 F3 Z2 D8 ~/ e' E
原文链接:https://blog.csdn.net/qq_40693171/article/details/100716766 ! s9 [' p. n( R: l/ h. z9 _0 N6 ?5 T; H2 h( A, r! Q