C1-1任务解析


前言

植物大战僵尸作为一个集趣味性和益智性为一身的经典塔防类游戏,在推出之初便收获了广泛的关注及好评。推出十年间,不断有围绕该游戏不同的攻略,不同的二创、三创作品。使得人们对该游戏的热度不减。然而,作为经典单机游戏,它的有趣性不仅体现在于其本身画面设计精美、游戏数据设计合理,还在与其有强大的可再修改性。通过修改当中完全开源的内容,玩家可以自行升高或降低难度,自行调节关卡进度,自行查看场地数据,达到了十足的可玩性。本文从最基本的关卡和金币修改出发,探究植物大战僵尸游戏中蕴藏的数据原理。


一、获取数据

使用二进制编辑器打开植物大战僵尸用户文件(一般为C:\ProgramData\PopCap Games\PlantsVsZombies\userdata\user1.dat)(如图)。

不难发现,当关卡变化时,(04,00000000)的数值发生了改变,而经过作者不断实验发现,当只改变关卡数,仅有该数值发生变化:当游戏关卡为1-1时,其数值为01,当游戏关卡为1-10时,其数值为0A,以此类推皆成立。发现,该位置数字为16进制,且符合关卡变动规律,故推定该位置为关卡数据存放位置。

同时,在其他条件均相同情况下,用其他修改器修改游戏内的金币数,观察游戏存档变化。发现,当金币变化时,(08,00000000)(09,00000000)(0A,00000000)(0B,00000000)四个位置的数据随金币数量的十分之一而改变。

不妨令其四个值为a,b,c,d.设金币数为g,实验观察得知,金币数g满足方程

0.1g=a+256b+65536c+16777216d

得知当金币数储存在上述各位置。

在这里插入图片描述


二、程序设计

以下以C++语言为例,简要说明修改的具体实现。


1.打开文件

首先,需要打开所需要的数据文件,并将其输入到内存中,此方法使用fread函数来读取二进制内容。由于该数据在显示上以两位16进制字符为一个单位,故使用char方式进行读取,以保证读取的数据格式与显示一致。

    FILE *infile;//创建两个文件指针
    FILE *outfile;
    char filename[] = "C:\\ProgramData\\PopCap Games\\PlantsVsZombies\\userdata\\user1.dat";//数据所在位置
    infile = fopen(filename, "rb");//以二进制方式读取
    while (fread(&num1, sizeof(char), 1, infile))//以一个字节为一个单位
        a[x] = num1, x++;
    fclose(infile);


2.修改

其次,进入修改环节,核心在于对输入的数据进行处理后修改。

若要跳关,则执行以下代码:

		printf("请输入您需要跳到的关卡(x-y):\n");
        scanf("%d-%d", &q, &w);//输入x-y关
        while (q < 1 || q > 6 || w > 10 || w < 1)//边界条件
        {
            printf("输入不正确,请再次输入(1<=x<=6,1<=y<=10)\n");
            scanf("%d-%d", &q, &w);
        }
        char jump = (q - 1) * 10 + w;//赋值
        a[4] = jump;
        printf("跳到%d-%d关......\n\n", q, w);

若要修改金币,则执行以下代码:

        printf("请输入您需要的金币数(x10):\n");
        scanf("%d", &gold);//输入金币数
        while (gold < 0 || gold > 999999999)
        {
            printf("输入不正确,请再次输入\n");
            scanf("%d", &gold);
        }
        /*
        以编码方式储存数据,并将int隐式转换为char
        */
        int g = gold;
        a[8] = gold % 256;
        gold /= 256;
        a[9] = gold % 256;
        gold /= 256;
        a[10] = gold % 256;
        gold /= 256;
        a[11] = gold % 256;
        gold /= 256;
        printf("修改到%d0金币......\n", g);



3.写入

将修改完的数组以二进制方式写入文件:

    outfile = fopen(filename, "wb");
    fwrite(a, sizeof(a), 1, outfile);
    fclose(outfile);



完整代码

以下代码加入了一些操作提示,便于进行操作

#include <bits/stdc++.h>
int main()
{
    int q, w, gold;
    FILE *infile;
    FILE *outfile;
    char filename[] = "C:\\ProgramData\\PopCap Games\\PlantsVsZombies\\userdata\\user1.dat";
    infile = fopen(filename, "rb");
    unsigned char a[820];
    unsigned char num1;
    int x = 0;
    while (fread(&num1, sizeof(char), 1, infile))
        a[x] = num1, x++;
    fclose(infile);
    printf("欢迎使用植物大战僵尸修改器\n\n");
    printf("需要跳关吗?\n输入1跳关\n");
    int num;
    scanf("%d", &num);
    if (num == 1)
    {
        printf("请输入您需要跳到的关卡(x-y):\n");
        scanf("%d-%d", &q, &w);
        while (q < 1 || q > 6 || w > 10 || w < 1)
        {
            printf("输入不正确,请再次输入(1<=x<=6,1<=y<=10)\n");
            scanf("%d-%d", &q, &w);
        }
        char jump = (q - 1) * 10 + w;
        a[4] = jump;
        printf("跳到%d-%d关......\n\n", q, w);
    }
    printf("需要修改金币吗?\n输入1修改\n");
    scanf("%d", &num);
    if (num == 1)
    {
        printf("请输入您需要的金币数(x10):\n");
        scanf("%d", &gold);
        while (gold < 0 || gold > 999999999)
        {
            printf("输入不正确,请再次输入\n");
            scanf("%d", &gold);
        }
        int g = gold;
        a[8] = gold % 256;
        gold /= 256;
        a[9] = gold % 256;
        gold /= 256;
        a[10] = gold % 256;
        gold /= 256;
        a[11] = gold % 256;
        gold /= 256;
        printf("修改到%d0金币......\n", g);
    }
    printf("\n");
    printf("修改成功!\n");
    outfile = fopen(filename, "wb");
    fwrite(a, sizeof(a), 1, outfile);
    fclose(outfile);
    system("pause");
    return 0;
}



相关样题解答

110101010001转十六进制是多少?
D51

101011.101011的十进制数是多少?
43.671875

常见的视频编码格式有哪些?
AVI,DV-AVI,MPEG,DivX,MOV,ASF,WMV,RM,RMVB等

65对应ASCII码是哪个字符?
‘A’


总结

本文对植物大战僵尸中的数值修改进行了阐述,望能对读者有所帮助。本人才疏学浅,本文必有纰漏之处,望诸君不吝指出,谢谢。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值