哈哈!终于摆平了!!!
算法思路:
在迷宫中随机撒下“种子点”,由这些种子点不断的生长、拼接,最终生成有且只有一条通路
的理想迷宫。
在生成过程中,采用了LastPoint和RepeatLastDir两个0..1的变量进行控制,可以生成不同
风格的迷宫——Perfect!
算法性能:在P4 1.6G上生成100*100的迷宫耗时6秒。
由于源代码太长,不便全部贴出,现将关键类文件的 Interface 部分贴出来。需要源代码的
富翁请发邮件到 creation_zy@sina.com,为了不增大本贴的长度,如果只是要代码的话请不要
跟贴,发mail即可,谢谢合作!
unit Maze;
interface
uses
Graphics, ExtCtrls, Classes, SysUtils;
const
CriticalWallID=256;
//临界墙壁ID——两个ID均小于等于它的墙壁不能合并
type
PWord=^Word;
TBooleanPointerFunc=function (P
ointer):Boolean;
TSupList=class(TList)
private
FValidCount: Integer;
function GetValidCount: Integer;
public
property ValidCount:Integer read GetValidCount;
procedure SoftDelete(const DelIndex:Integer);
procedure SoftUndelete(const UndelIndex:Integer);
procedure SoftDeleteByValue(const P
ointer);
procedure SoftUndeleteByValue(const P
ointer);
function AddValid(Item: Pointer): Integer;
function AddInvalid(Item: Pointer): Integer;
function AutoSoftDel(Func:TBooleanPointerFunc):Integer;
procedure Jion(SList: TSupList);
procedure DisposeList;
procedure FreeList;
procedure Clear;
override;
constructor Create;
end;
TWordPoint=Record
X,Y:Word;
end;
TMaze=class;
TMazeWall=class
private
FMaze: TMaze;
SelfID: Integer;
FPointList: TSupList;
FLastPoint: TWordPoint;
FLastDirection: Byte;
function GetLen: Integer;
function GetExpCount: Integer;
public
property Len:Integer read GetLen;
property ExpandableCount:Integer read GetExpCount;
property LastPoint:TWordPoint read FLastPoint;
property LastDirection:Byte read FLastDirection;
procedure AddPoint(const P: TWordPoint);
procedure DelPoint(const P: TWordPoint);
procedure Jion(Wall: TMazeWall);
procedure Growth;
function GetPoint(const Index: Word):TWordPoint;
constructor Create(OwnerMaze: TMaze;
ID: Integer);
destructor Destroy;
override;
end;
TPreDefineMazeUnit=(muNotDef,muEmpty,muWall);
MazeUnitRec=Record
Kind:Byte;
//0: Empty 1: Wall
WallID:Integer;
FreeDirNum:Byte;
Age:Word;
//越小表示生成的越早
PreDef:TPreDefineMazeUnit;
//预设单元
end;
TMaze=class
private
FData:array of array of MazeUnitRec;
FSpaceCount: Cardinal;
FTotalCount: Cardinal;
FWallCount: Cardinal;
FWidth: Cardinal;
FHeight: Cardinal;
FWallList: TList;
FFreeSeekCount: Integer;
FAge: Word;
FWallID: Integer;
FWallCountBeforeCritical: Word;
FStop: Boolean;
procedure SetHeight(const Value: Cardinal);
procedure SetWidth(const Value: Cardinal);
function GetHeight: Cardinal;
function GetWidth: Cardinal;
procedure AllocateSpace;
procedure FreeSpace;
function CanMake:Boolean;
function GetANewWallID:Integer;
procedure SetMazeUnit(P:TWordPoint;Empty_Wall:Boolean;WallID:Integer);
procedure PrepareWallID;
procedure MakeNewSeek;
procedure RefreshFreeDirNumRound(const P: TWordPoint);
function CanJion(x1,y1,x2,y2:Cardinal):Boolean;
public
RepeatLastDir:Single;
LastPoint:Single;
property Width:Cardinal read GetWidth write SetWidth;
property Height:Cardinal read GetHeight write SetHeight;
property TotalCount:Cardinal read FTotalCount;
property SpaceCount:Cardinal read FSpaceCount;
property WallCount:Cardinal read FWallCount;
procedure Clear;
function NewWall(StartPoint:TWordPoint):TMazeWall;
procedure Generate;
procedure MakeDefaultWall;
procedure Stop;
procedure SetElement(x,y:Cardinal;Empty_Wall:Boolean);
procedure Draw(Image:TImage;
WallWidth: Integer;
WallColor,BlankColor,OutsideColor:TColor;
ShiftX,ShiftY:Integer);
function SaveToFile(const FileName:String):Boolean;
function SaveToBitMap(const FileName:String):Boolean;
function LoadFromFile(const FileName:String):Boolean;
function LoadFromBitMap(const FileName:String):Boolean;
function IsValidWallPoint(P:TWordPoint):Boolean;
function IsValidEmptyPoint(P:TWordPoint):Boolean;
function CanWrite(P:TWordPoint):Boolean;
function WallByID(const WallID: Integer):TMazeWall;
constructor Create;
destructor Destroy;
override;
end;