我是C编程的初学者,如果我能得到一些关于如何设置程序重新启动的提示,我将不胜感激?我目前正在构建一个猜谜游戏,其中用户有4次尝试猜测随机提供的秘密号码。我几乎已经完成了代码,但它不能正常运行,并且它返回的某些内容不正确。请帮忙。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
int a, Thenumber, GuessNumber, NumberofTries = 4, theAnswer;
time_t ti;
printf("Welcome to the game. \nI am going to choose any number between 10 and 30");
printf("\nYou must try to guess the number. If you guess incorrect, I will tell you if you were too high or too low");
printf("\nYou will have 4 attempts to guess the number.\n");
srand((unsigned)time(&ti));
Thenumber = rand() % 1 + 3 + 1;//10+20+1;4
for (NumberofTries = 0; NumberofTries < 4; NumberofTries++) {
printf("\n \nPlease enter a number:");
scanf("%d", &GuessNumber);
if (GuessNumber > 30) {
printf("That is illegal. Your number can only be between 10 and 30. Please enter a number between those numbers:/n");
}
else if (GuessNumber > Thenumber) {
printf("I'm sorry, that is too high. \n");
}
}
if (GuessNumber < Thenumber) {
printf("I'm sorry, that is too low. \n");
}
else if (GuessNumber == Thenumber) {
printf("You are correct. Do you want to continue playing? y-yes n-no: \n");
return 0;
}
printf("\n \nI'm sorry, you have no more attempts.\n \nDo you want to play again? y-yes n-no: \n");
scanf("%d", &theAnswer);
if ((theAnswer = 'n')) {
printf("Goodbye, thank you for playing. Please play again soon.");
}
return 0;
}
您的输入程序非常脆弱。如果您这样做,会发生什么情况:
Please enter a number: twenty-one
使用scanf()
会发生匹配失败,从标准输入中提取的字符将停止,
将留在
相反,所有用户输入都应该使用面向行的输入函数来完成,例如
fgets()
或POSIXgetline()
。有了足够大的输入缓冲区(字符数组),fgets()
将一次消耗整行(最多为以nul结尾的字符的缓冲区-1
的大小)。如果初始lineptr
参数设置为NULL
并且n=0
参见man 3 getline,getline()
将动态分配足够的缓冲区来保存整行
然后,使用
尝试读取用户输入。与所有用户输入函数和数字转换函数一样,您必须验证返回值,以了解输入或转换是否成功。这不是可选的。否则,您将邀请“未定义行为”。sscanf()
解析缓冲区中的数值,而不是使用
为了提示"…继续玩?"
,您将需要嵌套循环。处理游戏的简单方法是:
while (choice == 'y') {
/* generate random in range */
for (tries = 0; tries < NTRIES; ) {
/* handle your guesses */
tries += 1;
}
/* prompt for continue playing? & read choice */
}
(注意:(;;;)的中没有增量。)
循环定义。如果输入有效,则只增加尝试次数。)
当您在C中使用具有自动存储持续时间的变量(在程序堆栈上创建的普通变量)时,任何在初始化之前访问其值的尝试(即当其值不确定时)都会导致未定义行为)。现在您可以使用
ti
,因为您不会在以下位置访问其值:
srand((unsigned)time(&ti));
但是使用它的地址——但我怀疑这种区别已经完全消失了。新程序员的经验法则——初始化所有值以避免UB的可能性。对于
srand()
播种随机数生成器可以简单地使用:
srand (time (NULL));
您对
Thenumber
的初始化不会导致10-30
之间的值。相反,您需要:
Thenumber = rand() % (30 - 10 + 1);
接下来,不要在代码中分散魔术数字。如果您需要一个常量,
#定义
它或使用全局枚举
来做同样的事情。例如:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NTRIES 4 /* if you need a constant, #define one (or more) */
#define MINNUM 10
#define MAXNUM 30
#define MAXC 1024
那么你你的号码一代就变成了:
Thenumber = rand() % (MAXNUM - MINNUM + 1);
这样,如果尝试的次数改变了,或者你想改变游戏的范围,你就不必通过每个循环限制和条件语句来进行改变。您只需更改在代码顶部方便定义的常量。
当您向用户呈现输出时,如果您的输出中不涉及转换,则无需使用可变参数
printf()
函数。如果您正在输出文本并想要尾随'\n'
,您可以简单地使用put()
,或者如果您需要行尾控制(例如在提出问题并且您不想要'\n'
输出时),您可以简单地使用put()
。无论如何,对于任何一个输出,您不需要对输出函数进行一次以上的调用,例如。
printf ("Welcome to the game.\n\n" /* a single printf will do */
"I am going to choose any number between %d and %d\n\n"
"You must try to guess the number. If you guess incorrect, I will tell you\n"
"if you were too high or too low. You will have %d attempts to guess the "
"number.\n", MINNUM, MAXNUM, NTRIES);
接下来,您需要一种系统化的方法来检查用户是否:
已经猜到了正确的数字,(这可能是第一个条件检查,因为如果他猜到了,回合就结束了)
- 如果用户的猜测超出范围,
- 如果猜测小于数字,或者最后
- 如果猜测大于数字。
您可以编写类似于以下内容的逻辑:
if (guess == number) { /* winner! */
puts ("\n Correct!");
goto again;
}
else if (guess < MINNUM || MAXNUM < guess) { /* guess out-of-range */
printf ("\n guess out of range, allowed %d - %d\n", MINNUM, MAXNUM);
continue;
}
else if (guess < number) { /* guess < number */
fputs ("\n I'm sorry, that was too low.\n", stdout);
}
else { /* guess > number */
fputs ("\n I'm sorry, that was too high.\n", stdout);
}
(同样,在任何极限中都没有幻数)
很明显,当你进入循环控制部分,要求用户再次播放时,你被卡住了。你将有你的外环控制选择继续和内环是一个完整的游戏。内部和外部之间的唯一混合将是一个可选选择,即是否在上面的条件中添加另一个
elseif(tries==NTRIES)
,并在内部循环中处理未尝试的情况,或者是否允许在中对(tries=0;tries)进行正常循环控制
总而言之,你可以这样做:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NTRIES 4 /* if you need a constant, #define one (or more) */
#define MINNUM 10
#define MAXNUM 30
#define MAXC 1024
int main() {
char buf[MAXC] = "y"; /* array to hold user-input */
int guess, number, tries; /* 3 int variables */
printf ("Welcome to the game.\n\n" /* a single printf will do */
"I am going to choose any number between %d and %d\n\n"
"You must try to guess the number. If you guess incorrect, I will tell you\n"
"if you were too high or too low. You will have %d attempts to guess the "
"number.\n", MINNUM, MAXNUM, NTRIES);
srand (time(NULL)); /* Using NULL is fine */
while (*buf == 'y') { /* test choice */
number = MINNUM + rand() % (MAXNUM - MINNUM + 1); /* rand() 10 - 30 (inclusive) */
for (tries = 0; tries < NTRIES; ) { /* do not increment */
fputs ("\nenter a number: ", stdout); /* no conversion, fputs() */
if (fgets (buf, MAXC, stdin) == NULL) { /* validate every input */
fputs ("(user canceled input)\n", stdout);
return 0;
}
if (sscanf (buf, "%d", &guess) != 1) { /* validate every conversion */
fputs ("error: invalid integer.\n", stderr);
continue;
}
if (guess == number) { /* winner! */
puts ("\n Correct!");
goto again;
}
else if (guess < MINNUM || MAXNUM < guess) { /* guess out-of-range */
printf ("\n guess out of range, allowed %d - %d\n", MINNUM, MAXNUM);
continue;
}
else if (guess < number) { /* guess < number */
fputs ("\n I'm sorry, that was too low.\n", stdout);
}
else { /* guess > number */
fputs ("\n I'm sorry, that was too high.\n", stdout);
}
tries += 1; /* increment only if not continued due to error in input */
}
printf ("\n\n%d tries exhaused, the number was '%d'.\n", NTRIES, number);
again:;
fputs ("\n\nplay again (y/n)? ", stdout);
if (fgets (buf, MAXC, stdin) == NULL) {
fputs ("(user canceled input)\n", stdout);
return 0;
}
}
/* no conversion involved and appended '\n' wanted -- use puts() */
puts ("\nGoodbye, thank you for playing. Please play again soon.");
}
(注意:上面的设计选择使用一个简单的
goto
在成功猜测时跳过out-of-tries代码,留下for
loop来控制out-of-tries逻辑,而不是添加另一个
-完全由您决定。用两种方式编写并比较差异)
最后,虽然不是错误,但C通常避免使用
camelCase
或MixedCase
变量和函数名,而只使用小写,同时保留大写名称以用于宏和常量。这是一个风格问题,所以这完全取决于你,但如果不遵循它,在某些圈子里可能会导致错误的第一印象。
示例使用/输出
您的输入必须处理用户可以输入的任何内容(或猫踩键盘):
$ ./bin/guessnumber
Welcome to the game.
I am going to choose any number between 10 and 30
You must try to guess the number. If you guess incorrect, I will tell you
if you were too high or too low. You will have 4 attempts to guess the number.
enter a number: twenty-one
error: invalid integer.
enter a number: 3
guess out of range, allowed 10 - 30
enter a number: 33
guess out of range, allowed 10 - 30
enter a number: 20 okay, okay, okay!!!
I'm sorry, that was too high.
enter a number: 15
Correct!
play again (y/n)? y
...
再次选择播放必须生成一个新的数字,重置所有值:
enter a number: 20
I'm sorry, that was too low.
enter a number: 25
I'm sorry, that was too low.
enter a number: 28
I'm sorry, that was too high.
enter a number: 27
I'm sorry, that was too high.
4 tries exhaused, the number was '26'.
play again (y/n)? n
Goodbye, thank you for playing. Please play again soon.
当你编写一个输入例程时 -- 去尝试打破它。输入尽可能多的有趣值,看看它是否正确处理它。如果没有,请修复它并重试。用户输入必须是防弹的...因为用户会用你的代码做最愚蠢的事情。确保它可以处理它。
还要注意,如果对
fgets()
的测试失败,则会显示"(用户取消输入)"
。这是因为用户可以使用Ctrl d(或Windows上的Ctrl z)生成手动EOF
。在这种情况下,这不是错误,用户只是选择取消输入——因此应该在此时使用优雅的程序退出来处理。
有很多东西需要消化。仔细看看,如果你还有其他问题,请告诉我。学习C不是一场比赛,而是一场旅程——放慢速度,理解你在每行中使用的每个字符,然后享受这段旅程。
我不知道这是否能解决你的问题,但这里有几点:
srand(time(&ti));
您不必将time()
强制转换为unsigned,因为1970年1月1日之后的时间不能为负值。
我不知道你的代码会发生什么,没有编译器来测试它,但是你应该始终初始化你的变量,因为你正在调用未定义的行为。
另一种方法是:
srand(time(null));
这将使用您机器上的当前时间初始化随机生成器。
Thenumber = rand() % 1+3+1;//10+20+1;
< code>%对< code> 有优先权,因此< code>rant()%1总是返回< code>0
检查“猜测数字”
的 if-else 语句应位于 for 循环内,而不是位于其后。
当你在 main()
方法中使用 return 0;
时,你的程序将终止,所以你不想这样做。
尝试更改:
if ((theAnswer = 'n'))
至:
if ('n' == theAnswer)
因为你想比较,而不是分配。双括号不会导致逻辑错误,但会增加混乱并降低代码的易读性。
本文向大家介绍C# 生成随机数的代码,包括了C# 生成随机数的代码的使用技巧和注意事项,需要的朋友参考一下 以上就是本文的全部内容了,希望大家能够喜欢,能够对大家学习C#有所帮助。
本文向大家介绍C++编写生成不重复的随机数代码,包括了C++编写生成不重复的随机数代码的使用技巧和注意事项,需要的朋友参考一下 C++编写生成不重复的随机数代码 再来一例: 方法三:来个复杂点的 以上3种方法均可实现生成不重复的随机数,具体的效率如何,小伙伴们自己测试下吧。
我想用骰子做一个游戏,我需要在其中加入随机数(以模拟骰子的侧面。我知道如何在1到6之间进行)。使用 不能很好地工作,因为当我运行程序几次时,我得到的输出是: 所以我想要一个每次都会生成不同随机数的命令,而不是连续5次生成相同的随机数。是否有命令可以执行此操作?
本文向大家介绍C++生成不重复的随机整数,包括了C++生成不重复的随机整数的使用技巧和注意事项,需要的朋友参考一下 C++生成不重复的随机数,供大家参考,具体内容如下 给定正整数的范围[n,m],生成k个不重复的随机数字。 IDE是vs013。 运行结果: 这个程序可以用于班级内部按照学号进行随机抽签。 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
本文向大家介绍C语言/C++如何生成随机数,包括了C语言/C++如何生成随机数的使用技巧和注意事项,需要的朋友参考一下 本文分享了C语言/C++如何生成随机数的具体实现方法,供大家参考,具体内容如下 C语言/C++怎样产生随机数:这里要用到的是rand()函数, srand()函数,C语言/C++里没有自带的random(int number)函数。 (1) 如果你只要产生随机数而不需要设定范围的
我想使用c生成0-2^64范围内的非常大的随机数。我使用了rand()函数,但它没有生成非常大的数字。任何一个都可以帮助吗?