unit R36; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls; type TRoom = record //房间记录类型 Used : Byte; Xpos : Byte; //区块位置 Ypos : Byte; Xsiz : Byte; //区块大小 Ysiz : Byte; UX : Byte; //上侧出入口位置 UY : Byte; DX : Byte; //下侧 DY : Byte; LX : Byte; //左侧 LY : Byte; RX : Byte; //右侧 RY : Byte; end; TRei36 = class(TForm) Button1: TButton; Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Timer1Timer(Sender: TObject); private { Private declarations } procedure MkRoom; procedure MkMaze; procedure Tline(a,b:Byte); procedure Lway; procedure Mway; procedure Rway; procedure DiMaze; public { Public declarations } end; const Mwidth = 50 * 10 + 20; //迷宫宽度 Mheight = 30 * 10 + 20; //迷宫高度 var Rei36: TRei36; MakeBmap : TBitmap; RectD : TRect; St,m,max : Byte; Mdata : array[0..49,0..29] of Byte; //迷宫数组50*30点 Box : array[0..14] of TRoom; //房间数组 15房间 ,记录数组类型 implementation {$R *.dfm} procedure TRei36.FormCreate(Sender: TObject); begin Rei36.Canvas.CopyMode := cmSrcCopy; MakeBmap := TBitmap.Create; MakeBmap.Width := Mwidth; MakeBmap.Height := Mheight; St := 1; //初始迷宫制作指令 Randomize; end; procedure TRei36.MkRoom; //制作房间参数 var n : byte; begin for n := 0 to 14 do Box[n].Used := 0; //房间清零 max := 5 + Random(5); //最大5+4个房间? m := 0; repeat n := Random(15); if (Odd(n) = False) and (Box[n].Used = 0) then //保证偶数块有房间3个 begin Box[n].Used := 1; m := m + 1; end; until m = 4; repeat //随机房间数量到MAX n := Random(15); if (n <> 7) and (Box[n].Used = 0) then begin Box[n].Used := 1; m := m + 1; end; until m > max; for n := 0 to 14 do with Box[n] do begin if Used = 1 then begin //设置房间大小,最小4+0+0=4,最大4+2+3=9 Xsiz := 4 + ((n + 1) mod 2) * 2 + Random(4); //这里为什么要引入n? Ysiz := 4 + ((n + 1) mod 2) * 2 + Random(4); //实际是为了控制奇区4-7,偶区6-9 end else begin //非房间大小 Xsiz := 4; Ysiz := 4; end; //设置房间位置,注意非房间也有位置的。放中间 Xpos := (n mod 5) * 10 + (10 - Xsiz) div 2; //5列,取余得到X块 Ypos := (n div 5) * 10 + (10 - Ysiz) div 2; //取商得到Y块 if Used = 1 then begin UX := Xpos + 1 + Random(Xsiz - 2); //上出口 UY := Ypos; DX := Xpos + 1 + Random(Xsiz - 2); //下出口 DY := Ypos + Ysiz - 1; LX := Xpos; //左出口 LY := Ypos + 1 + Random(Ysiz - 2); RX := Xpos + Xsiz - 1; //右出口 RY := Ypos + 1 + Random(Ysiz - 2); end else begin UX := Xpos; UY := Ypos; DX := UX; DY := UY; LX := UX; LY := UY; RX := UX; RY := UY; end; end; for n := 0 to 3 do //左右间隙小于3则修改成直连 ? if Box[n + 1].LX - Box[n].RX <= 3 then begin Box[n].RY := 4 + Random(2); Box[n + 1].LY := Box[n].RY; end; for n:= 5 to 8 do if Box[n + 1].LX - Box[n].RX <= 3 then begin Box[n].RY := 14 + Random(2); Box[n + 1].LY := Box[n].RY; end; for n := 10 to 13 do if Box[n + 1].LX - Box[n].RX <= 3 then begin Box[n].RY := 24 + Random(2); Box[n + 1].LY := Box[n].RY; end; for n := 0 to 4 do //上下间隙间隙小于3则修改成直连 begin if Box[n + 5].UY - Box[n].DY <= 3 then begin Box[n].DX := 4 + Random(2) + n * 10; Box[n + 5].UX := Box[n].DX; end; if Box[n + 10].UY - Box[n + 5].DY <= 3 then begin Box[n + 5].DX := 4 + Random(2) + n * 10; Box[n + 10].UX := Box[n].DX; end; end; end; procedure TRei36.MkMaze; var x,y,n : Byte; begin for x := 0 to 49 do for y := 0 to 29 do Mdata[x,y] := 1; //全设置为墙 for n := 0 to 14 do if Box[n].Used = 1 then for x := Box[n].LX to Box[n].RX do for y := Box[n].UY to Box[n].DY do Mdata[x,y] := 2; //设置为房间 Lway; Mway; Rway; end; procedure TRei36.Tline(a,b:Byte); //制作通道 var nn,mx,my : Byte; begin if (b-a) = 1 then //房间相邻 begin //横向连接 mx := Box[b].LX - (Box[b].LX - Box[a].Xpos - Box[a].Xsiz + 2) div 2; //取得一个中间点 for nn := Box[a].RX to mx do Mdata[nn,Box[a].RY] := Mdata[nn,Box[a].RY] and 2; //通道穿过房间还是10B,穿过墙则是00B for nn := mx to Box[b].LX do Mdata[nn,Box[b].LY] := Mdata[nn,Box[b].LY] and 2; if Box[a].RY > Box[b].LY then //从中间点开始连接 for nn := Box[b].LY to Box[a].RY do Mdata[mx,nn] := Mdata[mx,nn] and 2 else if Box[a].RY < Box[b].LY then //这里为什么要重复判断? for nn := Box[a].RY to Box[b].LY do Mdata[mx,nn] := Mdata[mx,nn] and 2; end else begin //不相邻则纵向连接? my := Box[b].UY - (Box[b].UY - Box[a].Ypos- Box[a].Ysiz + 2) div 2; for nn := Box[a].DY to my do Mdata[Box[a].DX,nn] := Mdata[Box[a].DX,nn] and 2; for nn := my to Box[b].UY do Mdata[Box[b].UX,nn] := Mdata[Box[b].UX,nn] and 2; if Box[a].DX > Box[b].UX then for nn := Box[b].UX to Box[a].DX do Mdata[nn,my] := Mdata[nn,my] and 2 else if Box[a].DX < Box[b].UX then for nn := Box[a].DX to Box[b].UX do Mdata[nn,my] := Mdata[nn,my] and 2; end; end; procedure TRei36.Lway; //0 1 5 6 10 11 左侧房间连接规则 begin if Random(2) = 0 then begin Tline(0,1); Tline(0,5); Tline(1,6); if (Box[5].Used and Box[6].Used = 0) or (Random(2) = 0) then Tline(5,6); if Box[10].Used = 1 then begin Tline(5,10); if Random(2) = 0 then Tline(10,11) else Tline(6,11); end else if Random(2) =0 then begin Tline(5,10); Tline(10,11); end else Tline(6,11); end else begin Tline(10,11); Tline(5,10); Tline(6,11); if (Box[5].Used and Box[6].Used = 0) or (Random(2) = 0) then Tline(5,6); if Box[0].Used = 1 then begin Tline(0,5); if Random(2) = 0 then Tline(0,1) else Tline(1,6); end else if Random(2) = 0 then begin Tline(0,5); Tline(0,1); end else Tline(1,6); end; end; procedure TRei36.Mway; //1 2 3 11 12 13 的中侧房间连接规则 begin case Random(4) of 0: begin Tline(1,2); Tline(2,3); Tline(11,12); if Random(2) = 0 then Tline(12,13); end; 1: begin Tline(1,2); Tline(2,3); Tline(12,13); if Random(2) = 0 then Tline(11,12); end; 2: begin Tline(11,12); Tline(12,13); Tline(1,2); if Random(2) = 0 then Tline(2,3); end; 3: begin Tline(11,12); Tline(12,13); Tline(2,3); if Random(2) = 0 then Tline(1,2); end; end; end; procedure TRei36.Rway; // 3 4 8 9 13 14 右侧房间连接规则 begin if Random(2) = 0 then // 随机 begin Tline(3,4); //将3,4 3,8 4,9 房间连接起来 Tline(3,8); Tline(4,9); if (Box[8].Used and Box[9].Used = 0) or (Random(2) = 0) then Tline(8,9); //当8与9的其中之一不是房间时,以随机数将8,9连接起来 if Box[14].Used = 1 then //若14是房间 begin Tline(9,14); //连接9,14 if Random(2) = 0 then //再将13,14 或 8,13连接 Tline(13,14) else Tline(8,13); end else if Random(2) = 0 then //14不是房间 begin // 连接9,14 13 14 或 8,13 Tline(9,14); Tline(13,14); end else Tline(8,13); end else begin //随机另一规则 Tline(13,14); Tline(8,13); Tline(9,14); if (Box[8].Used and Box[9].Used = 0) or (Random(2) = 0) then Tline(8,9); if Box[4].Used = 1 then begin Tline(4,9); if Random(2) = 0 then Tline(3,4) else Tline(3,8); end else if Random(2) = 0 then begin Tline(3,4); Tline(4,9); end else Tline(3,8); end; end; procedure TRei36.DiMaze; //在制作画板上以10*10 的块显示Mdata数组 var x,y : Byte; begin for x := 0 to 49 do for y := 0 to 29 do begin case Mdata[x,y] of 0: MakeBmap.Canvas.Brush.Color := clBlack; 1: MakeBmap.Canvas.Brush.Color := clOlive; 2: MakeBmap.Canvas.Brush.Color := clNavy; end; RectD := Rect(x * 10 + 10,y * 10 + 10,x * 10 + 20,y * 10 + 20); // RectD := Rect(x + 10,y + 10,x + 10 + 1,y + 10 + 1); //缩小比例 MakeBmap.Canvas.FillRect(RectD); end; end; procedure TRei36.Button1Click(Sender: TObject); begin St := 2; end; procedure TRei36.FormClose(Sender: TObject; var Action: TCloseAction); begin MakeBmap.Free; end; procedure TRei36.Timer1Timer(Sender: TObject); begin case St of 1: begin //绘制外框 RectD := Rect(0,0,Mwidth,Mheight); MakeBmap.Canvas.Brush.Color := clOlive; MakeBmap.Canvas.FillRect(RectD); RectD := Rect(10,10,Mwidth - 20,Mheight - 20); MakeBmap.Canvas.Brush.Color := clBlack; MakeBmap.Canvas.FillRect(RectD); Rei36.Canvas.Draw(0,0,MakeBmap); St := 2; end; 2: begin //制作新的迷宫显示出来,按钮控制 MkRoom; //制作房间参数 MkMaze; DiMaze; Rei36.Canvas.Draw(0,0,MakeBmap); St := 0; end; end; end; end.
1,迷宫,一个二维的数组,对它进行0,1,2 的写入,里面有几个过程,或者叫做类的方法
写入 墙1 ,房间 2,通道0的数据
2,一个数组元素代表一个点,最后是用一个10* 10 像素的方块表示出来,做了下用1 * 1 的方块表现出来
3,程序结构大致是 设定好迷宫大小 50 × 30,分成 15个块
这15个块 有一定规则随机生成5-9 个房间,生成房间数据
4,按照左,中,右侧,有一定规则,对其侧房间进行通道连接
5,感觉就是人为规则的实现,其中是有限限度随机变化?
6,必须看书本上的图示来理解,然后自己手绘出来有助于理解
标签:Box,10,begin,end,Delphi,Random,36,40,Tline From: https://www.cnblogs.com/D7mir/p/16862998.html