在“剪刀石头布”游戏中如果输入一个字母,会进入死循环。。
多谢你发现这个问题!原因是scanf扫描的输入不匹配则不会读走,下次循环这个字母还在,还读不走,再下次循环这个字母还在……要避免这个问题目前没啥好办法,只能是出错就终止程序了。讲到后面可以先用fgets读上来再用sscanf扫描。
我是学软件测试的。。所以经常会搞些这种去试。
正常的应该是让你输入整数你就不应该输入字母或者其他字符,但软件应该有个容错功能。。我觉得可以把那个scanf("%d",&man)改成scanf("%c",&man)用它的asc码来判断。。内存出错我也用过一个fflush(stdin)来清空。。这个函数是怎么实现的我不知道,只知道他可以用。。班门弄斧了,见笑见笑。你的意见非常对,但是scanf("%c"...)实在不是好玩的,要费更多唇舌才能解释清楚。scanf在标准库一章会详细解释,在这一章为了避免跑题,还是用这个不怎么容错的办法吧。今天又想到一种方法。。可以一试哦~这回不要用scanf("%c"...)。
flag=1;
while(flag){
fflush(stdin);
flag=0;
x=99999;//设置一不太可能用到的数
if(x==999999)
{
flag=1
}
}十分同意并欣赏:“数据代替了代码,数据驱动的编程(Data-driven Programming)"
“剪刀石头布”游戏的结果裁决也可以利用这个原理:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char game_type[3][8]={"scissor", "stone", "cloth"};
char result_type[3][13]={"Draw", "Computer win", "Human win"};
int computer_choice,human_choice;
int ret,result;
while(1){
//computer choice
computer_choice = rand()%3;
//human choice
do{
printf("Please input your choice.0 for scissor, 1 for stone, 2 for cloth \n");
ret = scanf("%d",&human_choice);
}while(human_choice >2||human_choice<0);
//Judgment of choise
printf("Computer choose:%s\n",game_type[computer_choice]);
printf("human choose: %s\n",game_type[human_choice]);
//Judgment of result
result= ((computer_choice - human_choice) + 3) % 3;
printf("Game result:%s\n",result_type[result]);
}
return 0;
}
(man - computer + 4) % 3 - 1神奇 I know somebody see it as natural, but for me, the expression makes me lunatic. plus 4 bracket modulo 3 minus 1 I collapse! Who can talk about the secret of the statement?
我也不知道(man - computer + 4) % 3 - 1这个算式怎么想出来的?为什么会达到这个效果,宋老师,能否解答一下?谢谢!
这个其实没有多复杂。再仔细想想吧。把所有可能情况下每一步的计算结果都列出来就明白了。
我觉得例8.4的语句 printf("%s\n", days[day]);前面应加上else
你说得很对,多谢!在实体书第二次印刷时会改过来的
860284226 860284226说的问题我竟然没注意到,汗死。。。。。。 恩,只是想提醒一下上面的几位朋友,fflush(stdin)结果是C标准未定义的,所以对程序的可移植性有要求时候要注意。
对于这个问题,我常常使用
while (getchar() != '\n')
continue;
来解决。当玩家输入的是0 电脑是2时候 0-2=-2 -2+4=2 2 mod 3 = 2 2-1 = 1 > 0 玩家获胜。。。。
。。。太神奇了。。。 man-c- 2 -1 0 1 -1 0 2 1 0 +4 2 3 4 5 3 4 6 5 4 mod 3 2 0 1 2 0 1 0 2 1 -1 1 -1 0 1 -1 0 -1 1 0
大概发现了。。。
剪刀石头布 分别为 0 1 2
剪刀对布 -2 胜
石头对剪刀 1 胜
布对石头 1 胜
石头对剪刀 2 负
剪刀对石头 -1 负
石头对布 -1 负
-2 和 1 为胜
2 和 -1 为负
0 为平
让所有情况大于0 用mod限定例8.4中void print_day(int day)内的if应当有个else配对吧,不然day number取1~7意外的数值时会输出乱码!
fflush(stdin)用来清除输入缓冲区只在ms编译器上有用,这是C标准未定义的,在gcc等编译器上并不支持。。。 剪刀 石头 布分别为0 1 2 人 vs 电脑 只有在man - comp = 1 或 man - comp = -2时才是man win... result = (man - computer + 4) % 3 - 1 这个公式正好包含了1与-2的情况,且只有这种情况才能让result > 0.... 为1或者2
-2 和 1 为胜
2 和 -1 为负
0 为平
这个可以想的出来,问题是怎么能够通过这个条件想到那个式子!!!result = (man - computer + 4) % 3 - 1 我的理解: 我们简化这个式子,都以结果非负考虑先: 上面的式子等同于: result = (man - computer + 1) % 3 -1 又等同于: result = (man - computer); 这个结果就是人选择的下标比computer的下标大1 再看看字符数组:剪刀,石头,布,刚好是后面的一个赢前面的那个。(除去负的情况) 现在,我们需要由 result = (man -computer) 往上推:正的情况不考虑。 当人=0,PC=2时,也是人赢,这时,我们需要一个不改变式子大小但是要让 (man -computer)非负的操作,没错,就是取余: result = (man - computer)+1-1; result = (man - computer+1)-1; result = (man - computer + 1)%3-1; result = (man - computer + 4)%3-1; 关于这个式子为什么这个特殊的数字是3,我还没想通..求高人指点
if (ret != 1 || man < 0 || man > 2) {
printf("Invalid input!\n");
return 1;
}
为什么ret==0 和 ret==2 不会执行上面的打印语句?
ret != 1 好像是在判断ret是不是整数,而不是在判断ret等不等于1? 这是怎么回事?
在一条线上均匀展开3种结果: ......输,平,嬴,输,平,嬴...... 任意相同结果出现的周期都是2。 (一组连续的整数中的每个数-其中最大的负数+1)%3,得到的结果展开: ......0,1,2,0,1,2....... 任意相同的两数出现的周期是2。 结果=(一组连续的整数中的每个数-其中最大的负数+1)%3 结果==0 执行动作0 结果==1 执行动作1 结果==2 执行动作2 “一组连续的整数中的每个数-其中最大的负数+1”说明: “连续”表示相邻两数差为1 “-其中最大的负数+1”:如果这是一组连续的正整数就不需要这么做。这么做的目的是为了%3的操作数是正数。
所以下面的代码也能实现相同的结果
result = (man - computer + 3) % 3 ;
if (result == 1)
printf("You win!\n");
else if (result == 0)
printf("Draw!\n");
else
printf("You lose!\n");如果您有建设性意见,哪怕只是纠正一个错别字,也请不吝赐教,您留下的姓名和email将会出现在本书前言的致谢中。再次感谢您的宝贵意见!