小试锋芒 发表于 2009-12-31 09:53:11

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是数组的行和列,很容易就对应错了。

assume 发表于 2009-12-31 10:00:47

/:good

太强大 了

missviola 发表于 2009-12-31 10:24:21

/:good 写得真不错啊,大侠求合体~

yayazhi 发表于 2009-12-31 10:34:49

/:good 学习

GGLHY 发表于 2009-12-31 11:30:31

强悍的锋芒兄弟!/:09
捉放曹,呵呵!

pao 发表于 2009-12-31 15:56:46

锋芒兄强啊!

lgjxj 发表于 2009-12-31 16:01:15

写得很好 , 赞一个 /:good

齐东野人 发表于 2010-1-1 05:18:25

请教:对于任意的用户名,是否一定有解(有注册码,能生成keygen)?

小试锋芒 发表于 2010-1-1 09:12:17

楼上的兄弟们,我是菜鸟,哪是什么大侠/:018
原帖由 齐东野人 于 2010-1-1 05:18 发表 https://www.chinapyg.com/images/common/back.gif
请教:对于任意的用户名,是否一定有解(有注册码,能生成keygen)?
有的,因为强制了走法和步数,当然你也可以用用户名和注册码来随即产生一个游戏局面,这样会更好~

lixy8888 发表于 2010-1-1 13:41:55

无语,只能膜拜了
页: [1] 2
查看完整版本: CrackMe V2.6 设计思路+源码