C语言实战第一篇:简易猜数字游戏实现与拓展
一.项目需求实现一个控制台版猜数字游戏具备以下功能1.电脑随机生成一个1 ~ 100之间的整数2.提供主菜单支持选择“开始游戏”或“退出游戏”3.处理玩家非法输入如字母、符号、非法数字防止程序卡死4.每次猜测后给出“猜大了”“猜小了”的提示5.玩家猜测正确后游戏回到主菜单界面二.分步实现代码与思路讲解那我们正式开始梳理我们的设计思路首先搭建一个主函数框架//主函数框架intmain(){return0;}随后我们要打印一个简单的主菜单要让用户“有得选”这里我们可以选择封装为一个函数命名为menu这个函数不需要返回值和参数只负责打印主菜单当然printf函数需要头文件stdio.h咱们后续就默认已经有了这个头文件了#includestdio.h//打印主菜单voidmenu(){printf(---------------------\n);printf(------猜数字游戏------\n);printf(-------1. play-------\n);printf(-------0. exit-------\n);printf(---------------------\n);}主菜单有了用户也就可以开始进行选择了这里我们可以用printf函数先告诉用户可以选择数字了随后用scanf函数接收用户输入的值在用户输入完成后我们需要用到条件语句去对用户输入的值进行判断输入1的话进入游戏这里我们先拟定一个game函数后面进行实现输入0的话退出游戏如果输入的是其他值可以告诉用户输入的值是非法的这里我选择的是switch语句当然如果使用if语句也是可以的这里就不过多做展开了intmain(){intinput0;menu();printf(请输入您要选择的数字);scanf(%d,input);//判断用户输入switch(input){case1:game();break;case0:printf(退出游戏\n);break;default:printf(输入非法请输入有效数字\n);break;}return0;}这个时候我们可能在想如果每一次都让break直接跳出的话那相当于程序的运行是“一次性”的也就是说这个游戏只能运行一次那我们的初心“输入0退出游戏”就显得有些多余了有没有什么办法能让用户如果不输入0就一直运行下去呢使用循环迭代去解决问题是相对比较好的我在这里选择的是do-while循环因为我们希望程序上来不要管别的先打印一次主菜单也就是先运行一次游戏后续再进行逻辑判断用户要玩还是退出do-while循环明显是更合适的问题在于循环条件是什么呢根据上述代码我们发现输入0为“退出”这个设计刚好让while的判断条件为假而其他任何数字都会被判断为真所以while的循环条件同样可以使用input进行判断intmain(){intinput0;//循环执行逻辑do{menu();printf(请输入您要选择的数字);scanf(%d,input);switch(input){case1:game();break;case0:printf(退出游戏\n);break;default:printf(输入非法请输入有效数字\n);break;}}while(input);return0;}当然这里我们也要考虑到用户可能输入的是字母和符号也就是字符那这里我们可以对scanf的返回值进行判断如果返回值不是正常的1就用getchar函数清空缓冲区随后continue回到循环的起始位置intmain(){intinput0;do{menu();printf(请输入您要选择的数字);///合法性判断if(scanf(%d,input)!1){while(getchar()!\n);printf(输入非法请输入有效数字\n);continue;}switch(input){case1:game();break;case0:printf(退出游戏\n);break;default:printf(输入非法请输入有效数字\n);break;}}while(input);return0;}主函数的框架我们基本已经完成了接下来就是对game函数的处理game函数也同样不需要任何返回值和参数我们只需要关心函数内部的逻辑是如何实现的但在那之前我们首先要做一件事情生成随机值这里我们可以使用rand函数来进行随机值的生成rand函数是可以返回一个随机值的但rand函数生成的随机值是“伪随机”的因为它依靠种子Seed去生成随机值这是它的“基准”。且Seed默认都是1而且rand是无参函数不能传参那我们怎么改变这个Seed呢这里需要用到srand函数对Seed进行初始化但进行传参的时候我们同样需要一个随机值那有没有什么值是一直在变化的呢对时间戳我们可以调用time函数对其传一个空指针就可以对srand的参数进行随机生成了因为时间戳是一直在变化的rand和srand函数的调用需要用到头文件stdlib.htime函数的调用需要头文件time.h但需要注意time函数的返回值是time_t类型的而srand的参数要求是无符号整型所以需要强制类型转换感兴趣的也可以去网上查这里用的网址是www.cplusplus.com这里有一个小问题我们项目的要求是随机值要在1 ~ 100之间而rand生成的随机数字范围是多大是0 ~ RAND_MAX而RAND_MAX的值通常是32767那怎么做到把这个范围变成1 ~ 100取模是个不错的选择也就是让这个数字模上100那么这个随机值的余数就是0 ~ 99只需要再加上1范围就变成了1 ~ 100符合项目要求beautiful之后我们就可以在函数内部使用printf和scanf提醒用户可以输入自己猜测的数字了并用scanf函数接收用户输入的值我们可以定义一个guess变量存储用户猜测的数字把rand的返回值存储到num变量里然后使用if条件语句对guess和num进行大小比较判断而我们想实现让“一直猜”的效果就可以用while死循环来实现猜对后break跳出即可这里我的循环条件使用了Bool类型使用别的当然也是可以的布尔类型需要头文件stdbool.h逻辑如下#includestdlib.h#includetime.h#includestdbool.hvoidgame(){srand((unsignedint)time(NULL));intguess0;intnumrand()%1001;while(true){printf(请输入您要猜测的数字);if(scanf(%d,guess)!1){while(getchar()!\n);printf(输入非法请输入有效数字\n);continue;}if(guessnum){printf(猜大了\n);}elseif(guessnum){printf(猜小了\n);}else{printf(恭喜你猜对了\n);break;}}}但这里也需要注意time(NULL)的精度是秒如果在同一秒内多次开始游戏生成的随机数会完全一样所以如果玩的人比较多的话把srand放在main函数里是更好的至此我们的简易项目就圆满完成了三.功能拓展那我们这个项目能不能拓展一些功能呢或者进行一些优化呢相信大家都有自己的想法这里我就以“增加猜测次数限制功能”举例我们怎么实现猜测次数限制呢首先game函数里的while循环条件要动吗其实可以改也可以不改因为我们的代码逻辑是“一直猜猜对了就break跳出循环”如果不改的话无非就是增加一个次数变量在循环内部的开头判断一次如果条件为真break跳出即可这和改动循环条件为次数变量归0时再判断本质上是一样的我们这里就不进行改动了由于次数限制可能是需要频繁被修改的我们可以直接宏定义一个GUESS_TIMES次数用这个宏定义去定义就可以了当然如果想在用户游戏失败后告诉用户正确答案也是可行的这里我就直接展示代码了逻辑如下#defineGUESS_TIMES5voidgame(){srand((unsignedint)time(NULL));intleftGUESS_TIMES;intguess0;intnumrand()%1001;while(true){if(left0){printf(很遗憾%d次机会用完您失败了\n,GUESS_TIMES);printf(正确答案为%d\n,num);break;}printf(请输入您要猜测的数字您还有%d次机会,left);if(scanf(%d,guess)!1){while(getchar()!\n);printf(输入非法请输入有效数字\n);continue;}if(guessnum){printf(猜大了\n);left--;}elseif(guessnum){printf(猜小了\n);left--;}else{printf(恭喜你猜对了\n);break;}}}至此我们的代码优化也结束了接下来是完整的.c代码#define_CRT_SECURE_NO_WARNINGS#defineGUESS_TIMES5#includestdio.h#includestdlib.h#includetime.h#includestdbool.hvoidgame(){srand((unsignedint)time(NULL));intleftGUESS_TIMES;intguess0;intnumrand()%1001;while(true){if(left0){printf(很遗憾%d次机会用完您失败了\n,GUESS_TIMES);printf(正确答案为%d\n,num);break;}printf(请输入您要猜测的数字您还有%d次机会,left);if(scanf(%d,guess)!1){while(getchar()!\n);printf(输入非法请输入有效数字\n);continue;}if(guessnum){printf(猜大了\n);left--;}elseif(guessnum){printf(猜小了\n);left--;}else{printf(恭喜你猜对了\n);break;}}}voidmenu(){printf(---------------------\n);printf(------猜数字游戏------\n);printf(-------1. play-------\n);printf(-------0. exit-------\n);printf(---------------------\n);}intmain(){intinput0;do{menu();printf(请输入您要选择的数字);if(scanf(%d,input)!1){while(getchar()!\n);printf(输入非法请输入有效数字\n);continue;}switch(input){case1:game();break;case0:printf(退出游戏\n);break;default:printf(输入非法请输入有效数字\n);break;}}while(input);return0;}代码虽然简单但是也还是挺有趣的~