CrackMe V2.6 设计思路+源码
CrackMe V2.6的注册算法源自文曲星上的一个小游戏《华容道》。先来简单的介绍下这个游戏吧O(∩_∩)O~。华容道游戏取自著名的三国故事,曹操在赤壁大战中被刘备和孙权的“苦肉计”、“火烧连营”打败,**退逃到华容道,又遇上诸葛亮的伏兵,关羽为了报答曹操对他的恩情,明逼实让,终于帮助曹操逃出了华容道。
游戏就是依照“曹瞒兵败走华容,正与关公狭路逢。只为当初恩义重,放开金锁走蛟龙”这一故事情节,通过移动各个棋子,帮助曹操从初始位置移到棋盘最下方中部,从出口逃走。不允许跨越棋子,还要设法用最少的步数把曹操移到出口。曹操逃出华容道的最大障碍是关羽,关羽立马华容道,一夫当关,万夫莫开。
成功的条件:
1.
首先定义一个全变数组变量Block,摆好位置,进行初始化,最终成功的条件应该是曹操跑出,也即4个9在数组的位置Block,Block,Block,Block5]。我这里为了简单,自己定义了一个初始化的局面,大家也可以由用户名和注册码进行运算后得出一个开局,这样就避免了开局的单一性。var
//初始化华容道
//0,1,2,3分别代表兵,卒,勇,丁
//4,5,6,7分别代表张飞,赵云,马超,黄忠,8代表关羽,9代表曹操 ,10代表空格子
Block : array of Integer =((0,9,9,1),
(2,9,9,3),
(4,8,8,5),
(4,6,7,5),
(10,6,7,10));
2.
下面就是每个人物的移动了,先确定移动的方向:
3.
游戏的设置都好了后,下面就应该是设计让人物开始移动了,怎么移动呢?移动有两个要素:一是谁移动,即对象,二是移动的方向。我们可以让用户名和注册码来决定移动的人物和移动的方向。procedure TForm1.Button1Click(Sender: TObject);
var
UserName : string;
RegCode : string;
DirectionSN : string; //移动方向序列
BlockSN : string; //移动的格子序列
strTemp : string; //临时字符串
LenUN, i : Integer;
begin
UserName := Edit1.Text;
RegCode:= Edit2.Text;
LenUN := Length(UserName);
if (UserName <> '') and (RegCode <> '') then
begin
//取出注册码中的前68位
while LenUN < 98 do
begin
UserName := UserName + UserName;
LenUN := Length(UserName);
end;
UserName := LeftStr(UserName, 98);
//得到移动序列
strTemp := '';
for i := 1 to 98 do
begin
strTemp := strTemp + IntToStr(Abs(byte(UserName) - byte(RegCode))) ;
end;
//得到移动的格子序列
BlockSN := '';
for i := 0 to 48 do
begin
BlockSN := BlockSN + strTemp;
end;
//得到移动方向序列
DirectionSN := '';
for i := 1 to 49 do
begin
DirectionSN := DirectionSN + strTemp;
end;
//游戏开始
for i := 1 to 49 do
begin
MoveBlock(StrToInt(BlockSN), StrToInt(DirectionSN));
end;
if (Block= Block) and (Block= Block) and (Block= Block) and (Block = 9)then
begin
try
i := i div reg;
except
MessageBox(0,'注册成功!','提示',0);
end;
strTemp := IntToStr(reg) + IntToStr(i);
end;
end;
我们作为CM的编写者,必须要知道这个游戏的解决方案是什么,也就是必须要知道每一步该怎么走,我这里简单起见,强制了走法,必须是49步走完游戏,否则就挂了,每一步都是用一个函数MoveBlock来实现。走完49步后,就要判断是不是曹操逃跑了,也即(Block= Block) and (Block= Block) and (Block= Block) and (Block = 9)。
4.我们来看下MoveBlock函数的具体实现过程://移动格子,参数BlockN是要移动的数字,Direction是移动的方向
//0,1,2,3分别代表
//0:↑
//1:→
//2:↓
//3:←
procedure MoveBlock(BlockN : Integer; Direction : Integer);
var
x,y,x1,x2,y1,y2,x3,y3,x4,y4,i,j : Integer;
label
lb1;
begin
x := 0;
y := 0;
////在矩阵中找到要移动的格子的位置x,y
for i := 1 to 5 do
begin
for j := 1 to 4do
begin
if Block = BlockN then
begin
x := j;
y := i;
goto lb1;
end;
end;
end;
lb1:
try
case BlockN of
0..3 ://选中的格子是兵,卒,勇,丁的其中一个
begin
case Direction of
0 :
begin
x1 := x; y1 := y-1;
end;
1 :
begin
x1 := x+1; y1 := y;
end;
2 :
begin
x1 := x; y1 := y+1;
end;
3 :
begin
x1 := x-1; y1 := y;
end;
else
reg := reg + 1;
end;
//判断下即将移动的位置是不是空的,是空的才能移,否则就挂!
if Block <> 10 then
reg := reg + 1
else
begin
Block := 10;//原来的位置就变成空格子了
Block := BlockN;
end;
end;
4..7 ://选中的格子是张飞,赵云,马超,黄忠的其中一个
begin
case Direction of
0:
begin
x1 := x;
x2 := x;
y1 := y-1;
y2 := y1+1;
if Block <> 10 then
reg := reg+1;
end;
1:
begin
x1 := x+1;
x2 := x+1;
y1 := y;
y2 := y+1;
if (Block <> 10) and (Block <> 10)then
reg := reg+1;
end;
2:
begin
x1 := x;
x2 := x;
y1 := y+2;
y2 := y1-1;
if Block <> 10 then
reg := reg+1;
end;
3:
begin
x1 := x-1;
x2 := x-1;
y1 := y;
y2 := y+1;
if (Block <> 10) and (Block <> 10)then
reg := reg+1;
end;
else
reg := reg+1;
end;
Block := 10;
Block:= 10;
Block := BlockN;
Block := BlockN;
end;
8 ://选中的格子是关羽
begin
case Direction of
0:
begin
x1 := x;
x2 := x1+1;
y1 := y-1;
y2 := y1;
if (Block <> 10) and (Block <> 10)then
reg := reg+1;
end;
1:
begin
x1 := x+2;
x2 := x1-1;
y1 := y;
y2 := y1;
if Block <> 10 then
reg := reg+1;
end;
2:
begin
x1 := x;
x2 := x1+1;
y1 := y+1;
y2 := y1;
if (Block <> 10) and (Block <> 10)then
reg := reg+1;
end;
3:
begin
x1 := x-1;
x2 := x1+1;
y1 := y;
y2 := y1;
if Block <> 10 then
reg := reg+1;
end
else
reg := reg+1;
end;
Block := 10;
Block:= 10;
Block := BlockN;
Block := BlockN;
end;
9 ://选中的格子是曹操
begin
case Direction of
0:
begin
x1 := x;
x2 := x1+1;
x3 := x1;
x4 := x3+1;
y1 := y-1;
y2 := y1;
y3 := y1+1;
y4 := y3;
if (Block <> 10) and (Block <> 10)then
reg := reg+1;
end;
1:
begin
x1 := x+1;
x2 := x1+1;
x3 := x1;
x4 := x3+1;
y1 := y;
y2 := y1;
y3 := y1+1;
y4 := y3;
if (Block <> 10) and (Block <> 10)then
reg := reg+1;
end;
2:
begin
x1 := x;
x2 := x1+1;
x3 := x1;
x4 := x3+1;
y1 := y+1;
y2 := y1;
y3 := y1+1;
y4 := y3;
if (Block <> 10) and (Block <> 10)then
reg := reg+1;
end;
3:
begin
x1 := x-1;
x2 := x1+1;
x3 := x1;
x4 := x3+1;
y1 := y;
y2 := y1;
y3 := y1+1;
y4 := y3;
if (Block <> 10) and (Block <> 10)then
reg := reg+1;
end
else
reg := reg+1;
end;
Block := 10;
Block := 10;
Block:= 10;
Block := 10;
Block := BlockN;
Block := BlockN;
Block := BlockN;
Block := BlockN;
end;
10 : //选中格子是空格子
begin
reg := reg + 1;
end;
end;
except
MessageBox(0,'请重新启动程序!','提示',0);
ExitProcess(0);
end;
end;简单解释下其中的思路,首先遍历数组元素,发现要移动的数字,那么就定位出该格子的位置x,y。由于游戏里面的人物占用的格子的数目是不一样的,导致了人物在移动的时候处理也会不同,其次,选中人物后,根据移动方向来确定该怎么移动,里面涉及到临界问题的处理,比方说这个人物在周边的时候,不能移动到整个游戏格局的外面去,再比方说右边已经有人占着在,就不能再往右边移动了。我在处理的时候偷了个懒,我不管是不是有人站着也不管是不是移到外面去了,统统认为是异常发生了,那么我就可以采用异常处理机制来处理,设置一个变量reg,初始化为0,如果移动到外面或移动到有人的位置,reg则加1,最后将reg作为除数,除数为0的时候才弹出正确的注册成功提示,否则就失败。另外还有一点要注意的是坐标问题,x,y分别是横坐标和纵坐标,而i,j是数组的行和列,很容易就对应错了。
/:good
太强大 了 /:good 写得真不错啊,大侠求合体~ /:good 学习 强悍的锋芒兄弟!/:09
捉放曹,呵呵! 锋芒兄强啊! 写得很好 , 赞一个 /:good 请教:对于任意的用户名,是否一定有解(有注册码,能生成keygen)? 楼上的兄弟们,我是菜鸟,哪是什么大侠/:018
原帖由 齐东野人 于 2010-1-1 05:18 发表 https://www.chinapyg.com/images/common/back.gif
请教:对于任意的用户名,是否一定有解(有注册码,能生成keygen)?
有的,因为强制了走法和步数,当然你也可以用用户名和注册码来随即产生一个游戏局面,这样会更好~ 无语,只能膜拜了
页:
[1]
2