能力值:
( LV9,RANK:180 )
|
-
-
2 楼
帐号: sessiondiy
序号: 1F20140A06010D1B1F2016111F20140A05120D1B1F20161006010F13140A06
游戏是满好玩的, 可是为什么我的名字那么难 ?
|
能力值:
(RANK:410 )
|
-
-
3 楼
马甲?
个别名字可能注册码比较长,主要是想报复下,hiahia。
最长注册码的用户名应该是test,恐怕要写keygen才可。
三天构思,一天写码调试。。。瞬间被搞定。
|
能力值:
( LV9,RANK:180 )
|
-
-
4 楼
不可能瞬间
我可是花了将近一个小时
还用掉一张纸 + 一把剪刀
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
楼上的用剪刀干嘛了?
|
能力值:
( LV9,RANK:180 )
|
-
-
6 楼
剪鼻毛
文章太短
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
郁闷,咋我只能爆呢~
学习了~
|
能力值:
(RANK:410 )
|
-
-
8 楼
呵呵,用扑克牌好些。我的注册码是用扑克牌
|
能力值:
( LV4,RANK:50 )
|
-
-
9 楼
郁闷,咋我爆也不能呢~
见鬼了~
|
能力值:
( LV5,RANK:60 )
|
-
-
10 楼
一般用户 是3*3的拼图
ccfer 是5*5的 你要累死他啊
|
能力值:
(RANK:410 )
|
-
-
11 楼
本计划是8*8的。犹豫再三改成了5*5。另设了个test用户为7*7。
|
能力值:
( LV9,RANK:250 )
|
-
-
12 楼
爆破很容易,留名,写个算法机..
|
能力值:
( LV5,RANK:60 )
|
-
-
13 楼
我来个稍微短点的
用户名:1
注册码:3c3027293543443a3630272b2d3a35423c33342a
|
能力值:
( LV5,RANK:60 )
|
-
-
14 楼
我估计 用户名为ccfer的 可能要N步才能拼好!!
不知ccfer能否搞出来.
3*3这个 我上面那个20步估计是最优解了.
小时侯老是玩这种圣斗士的拼图,那个好象是4*6的长方形的 ,打乱后拿在手里要拼好半天才能拼好呢.
|
能力值:
( LV5,RANK:60 )
|
-
-
15 楼
壳狼: 下次写crackme 把下面那个注册框弄成可以换行的吧
不然注册码长了 看起来不方便
|
能力值:
(RANK:410 )
|
-
-
16 楼
好,多谢。
|
能力值:
( LV15,RANK:2473 )
|
-
-
17 楼
我觉得壹只老虎的这两个程序比楼主的更好玩
http://bbs.pediy.com/showthread.php?t=52748
http://bbs.pediy.com/showthread.php?t=52799
|
能力值:
( LV5,RANK:60 )
|
-
-
18 楼
1只老虎那个表太大了 不太适合游戏
只适合 科普
|
能力值:
(RANK:410 )
|
-
-
19 楼
有时间去玩下,学习下
|
能力值:
( LV5,RANK:60 )
|
-
-
20 楼
幸好是3*3,不然拼到累趴。。。
懒得去算最优解了。随便贴上个。
用户名:hflywolf
注册码:1F203A351F20140A06010D1B1F20140A05120D1B1F20140A06010D1B1F20161230
|
能力值:
(RANK:410 )
|
-
-
21 楼
:),多谢大家参与测试。
本想诱骗大家写出个keygen,没有得逞。是我手机上的小游戏,一直玩不过老婆,所以最近在琢磨怎么写个算法解决它。于是先写了个crackme.
写到一半考虑怎么解决无解问题时,网上搜了下,没想到竟是个经典的八数码问题。可以用A*,广度搜索,深度搜索等....我的方法是先将7*7变成6*6再变成5*5....
正学习MFC,贴部分代码,有空的朋友指点下。
//注册检查
void Ccrackme080524Dlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
char name[16];
int namelen;
char namevalue[16];
//int *nameint0,*nameint1;
//-regcode
char regcode[4096];
int regcodelen;
char regcodevalue[2052];//4096/2+4 for scanf
//-md5para
MD5_CTX context;//MD5,get md5 value of name
//Pintu object
Pintu pintu1;
//-tmp
int tmpi,tmpint;//tmpcount
//chk name,regcode len
namelen=GetDlgItemText(IDC_EDIT1,&name[0],15);
regcodelen=GetDlgItemText(IDC_EDIT2,®code[0],4095);
if (namelen==0||regcodelen==0||regcodelen%2!=0)
return;
strupr(®code[0]);//转换大小写
for(tmpi=0;tmpi<regcodelen;tmpi++)
{
if (regcode[tmpi]>0x39||regcode[tmpi]<0x30)
if(regcode[tmpi]>'F'||regcode[tmpi]<'A')
return;
}
//get namevalue
MD5Init (&context);
MD5Update (&context, (unsigned char *)&name[0], namelen);
MD5Final (&context);
//set level
if (context.state[0]==0x7d98ebe5//ccfer
||context.state[0]==0x6c6b0f79)//forgot
{
pintu1.M=5;
pintu1.N=5;
}
else
{
pintu1.M=3;
pintu1.N=3;
}
//test
if (namelen==4&&name[0]=='t'&&name[1]=='e'&&name[2]=='s'&&name[3]=='t')
{
pintu1.M=7;
pintu1.N=7;
}
//set key
pintu1.Key[0]=context.state[0];
pintu1.Key[1]=context.state[1];
pintu1.Key[2]=context.state[2];
pintu1.Key[3]=context.state[3];
//init dest & src
pintu1.Init_Dest();
pintu1.Init_Src();
//get regcodevalue
//转换原始数据为二进制
for(tmpi=0;tmpi<regcodelen/2;tmpi++)
sscanf(®code[tmpi*2],"%02x",®codevalue[tmpi]);
//reg
if (pintu1.IsSolvable())
pintu1.MOVE_reg(®codevalue[0],int(regcodelen/2));
//检测注册码
if(pintu1.chkequal())//checkwin
MessageBox("注册成功",name,MB_OK);
else
MessageBox("注册失败",name,MB_OK);
return;
}
//pintu.cpp
#include "StdAfx.h"
#include "Pintu.h"
Pintu::Pintu(void)
{
M=MAXM;
N=MAXN;
}
Pintu::~Pintu(void)
{
}
// //判断是否有解
bool Pintu::IsSolvable(void)
{
int sn0;
int sn1;
int sn0_m,sn0_n;
int sn1_m,sn1_n;
int Src_nixu=0;
int Dest_nixu=0;
if (M!=N||M%2!=1)
return false;
//check nixu
//calc dest
for(sn0=0;sn0<M*N;sn0++)
{
sn0_n=int(sn0/M);
sn0_m=sn0%M;
for(sn1=0;sn1<sn0;sn1++)
{
sn1_n=int(sn1/M);
sn1_m=sn1%M;
if(Dest[sn1_n][sn1_m]!=0&&Dest[sn1_n][sn1_m]<Dest[sn0_n][sn0_m])
Dest_nixu=Dest_nixu+1;
}
}
//calc src
for(sn0=0;sn0<M*N;sn0++)
{
sn0_n=int(sn0/M);
sn0_m=sn0%M;
for(sn1=0;sn1<sn0;sn1++)
{
sn1_n=int(sn1/M);
sn1_m=sn1%M;
if(Src[sn1_n][sn1_m]!=0&&Src[sn1_n][sn1_m]<Src[sn0_n][sn0_m])
Src_nixu=Src_nixu+1;
}
}
//check
return (Dest_nixu%2==Src_nixu%2);
}
// //初始化源数组
bool Pintu::Init_Src(void)
{
int tmpi,tmpj;
int tmpk,tmpc;
int dir;
//填充背景0xff
for(tmpj=0;tmpj<MAXN;tmpj++)
for(tmpi=0;tmpi<MAXM;tmpi++)
Src[tmpj][tmpi]=0xff;
//反序排列
for(tmpj=0;tmpj<N;tmpj++)
for(tmpi=0;tmpi<M;tmpi++)
Src[tmpj][tmpi]=(N-tmpj-1)*M+M-tmpi-1;
//key打乱
for(tmpk=0;tmpk<4;tmpk++)
for(tmpc=0;tmpc<16;tmpc++)
{
dir=Key[tmpk]>>tmpc*2&0x00000003;
MOVE(dir);
}
return true;
}
// //初始化目标数组
bool Pintu::Init_Dest(void)
{
int tmpi,tmpj;
for(tmpj=0;tmpj<MAXN;tmpj++)
for(tmpi=0;tmpi<MAXM;tmpi++)
{
Dest[tmpj][tmpi]=0xff;
}
for(tmpj=0;tmpj<N;tmpj++)
for(tmpi=0;tmpi<M;tmpi++)
{
Dest[tmpj][tmpi]=tmpj*M+tmpi;
}
return true;
}
// //根据方向移动
bool Pintu::MOVE(int dir)
{
int sn;
sn=Find_n_in_Array(0);
if (dir<0||dir>3||sn>=M*N)
return false;
int m,n;
n=int(sn/M);
m=sn%M;
switch (dir)
{
case 0://up
if((n-1)>=0)
{
Src[n][m]=Src[n-1][m];
Src[n-1][m]=0;
}
break;
case 1://down
if((n+1)<N)
{
Src[n][m]=Src[n+1][m];
Src[n+1][m]=0;
}
break;
case 2://left
if((m-1)>=0)
{
Src[n][m]=Src[n][m-1];
Src[n][m-1]=0;
}
break;
case 3://right
if((m+1)<M)
{
Src[n][m]=Src[n][m+1];
Src[n][m+1]=0;
}
break;
default:
break;
}
return true;
}
// //查找数据在数组中的位置;返回序号
int Pintu::Find_n_in_Array(int n)
{
int tmpi,tmpj;
int sn=M*N;
for(tmpj=0;tmpj<N;tmpj++)
for(tmpi=0;tmpi<M;tmpi++)
{
if (Src[tmpj][tmpi]==n)
sn=tmpj*M+tmpi;
}
return sn;
}
// //指定0位置根据方向移动//返回0的位置//如返回值为64表示失败
int Pintu::MOVEsn(int sn, int dir)
{
int m,n;
if(sn<0||sn>=M*N
||dir<0||dir>3)
return 64;
n=int(sn/M);
m=sn%M;
if(Src[n][m]!=0)
return 64;
switch (dir)
{
case 0://up
if((n-1)>=0)
{
Src[n][m]=Src[n-1][m];
Src[n-1][m]=0;
sn=(n-1)*M+m;
}
break;
case 1://down
if((n+1)<N)
{
Src[n][m]=Src[n+1][m];
Src[n+1][m]=0;
sn=(n+1)*M+m;
}
break;
case 2://left
if((m+1)>=0)
{
Src[n][m]=Src[n][m-1];
Src[n][m-1]=0;
sn=n*M+m-1;
}
break;
case 3://right
if((m+1)<M)
{
Src[n][m]=Src[n][m+1];
Src[n][m+1]=0;
sn=n*M+m+1;
}
break;
default:
sn=64;
break;
}
return sn;
}
// //比较源和目的数组
bool Pintu::chkequal(void)
{
int tmpi,tmpj;
bool result=true;
for(tmpj=0;tmpj<N;tmpj++)
for(tmpi=0;tmpi<M;tmpi++)
if(Dest[tmpj][tmpi]!=Src[tmpj][tmpi])
result=false;
return result;
}
// //根据注册码移动,注册码每字节中前6位为position,后2位为dir
void Pintu::MOVE_reg(char * pchar, int len)
{
if (len<=0)
return;
char tmpB;
char tmpPos,tmpDir;
int tmpi;
int m,n;
for(tmpi=0;tmpi<len;tmpi++,pchar++)
{
tmpB=*pchar;
tmpPos=((tmpB>>2)&0x3F)%(M*N);
tmpDir=tmpB&0x03;
MOVEsn(tmpPos,tmpDir);
}
}
|
能力值:
( LV8,RANK:130 )
|
-
-
22 楼
大于2*2的一定有解吧
|
能力值:
(RANK:410 )
|
-
-
23 楼
任意组合的话,应该是一半有解,一半无解。当把N*N可简化为2*2。对2*2的组合,一半有解。
网上有这个的讨论,通过计算逆序数的方法,比对源拼图和目的拼图的逆序数可知是否有解。代码中构造的目的拼图和源拼图,是肯定有解的,因其N为奇数,源拼图和目的拼图的逆序数奇偶性相同。
|
能力值:
( LV8,RANK:130 )
|
-
-
24 楼
楼上请构造一个4*4无解的出来看看吧
|
能力值:
(RANK:410 )
|
-
-
25 楼
目的拼图
1 2 3 4
5 6 7 8
9 A B C
D E F X
源拼图
1 2 3 4
5 6 7 8
9 A B F
D E C X
|
|
|