首页 > 黑暗科技研究 > 【死兔】游戏作弊器

【死兔】游戏作弊器

2012年8月11日 发表评论 阅读评论

今日玩了一个叫做《死兔》的国产游戏。创意嘛,其实还一般,就是变化版的扫雷游戏。

规则大概是这样的,在一个方格布局的地图中,你需要从你开始的那个起始点那里,找到一条路到达指定的唯一终点,路上会经过一些有数字标记的格子,这些数字的意义就是说这个格子上下左右四个位置中安全区域有多少个(看嘛,就是变化版的扫雷嘛。。),然后你需要用逻辑推理来找到那条路。如果单单是这样就没什么难得了,但是随着剧情的发展,你可以控制四只兔子,每个兔子在寻找地图的出口的时候都拥有各自的能力,一只可以标记做过的安全路,一个可以在危险的路上做记号(这两个没什么,只要记忆力足够好,就和没用差不多了,虽然实际上会很有用。。),另外两只一直可以瞬移,一直可以通过一小段危险区域。以上,规则!!


据说这个游戏大部分人正常思路没法过关,我试了一下,在纯凭脑子记忆不动手记录点草稿的情况下,直接被秒。。然后我又很烦浪费宝贵的草稿纸来打游戏。。所以呢,花了一下午写了一个"作弊器",额,其实就是个提示功能的东西(照旧,代码在最后)。

东西的界面如下:启动时全屏幕只有网格没有东西,然后你用左键鼠标点击每个格子,就可以改变上面的示数,然后软件会自动标记出危险区域(红色),安全区域(蓝色),未知区域(白色),只要你在游戏中不断地前进,就可以不断地拓展这个地图,然后获取一个非常清晰的地图全貌。

逻辑嘛,显然超级简单,一个格子如果示数等于周围已经确定的安全区域的格子数,那么周围其余所有未确定的则全部标记为危险,如果一个格子周围确定为危险区域的格子的数目等于4-示数,那么周围所有未确定的格子全部都标记为安全区域。

同时,这个软件里面有个自动检测矛盾的机制,就是不可解的时候左上角会出现一个大感叹号,比如说下图:

因为最右下角的4的出现,导致了兔子(圆圈)右边那个2绝对不可能成立,所以产生了不可解的情况,这种时候就会有提示。其实这个的检测的原理就是用的上面那个逻辑的反面,如果一个格子周围确定安全的区域超过这个示数,那么就是矛盾,如果周围的确定危险的格子数目大于4-示数,那么也是矛盾。

其他的就没什么好讲的了,就是一些方便游戏的功能了:

鼠标右键可以把一个格子的状态强制标记为危险或者安全,游戏的时候你就会知道为什么有用了,(另外,游戏开始那一格也会被强制标记为安全);

左键格子可以改变示数;无→0→1→2→3→4→无;

E,D,S,F可以改变 兔子的位置(为了和游戏一样,一开始用WSAD就老是按错),其实改变兔子的位置没啥意义,因为即使移动到危险区域也没有任何提示,只是我程序中把兔子的位置放在了屏幕的正中间,所以改变兔子的位置只是为了调节视角而已;

R可以旋转视角,U可以把地图关于起始位置上下翻转,L可以左右翻转。这个功能主要是我们知道某一关如果死了,重开时地图虽然拓扑上一样,但是是经过旋转和翻转的,所以为了可以直接用上一局死前的信息,不用重新标记就可以直接用而加的功能;

C可以重开一局;

ESC退出程序;

图中标记为蓝色的是安全区域,如果是"V"说明那个一定安全,只是格子还没打开,可以往那里跳。如果是红色的X,说明还没打开,但是一定是危险区域。


题外话,玩过的孩子你就知道,就算有这个,你想一帆风顺的过关也是没门的,只是这个可以大大提高你游戏的效率,比如前20关,呼吸一下就过了,30开始这个东西其实就不是那么给力了。。

另外,其实写完这个程序,我想有空弄一下一个自动控制鼠标扫雷的程序。。有空就弄吧。。

下面是"作弊器"的CODE。。如果想要程序,请找我吧。。


#ifdef _DEBUG
    #pragma comment ( lib, "cxcore200d.lib" )
    #pragma comment ( lib, "cv200d.lib" )
    #pragma comment ( lib, "highgui200d.lib" )
#else
    #pragma comment ( lib, "cxcore200.lib" )
    #pragma comment ( lib, "cv200.lib" )
    #pragma comment ( lib, "highgui200.lib" )
#endif
#include "cv.h"
#include "highgui.h"
#include <iostream>
#include <stdlib .h>
using namespace std;

#define WINDOWNAME "死兔"
#define BACKGROUND_COLOR cvScalar(0,0,0)
#define GRID_COLOR cvScalar(255,255,255)
#define RABBIT_COLOR cvScalar(0,255,0)
#define DANGER_COLOR cvScalar(0,0,255)
#define WARNING_COLOR cvScalar(0,0,255)
#define SAFE_COLOR cvScalar(255,0,0)
#define UNKNOWN_COLOR cvScalar(255,255,255)
#define FRAME_WIDTH 600
#define FRAME_HEIGTH 600
#define GRID_SIZE 50

#define GRID_WIDTH 128
#define GRID_HEIGTH 128

#define SAFE 1
#define DANGER 2
#define UNKNOWN -1

int GridState[GRID_HEIGTH][GRID_WIDTH];
int PreSafe[GRID_HEIGTH][GRID_WIDTH];
int DangerState[GRID_HEIGTH][GRID_WIDTH];
CvPoint RabbitPos;
IplImage* frame = NULL;

CvFont font;
double hScale=1.0;
double vScale=1.0;
int    lineWidth=1;

CvFont Warning_font;

void Initial()
{
    frame = cvCreateImage(cvSize(FRAME_WIDTH,FRAME_HEIGTH),IPL_DEPTH_8U,3);
    cvZero(frame);
    for(int i = 0;i < GRID_HEIGTH;i++)
        for(int j = 0;j < GRID_WIDTH;j++)
        {
            GridState[i][j] = UNKNOWN;//-1是空白,其余则是相应数字
            DangerState[i][j] = UNKNOWN;//-1是位置,1是安全,2是危险
            PreSafe[i][j] = UNKNOWN;
        }
    RabbitPos.x = static_cast<int>(GRID_WIDTH/2);
    RabbitPos.y = static_cast<int>(GRID_HEIGTH/2);
    cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC,
        hScale,vScale,0,lineWidth);
    cvInitFont(&Warning_font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC,
        hScale*3,vScale*3,0,lineWidth*3);
    PreSafe[static_cast</int><int>(GRID_HEIGTH/2)][static_cast</int><int>(GRID_WIDTH/2)] = SAFE;
}

void on_mouse( int event, int x, int y, int flags, void* param )
{
    int grid_x = RabbitPos.x + floor(double(x-FRAME_WIDTH/2-GRID_SIZE/2)/GRID_SIZE)+1;
    int grid_y = RabbitPos.y + floor(double(y-FRAME_HEIGTH/2-GRID_SIZE/2)/GRID_SIZE)+1;
    if (grid_x < 0 || grid_y < 0 || grid_x >= GRID_WIDTH || grid_y >= GRID_HEIGTH)
        return;
    if(event == CV_EVENT_LBUTTONDOWN)
    {
        GridState[grid_y][grid_x]++;
        if (GridState[grid_y][grid_x] == 5)
            GridState[grid_y][grid_x] = UNKNOWN;
    }
    else if(event == CV_EVENT_MOUSEMOVE && flags == CV_EVENT_FLAG_RBUTTON)
        PreSafe[grid_y][grid_x] = DANGER;
    else if(event == CV_EVENT_RBUTTONDOWN)
        PreSafe[grid_y][grid_x] = SAFE;
}

void DrawRabbit()
{
    //int t = 10;
    //cvLine(frame,cvPoint(FRAME_WIDTH/2-t,FRAME_HEIGTH/2),cvPoint(FRAME_WIDTH/2+t,FRAME_HEIGTH/2),RABBIT_COLOR);
    //cvLine(frame,cvPoint(FRAME_WIDTH/2,FRAME_HEIGTH/2-t),cvPoint(FRAME_WIDTH/2,FRAME_HEIGTH/2+t),RABBIT_COLOR);
    cvCircle(frame,cvPoint(FRAME_WIDTH/2,FRAME_HEIGTH/2),GRID_SIZE/2-3,cvScalar(255,255,0));
}

void DrawGrid()
{
    CvPoint Begin_Point,End_Point;

    Begin_Point.x = max(0,FRAME_WIDTH/2-GRID_SIZE/2-(RabbitPos.x)*GRID_SIZE);
    End_Point.x = min(FRAME_WIDTH-1,FRAME_WIDTH/2-GRID_SIZE/2-(RabbitPos.x-GRID_WIDTH)*GRID_SIZE);

    Begin_Point.y = max(0,FRAME_HEIGTH/2-GRID_SIZE/2-(RabbitPos.y)*GRID_SIZE);
    End_Point.y = min(FRAME_HEIGTH-1,FRAME_HEIGTH/2-GRID_SIZE/2-(RabbitPos.y-GRID_HEIGTH)*GRID_SIZE);

    for(int i = RabbitPos.y-GRID_HEIGTH;i < = RabbitPos.y;i++)
    {
        cvLine(frame,cvPoint(Begin_Point.x,FRAME_HEIGTH/2-GRID_SIZE/2-i*GRID_SIZE),
            cvPoint(End_Point.x,FRAME_HEIGTH/2-GRID_SIZE/2-i*GRID_SIZE),GRID_COLOR);
    }

    for(int i = RabbitPos.x-GRID_WIDTH;i <= RabbitPos.x;i++)
    {
        cvLine(frame,cvPoint(FRAME_WIDTH/2-GRID_SIZE/2-i*GRID_SIZE,Begin_Point.y),
            cvPoint(FRAME_WIDTH/2-GRID_SIZE/2-i*GRID_SIZE,End_Point.y),GRID_COLOR);
    }
}

void DrawNumber()
{
    int bias_x = 7;
    int bias_y = 10;
    for(int i = 0;i < GRID_HEIGTH;i++)
    {
        for(int j = 0;j < GRID_WIDTH;j++)
        {
            int center_x = FRAME_WIDTH/2+(j-RabbitPos.x)*GRID_SIZE-bias_x;
            int center_y = FRAME_HEIGTH/2+(i-RabbitPos.y)*GRID_SIZE+bias_y;
            if (GridState[i][j] >= 0)
            {
                char str[2];
                sprintf(str,"%d",GridState[i][j]);
                if (DangerState[i][j] == DANGER)
                    cvPutText (frame,str,cvPoint(center_x,center_y), &font,DANGER_COLOR);
                else if(DangerState[i][j] == SAFE)
                    cvPutText (frame,str,cvPoint(center_x,center_y), &font,SAFE_COLOR);
                else
                    cvPutText (frame,str,cvPoint(center_x,center_y), &font,UNKNOWN_COLOR);
            }
            else if(DangerState[i][j] == DANGER)
                cvPutText (frame,"X",cvPoint(center_x,center_y), &font,DANGER_COLOR);
            else if(DangerState[i][j] == SAFE)
                cvPutText (frame,"v",cvPoint(center_x,center_y), &font,SAFE_COLOR);
        }
    }
}

int GetSureSafe(int i,int j,int IsSafe)
{
    return (i>0 && DangerState[i-1][j] == IsSafe) +
           (i<grid_heigth -1 && DangerState[i+1][j] == IsSafe) +
           (j>0 && DangerState[i][j-1] == IsSafe) +
           (j<grid_width -1 && DangerState[i][j+1] == IsSafe);
}

int SetDangerState(int i,int j,int IsSafe)
{
    int ChangeFlag = 0;
    if(i>0 && DangerState[i-1][j] == UNKNOWN)
    {    
        DangerState[i-1][j] = IsSafe;
        ChangeFlag = 1;
    }
    if(i<grid_heigth -1 && DangerState[i+1][j] == UNKNOWN)
    {
        DangerState[i+1][j] = IsSafe;
        ChangeFlag = 1;
    }
    if (j>0 && DangerState[i][j-1] == UNKNOWN)
    {
        DangerState[i][j-1] = IsSafe;
        ChangeFlag = 1;
    }
    if (j<grid_width -1 && DangerState[i][j+1] == UNKNOWN)
    {
        DangerState[i][j+1] = IsSafe;
        ChangeFlag = 1;
    }
    return ChangeFlag;
}

void UpDateDangerState()
{
    for(int i = 0;i < GRID_HEIGTH;i++)
    {
        for(int j = 0;j < GRID_WIDTH;j++)
        {
            DangerState[i][j] = PreSafe[i][j];//-1是位置,1是安全,2是危险
        }
    }
    int ChangeFlag = 1;
    while(ChangeFlag)
    {
        ChangeFlag = 0;
        for(int i = 0;i < GRID_HEIGTH;i++)
        {
            for(int j = 0;j < GRID_WIDTH;j++)
            {
                if (GridState[i][j] != UNKNOWN)
                {
                    int sure_safe = GetSureSafe(i,j,SAFE);

                    if(GridState[i][j] == sure_safe)
                    {
                        if(SetDangerState(i,j,DANGER) == 1)
                            ChangeFlag = 1;
                    }

                    int sure_danger = GetSureSafe(i,j,DANGER);
                    if((i>0)+(j>0)+(i<grid_heigth -1)+(j<GRID_WIDTH-1) - GridState[i][j] == sure_danger)
                    {
                        if(SetDangerState(i,j,SAFE) == 1)
                            ChangeFlag = 1;
                    }

                }
            }
        }
    }
}

CvPoint CheckInvalid()
{
    for(int i = 0;i < GRID_HEIGTH;i++)
    {
        for(int j = 0;j < GRID_WIDTH;j++)
        {
            if (GridState[i][j] != UNKNOWN)
            {
                int sure_safe = GetSureSafe(i,j,SAFE);
                int sure_danger = GetSureSafe(i,j,DANGER);
                if((i>0)+(j>0)+(i</grid_heigth><grid_heigth -1)+(j<GRID_WIDTH-1) - GridState[i][j]
                        < sure_danger || sure_safe > GridState[i][j])
                {
                    return cvPoint(i,j);
                }
            }
        }
    }
    return cvPoint(-1,-1);
}

void DrawUnvalidPoint(CvPoint UnvalidPoint)
{
    if (UnvalidPoint.x > 0)
    {
        cvPutText (frame,"!",cvPoint(30,70), &Warning_font,WARNING_COLOR);
    }    
}

void Draw_Background()
{
    cvZero(frame);
    /*for(int i = 0;i < FRAME_HEIGTH;i++)
    {
        for(int j = 0;j < FRAME_WIDTH;j++)
        {
            CV_IMAGE_ELEM(frame,uchar,i,3*j) = BACKGROUND_COLOR.val[0];
            CV_IMAGE_ELEM(frame,uchar,i,3*j+1) = BACKGROUND_COLOR.val[1];
            CV_IMAGE_ELEM(frame,uchar,i,3*j+2) = BACKGROUND_COLOR.val[2];
        }
    }*/
}

int Draw()
{
    UpDateDangerState();
    Draw_Background();
    DrawGrid();
    DrawRabbit();
    DrawNumber();
    DrawUnvalidPoint(CheckInvalid());
    cvShowImage(WINDOWNAME,frame);
    return cvWaitKey(2);
}

void UpdateRabbitPos(int key)
{
    switch(char(key))
    {
        case 'S':
        case 's':
            if (RabbitPos.x>0)
                RabbitPos.x--;
            break;
        case 'F':
        case 'f':
            if(RabbitPos.x<grid_width -1)
                RabbitPos.x++;
            break;
        case 'E':
        case 'e':
            if (RabbitPos.y>0)
                RabbitPos.y--;
            break;
        case 'D':
        case 'd':
            if(RabbitPos.y<grid_heigth -1)
                RabbitPos.y++;
            break;
        default:break;
    }
}

void CopyState(int src[GRID_HEIGTH][GRID_WIDTH],int dst[GRID_HEIGTH][GRID_WIDTH])
{
    for(int i = 0;i < GRID_HEIGTH;i++)
    {
        for(int j = 0;j < GRID_WIDTH;j++)
        {
            dst[i][j] = src[i][j];
            src[i][j] = UNKNOWN;
        }
    }
}

void Rotate()
{
    int temp1[GRID_HEIGTH][GRID_WIDTH];
    int temp2[GRID_HEIGTH][GRID_WIDTH];
    CvPoint center= cvPoint(static_cast<int>(GRID_WIDTH/2),static_cast<int>(GRID_HEIGTH/2));
    CopyState(GridState,temp1);
    CopyState(PreSafe,temp2);
    for(int i = 0;i < GRID_HEIGTH;i++)
    {
        for(int j = 0;j < GRID_WIDTH;j++)
        {
            if(temp1[i][j] != UNKNOWN)
                GridState[center.y+j-center.x][center.x+center.y-i] = temp1[i][j];
            if(temp2[i][j] != UNKNOWN)
                PreSafe[center.y+j-center.x][center.x+center.y-i] = temp2[i][j];
        }
    }
    RabbitPos = cvPoint(center.x+center.y-RabbitPos.y,center.y+RabbitPos.x-center.x);
}

void FlipUD()
{
    int temp1[GRID_HEIGTH][GRID_WIDTH];
    int temp2[GRID_HEIGTH][GRID_WIDTH];
    CvPoint center = cvPoint(static_cast<int>(GRID_WIDTH/2),static_cast</int><int>(GRID_HEIGTH/2));
    CopyState(GridState,temp1);
    CopyState(PreSafe,temp2);
    for(int i = 0;i < GRID_HEIGTH;i++)
    {
        for(int j = 0;j < GRID_WIDTH;j++)
        {
            if(temp1[i][j] != UNKNOWN)
                GridState[center.y+center.y-i][j] = temp1[i][j];
            if(temp2[i][j] != UNKNOWN)
                PreSafe[center.y+center.y-i][j] = temp2[i][j];
        }
    }
    RabbitPos = cvPoint(RabbitPos.x,center.y+center.y-RabbitPos.y);
}

void FlipLR()
{
    int temp1[GRID_HEIGTH][GRID_WIDTH];
    int temp2[GRID_HEIGTH][GRID_WIDTH];
    CvPoint center = cvPoint(static_cast<int>(GRID_WIDTH/2),static_cast</int><int>(GRID_HEIGTH/2));
    CopyState(GridState,temp1);
    CopyState(PreSafe,temp2);
    for(int i = 0;i < GRID_HEIGTH;i++)
    {
        for(int j = 0;j < GRID_WIDTH;j++)
        {
            if(temp1[i][j] != UNKNOWN)
                GridState[i][center.x+center.x-j] = temp1[i][j];
            if(temp2[i][j] != UNKNOWN)
                PreSafe[i][center.x+center.x-j] = temp2[i][j];
        }
    }
    RabbitPos = cvPoint(center.x+center.x-RabbitPos.x,RabbitPos.y);
}

void ShowTip()
{
    printf("\
           本程序是 死兔 游戏的简单提示器\n\
           使用方法:\n\
           \t单击鼠标右键可以标记该位置为安全状态\n\
           \t右键微小拖动鼠标可以将该位置标记为危险状态\n\
           \t左键可以改变该格子的数目\n\
           \tE,D,S,F可以移动兔子位置\n\
           \tR键可以旋转视角\n\
           \tU键可以上下翻转\n\
           \tL键可以左右翻转\n\
           \tESC键退出程序\n\
           \t键盘C键可以重新开一局\n\
           其他信息:\n\
           \t左上角显示感叹号时表示现在不可解\n\
           祝你游戏愉快\n");
}

void UpdateControl(int key)
{
    switch(key)
    {
        case 'C':
        case 'c':
            Initial();
            break;
        case 'R':
        case 'r':
            Rotate();
            break;
        case 'U':
        case 'u':
            FlipUD();
            break;
        case 'L':
        case 'l':
            FlipLR();
            break;
        default:
            UpdateRabbitPos(key);
            break;
    }
}

int main(int argc,char* argv[])
{
    ShowTip();
    cvNamedWindow(WINDOWNAME,1);
    cvSetMouseCallback(WINDOWNAME, on_mouse, 0 );
    Initial();
    while(1)
    {
        int key = Draw();    
        if(key != 27)
            UpdateControl(key);
        else
            return 0;
    }
    return 0;
}

【完】

本文内容遵从CC版权协议,转载请注明出自http://www.kylen314.com