说说《牧场物语:矿石镇的伙伴们》中的猜大小游戏

《牧场物语:矿石镇的伙伴们》是一款模拟经营类游戏,2003 年发布于 GBA 平台上,因此也简称 GBA 版矿石镇。笔者认为这款游戏是牧场物语系列最经典的一作,没有之一。2019 年该游戏的重置版发布在任天堂 Switch 平台上,但是笔者没有 Switch ,而且由于笔者没收到广告费,就不做宣传了

对GBA 版矿石镇熟悉的玩家应该都知道里面的猜数字大小游戏。这个游戏的大概流程是这样:首先,女神会询问玩家是否愿意玩这个游戏,如果愿意则进入游戏。游戏过程中,女神会告诉玩家一个数字,并要求玩家猜测下一个出现数字与当前数字的大小关系。玩家只能回答比当前数字大或者比当前数字小。回答完后,女神会告知新的数字。如果新的数字与前一数字相等,则玩家累计猜对次数不变,游戏继续。如果新的数字与前一数字不相等,且玩家猜测正确,则玩家累计猜对次数增加一次,游戏继续。如果新的数字与前一数字不相等,且玩家猜测错误,则显示玩家猜对次数,游戏结束。游戏中出现的所有数字均为大于等于 0 且小于等于 9 的整数。游戏过程中,玩家累计猜对的次数仅在前后两次数字不等且玩家猜错的情况下显示,其他情况不显示。

这个无聊的猜数游戏制作起来貌似比较简单,在不要求可视化界面的前提下像笔者这样的编程小白借助百度的帮助也能写出来的,只不过笔者写出来的游戏的画风跟原作差距有点大。下面笔者就简单分析一下写代码的步骤。

分步流程解析及代码实现

上文所述游戏流程可以分为两部分,第一部分是游戏意愿判断,第二部分是游戏具体流程。

游戏意愿判断

游戏意愿的流程简单来讲,就是先询问游戏意愿,如果答非所问就回到原点,一直答非所问就一直循环下去。如果回答否,直接退出循环。如果回答是,则开始游戏,在游戏结束的时候退出循环。那么如何通过代码实现这个流程呢?

笔者的思路是创造一个死循环,答非所问就 continue;,回答是 no 就 break;, 回答是 yes 就执行游戏流程,执行完毕后 break;。笔者应用的代码类型是 C++ ,代码框架如下:

#include <iostream>
int main()
{
    using namespace std;
    char will; 
    for( ; ; ) // 建立死循环
    {
        cout << "Type y to start the game. Type n to exit." << endl;
        cin >> will; // 输入意愿,y 为 yes,n 为 no

        if(will == 'n')  // 回答为 n,退出游戏
        {
            break;
        }
        else if(will != 'n' && will != 'y') // 答非所问,回到循环起点
        {
            cout << "Your answer has to be either n or y." << endl;
            cout << "Press any key to continue." << endl;
            cin.get();
            continue;
        }

        // 这里准备书写具体游戏过程的代码,只有回答为 y 才能执行。

        break;
    }

}

具体游戏过程

笔者上面那段代码框架里预留了一个位置,准备写具体游戏流程代码。那这段代码该如何写呢?笔者先来梳理一下游戏具体过程的流程:先生成一个随机数,显示出来。再询问玩家下一个数字比当前数字大还是小。如果答非所问则再次询问。如果回答是大或小则生成下一个随机数。如果生成的新随机数与前一个相等,则再次询问玩家下一个数字与当前数字的关系。若新随机数与前一随机数不等,则判断这两个数字的大小关系,并判断玩家是否猜对。若玩家猜错,则停止。若玩家猜对,则继续游戏。代码仍是依旧死循环与分枝结构的组合,具体如下:

int n = 0;
srand((unsigned)time(0));
int randnum = rand() % 10;
int xran;
char sol;

for ( ; ; )
        {
            // 询问玩家的猜测;
            cout << "The current number is " << randnum << endl;
            cout << "The next number will be larger or smaller\?" << endl;
            cout << "Enter s for smaller, or enter l for larger. ";
            cout << "Notice that l is the lower case of letter L, not the number one. " << endl;
            cin >> sol;

            // 答非所问的处理
            if (sol != 's' && sol != 'l')
            {
                cout << "Your answer has to be either s or l. ";
                cout << "Notice that l is the lower case of L, not the number one. " << endl; 
                continue;            
            }

            xran = rand() % 10;  // 生成新随机数
            
            if (xran == randnum)  // 新随机数与前一随机数相等时,回到循环起点。
            {
                cout << "The new number is " << xran << ". ";
                cout << "It is equal to the last number. " << endl;
            }
            else if (xran < randnum)
            {
                cout << "The new number is " << xran << ". ";
                cout << "It is smaller than " << randnum << ". " << endl;
                
                if (sol == 's')
                {                                     
                    cout << "Congratulations! your answer is correct." << endl;
                    randnum = xran;
                    n++;  
                    // 猜对了,累积猜对数目 +1,xran 赋值给 randnum,继续循环。
                }
                else if (sol == 'l')
                {
                    cout << "We are sorry but this time your answer is wrong. ";
                    cout << "You have made it right " << n << " times." << endl;
                    cout << "Game Over." << endl;
                    break;
                    // 猜错了,显示累积猜对数目,循环结束。
                }
            }
            else if (xran > randnum)
            {
                cout << "The new number is " << xran << ". ";
                cout << "It is larger than " << randnum << ". " << endl;
                if (sol == 'l')
                {
                    cout << "Congratulations! your answer is correct." << endl;
                    randnum = xran;
                    n++;
                    // 猜对了,累积猜对数目 +1,xran 赋值给 randnum,继续循环。
                }
                else if (sol == 's')
                {
                    cout << "We are sorry but this time your answer is wrong. ";
                    cout << "You have made it right " << n << " times." << endl;
                    cout << "Game Over." << endl;
                    break;
                    // 猜错了,显示累积猜对数目,循环结束。
                }
            }
        }

整体代码

把上文中的第二段代码嵌套到第一段代码中的循环里的对应位置,再做些小的改动,就可以得到完整的代码了。需要注意的是因为代码中用到了 rand() 函数、srand() 函数以及 time() 函数,所以头文件除了iostream 外还需要包含 cstdlib 以及ctime。下面是整体代码:

#include <iostream>
#include <cstdlib>
#include <ctime>

int main()
{
    using namespace std;
    cout << "In this game, your computer will come up with ";
    cout << "an interger in the range of 0 to 9." << endl;
    cout << "You will be asked to guess if the next number is ";
    cout << "larger or smaller than the current number." << endl;
    char will, sol;
    int n = 0;
    srand((unsigned)time(0));
    int randnum = rand() % 10;
    int xran;

    for ( ; ; )
    {
        cout << "Are you willing to play the game\? ";
        cout << "Type y to start the game. Type n to exit." << endl;
        cin >> will;

        cin.ignore(1024, '\n');

        if(will == 'n') 
        {
            break;
        }
        else if(will != 'n' && will != 'y')
        {
            cout << "Your answer has to be either n or y." << endl;
            cout << "Press any key to continue." << endl;
            cin.get();
            continue;
        }
             
        for ( ; ; )
        {
            cout << "The current number is " << randnum << endl;
            cout << "The next number will be larger or smaller\?" << endl;
            cout << "Enter s for smaller, or enter l for larger. ";
            cout << "Notice that l is the lower case of letter L, not the number one. " << endl;
            cin >> sol;

            cin.ignore(1024, '\n');

            xran = rand() % 10;

            if (sol != 's' && sol != 'l')
            {
                cout << "Your answer has to be either s or l. ";
                cout << "Notice that l is the lower case of L, not the number one. " << endl;
                cout << "Press any key to continue." << endl;
                cin.get();
                continue;
            }
            else if (xran == randnum)
            {
                cout << "The new number is " << xran << ". ";
                cout << "It is equal to the last number. " << endl;
                cout << "Press any key to continue. " << endl;
                cin.get();
            }
            else if (xran < randnum)
            {
                cout << "The new number is " << xran << ". ";
                cout << "It is smaller than " << randnum << ". " << endl;
                if (sol == 's')
                {                                     
                    cout << "Congratulations! your answer is correct." << endl;
                    cout << "Press any key to continue." << endl;
                    cin.get();
                    randnum = xran;
                    n++;
                }
                else if (sol == 'l')
                {
                    cout << "We are sorry but this time your answer is wrong. ";
                    cout << "You have made it right " << n << " times." << endl;
                    cout << "Game Over." << endl;
                    cin.get();
                    break;
                }
            }
            else if (xran > randnum)
            {
                cout << "The new number is " << xran << ". ";
                cout << "It is larger than " << randnum << ". " << endl;
                if (sol == 'l')
                {
                    cout << "Congratulations! your answer is correct." << endl;
                    cout << "Press any key to continue." << endl;
                    cin.get();
                    randnum = xran;
                    n++;
                }
                else if (sol == 's')
                {
                    cout << "We are sorry but this time your answer is wrong. ";
                    cout << "You have made it right " << n << " times." << endl;
                    cout << "Game Over." << endl;
                    cin.get();
                    break;
                }
            }
        }
        break;
    }
    return 0;
}

最后,笔者点开用上面的代码编译生成的 .exe 文件玩了玩,画风是这样的:


image

当年计算机没有图形界面的时候的电脑游戏估计就是这个画风吧。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容

  • 今天我读了一个绿叶仙踪上的故事,明教惨遭劫难,我最喜欢的。词语是咬牙切齿,小心翼翼和操我最喜欢的部分是因盒子里装着...
    韩梦荧阅读 130评论 0 0
  • 今天的过山车行情有必要来记录一样。 昨天晚上,确切的讲,应该是昨天凌晨A股纳入了MSCI指数,一场历时4年的考试,...
    yichen大刀阅读 238评论 0 1
  • 在农历九月十二的那一天,是我们这里的大集,也就十里路吧,我骑着电车去赶集。 回来路过一片冬瓜地时,看见那地里的冬瓜...
    uuuvfd阅读 437评论 0 8
  • “五行漫谈”第十期 主题内容:《最动人的语言》 互动嘉宾是一位事业有成,气质典雅有情怀的成功女性。 她有一个13岁...
    杜薇说五行阅读 172评论 0 2
  • kubernetes是谷歌开源的容器集群管理系统,是Google多年大规模容器管理技术Borg的开源版本 (1)基...
    jiangshanhot阅读 528评论 0 0