- UID
- 59635
注册时间2009-1-30
阅读权限30
最后登录1970-1-1
龙战于野
TA的每日心情 | 慵懒 2019-4-26 10:19 |
---|
签到天数: 14 天 [LV.3]偶尔看看II
|
CrackMe V2.6的注册算法源自文曲星上的一个小游戏《华容道》。先来简单的介绍下这个游戏吧O(∩_∩)O~。
华容道游戏取自著名的三国故事,曹操在赤壁大战中被刘备和孙权的“苦肉计”、“火烧连营”打败,**退逃到华容道,又遇上诸葛亮的伏兵,关羽为了报答曹操对他的恩情,明逼实让,终于帮助曹操逃出了华容道。
游戏就是依照“曹瞒兵败走华容,正与关公狭路逢。只为当初恩义重,放开金锁走蛟龙”这一故事情节,通过移动各个棋子,帮助曹操从初始位置移到棋盘最下方中部,从出口逃走。不允许跨越棋子,还要设法用最少的步数把曹操移到出口。曹操逃出华容道的最大障碍是关羽,关羽立马华容道,一夫当关,万夫莫开。
成功的条件:
1.
首先定义一个全变数组变量Block,摆好位置,进行初始化,最终成功的条件应该是曹操跑出,也即4个9在数组的位置Block[4][2],Block[4][3],Block[5][2],Block5][3]。我这里为了简单,自己定义了一个初始化的局面,大家也可以由用户名和注册码进行运算后得出一个开局,这样就避免了开局的单一性。- var
- //初始化华容道
- //0,1,2,3分别代表兵,卒,勇,丁
- //4,5,6,7分别代表张飞,赵云,马超,黄忠,8代表关羽,9代表曹操 ,10代表空格子
- Block : array[1..5,1..4] 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[i]) - byte(RegCode[i]))) ;
- end;
- //得到移动的格子序列
- BlockSN := '';
- for i := 0 to 48 do
- begin
- BlockSN := BlockSN + strTemp[2*i+1];
- end;
- //得到移动方向序列
- DirectionSN := '';
- for i := 1 to 49 do
- begin
- DirectionSN := DirectionSN + strTemp[2*i];
- end;
- //游戏开始
- for i := 1 to 49 do
- begin
- MoveBlock(StrToInt(BlockSN[i]), StrToInt(DirectionSN[i]));
- end;
- if (Block[4][2]= Block[4][3]) and (Block[5][2]= Block[4][3]) and (Block[5][3]= Block[4][3]) and (Block[4][2] = 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[4][2]= Block[4][3]) and (Block[5][2]= Block[4][3]) and (Block[5][3]= Block[4][3]) and (Block[4][2] = 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 4 do
- begin
- if Block[i][j] = 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[y1][x1] <> 10 then
- reg := reg + 1
- else
- begin
- Block[y][x] := 10; //原来的位置就变成空格子了
- Block[y1][x1] := BlockN;
- end;
- end;
- 4..7 : //选中的格子是张飞,赵云,马超,黄忠的其中一个
- begin
- case Direction of
- 0:
- begin
- x1 := x;
- x2 := x;
- y1 := y-1;
- y2 := y1+1;
- if Block[y1][x1] <> 10 then
- reg := reg+1;
- end;
- 1:
- begin
- x1 := x+1;
- x2 := x+1;
- y1 := y;
- y2 := y+1;
- if (Block[y1][x1] <> 10) and (Block[y2][x2] <> 10)then
- reg := reg+1;
- end;
- 2:
- begin
- x1 := x;
- x2 := x;
- y1 := y+2;
- y2 := y1-1;
- if Block[y1][x1] <> 10 then
- reg := reg+1;
- end;
- 3:
- begin
- x1 := x-1;
- x2 := x-1;
- y1 := y;
- y2 := y+1;
- if (Block[y1][x1] <> 10) and (Block[y2][x2] <> 10)then
- reg := reg+1;
- end;
- else
- reg := reg+1;
- end;
- Block[y][x] := 10;
- Block[y+1][x] := 10;
- Block[y1][x1] := BlockN;
- Block[y2][x2] := BlockN;
- end;
- 8 : //选中的格子是关羽
- begin
- case Direction of
- 0:
- begin
- x1 := x;
- x2 := x1+1;
- y1 := y-1;
- y2 := y1;
- if (Block[y1][x1] <> 10) and (Block[y2][x2] <> 10)then
- reg := reg+1;
- end;
- 1:
- begin
- x1 := x+2;
- x2 := x1-1;
- y1 := y;
- y2 := y1;
- if Block[y1][x1] <> 10 then
- reg := reg+1;
- end;
- 2:
- begin
- x1 := x;
- x2 := x1+1;
- y1 := y+1;
- y2 := y1;
- if (Block[y1][x1] <> 10) and (Block[y2][x2] <> 10)then
- reg := reg+1;
- end;
- 3:
- begin
- x1 := x-1;
- x2 := x1+1;
- y1 := y;
- y2 := y1;
- if Block[y1][x1] <> 10 then
- reg := reg+1;
- end
- else
- reg := reg+1;
- end;
- Block[y][x] := 10;
- Block[y][x+1]:= 10;
- Block[y1][x1] := BlockN;
- Block[y2][x2] := 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[y1][x1] <> 10) and (Block[y2][x2] <> 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[y2][x2] <> 10) and (Block[y4][x4] <> 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[y3][x3] <> 10) and (Block[y4][x4] <> 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[y1][x1] <> 10) and (Block[y3][x3] <> 10)then
- reg := reg+1;
- end
- else
- reg := reg+1;
- end;
- Block[y][x] := 10;
- Block[y][x+1] := 10;
- Block[y+1][x]:= 10;
- Block[y+1][x+1] := 10;
- Block[y1][x1] := BlockN;
- Block[y2][x2] := BlockN;
- Block[y3][x3] := BlockN;
- Block[y4][x4] := 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是数组的行和列,很容易就对应错了。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?加入我们
x
评分
-
查看全部评分
|