【C语言】猜数游戏
系统随机产生四个不同的有序的数字 (从小到大排列),等待用户输入猜测的结果, 用A来表示数字正确且位置正确的个数 ,用B来表示数字正确但位置不正确的个数,给八次机会,猜中则游戏成功,机会用完则游戏失败
分析:1.需要一个数组存放生成的随机数,保证数据不重复且按从小到大排列
2.需要另外一个数组存放用户的猜测结果
3.需要一个变量记录已经猜了多少次
4.将两个数组进行比较,统计A和B的个数并告知用户,方便其继续猜
5.当用户全部猜中或机会用完时,游戏结束,退出
我第一次得到题目时编写的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
//提示游戏规则
printf("****************************************************\n");
printf("*********************游戏规则***********************\n");
printf("系统将随机生成四个不同的有序数字(按从小到大排列)\n");
printf("请输入您猜测的四个数字\n");
printf("用A表示数字正确且位置正确的个数\n");
printf("用B表示数字正确但位置不正确的个数\n");
printf("一共有八次机会\n");
printf("****************************************************\n");
//产生不同的随机数
srand(time(NULL));
int number[4];
number[0] = rand() %9+1;
number[1] = rand() %9+1;
number[2] = rand() %9+1;
number[3] = rand() %9+1;
while (number[1] == number[0]) {
number[1] = rand() %9+1;
}
while (number[2] == number[1] || number[2] == number [0]) {
number[2] = rand() %9+1;
}
while (number[3] == number[2] || number[3] == number [1] || number[3] ==number[0]) {
number[3] = rand() %9+1;
}
//这一句是为了检查数据是否重复,真正编译时应该删掉
printf("%4d %4d %4d %4d\n",number[0],number[1],number[2],number[3]);
//将随机数按从小到大排列
for(int i = 0; i < 4; i++){
for(int j = 0; j < i; j++)
{
if(number[i] < number[j]){
number[i] = number[i] + number[j];
number[j] = number[i] - number[j];
number[i] = number[i] - number[j];
}
}
}
//这一句是为了检查数据是否正确排列,真正编译时应该删掉
printf("%4d %4d %4d %4d\n",number[0],number[1],number[2],number[3]);
//输入数据并判断
int guess[4];
int count = 8;
do{
int countA = 0;
int countB = 0;
//提示用户输入数据
printf("请输入四个1~9的数字(每输一个按一次回车):\n");
for (int i = 0; i < 4; i++) {
scanf("%d",&guess[i]);
while (guess[i] < 1 || 9 < guess[i]) {
printf("输入数据有误,请重新输入\n");
scanf("%d",&guess[i]);
}
}
printf("%4d %4d %4d %4d\n",guess[0],guess[1],guess[2],guess[3]);
//判断数字、位置是否相同并计数
for ( i = 0; i < 4; i++) {
if (guess[i] == number[i]) {
countA++;
continue;
}
for (int j = 0; j < 4; j++) {
if (i == j) {
continue;
} else if (guess[i] == number[j]){
countB++;
}
}
}
printf("一共有 %dA,%dB\n",countA,countB);
//判断游戏是否应该结束
if (countA == 4) {
printf("恭喜您!游戏成功\n");
getchar();
getchar();
exit(EXIT_SUCCESS);
}
count--;
printf("还有%d次机会\n",count);
printf("*******************************************\n");
}while (count > 0);
printf("次数用完,游戏失败\n");
printf("正确数字为:%4d %4d %4d %4d\n",number[0],number[1],number[2],number[3]);
getchar();
getchar();
return 0 ;
}
这个代码是存在很多不足的,我在经过这两天学习之后,主要进行了四个修改。
1.产生不同的随机数部分
这是整个代码最傻的部分,我第一次编写时考虑使用for循环比较下标来保证数据不重复,但一直没办法实现,所以用了一个很傻的方法来使它不重复,实际上是不可取的。后来发现可以通过与一个临时变量比较来实现,代码如下:
//产生不同的随机数
srand(time(NULL));
int number[4];
for (int i = 0; i < 4; i++) {
//定义一个temp存放随机数
int temp = rand() %9+1;
//判断是否为第一个数
if (i == 0) {
//是第一个数,直接存放
number[i] = temp;
} else {
//不是,将temp与先前的数进行比较
for (int j = 0; j < i; j++) {
if (number[j] == temp ) {
//相同,退出循环,重新生成temp
i--;
break;
} else{
//不同,直接存放
number[i] = temp;
}
}
}
}
printf("%4d %4d %4d %4d\n",number[0],number[1],number[2],number[3]);
用这个方法就不会显得那么傻,而且可以借鉴到其他地方
2.判断数字、位置是否相同并计数部分
这一部分乍一看没问题,其实可以更加简化,也更方便理解,代码如下:
//判断数字、位置是否相同并计数
for (i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
//判断数字是否相同
if (guess[i] == number[j]){
//数字相同,判断位置是否相同
if (i == j) {
//位置相同,A+1
countA++;
} else{
//位置不同,B+1
countB++;
}
}
}
}
printf("一共有 %dA,%dB\n",countA,countB);
3.将随机数按从小到大排列部分
这个部分主要是在两个数据交换位置时,通过两个数据相互加减的方法来交换虽然不需要引入第三个变量,但是增加了运算,使效率变低,也显得不够简单,因此最后改为引入第三个变量进行交换。
4.对countA、countB的定义部分
将 int countA和int countB放进了do…while循环中,造成了重复定义,这实际上是不够严谨的,于是将这两个变量的定义提到外部,并在循环的最后将其清零。
修改后的所有代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
//提示游戏规则
printf("****************************************************\n");
printf("*********************游戏规则***********************\n");
printf("系统将随机生成四个不同的有序数字(按从小到大排列)\n");
printf("请输入您猜测的四个数字\n");
printf("用A表示数字正确且位置正确的个数\n");
printf("用B表示数字正确但位置不正确的个数\n");
printf("一共有八次机会\n");
printf("****************************************************\n");
//产生不同的随机数
srand(time(NULL));
int number[4];
for (int i = 0; i < 4; i++) {
//定义一个temp存放随机数
int temp = rand() %9+1;
//判断是否为第一个数
if (i == 0) {
//是第一个数,直接存放
number[i] = temp;
} else {
//不是,将temp与先前的数进行比较
for (int j = 0; j < i; j++) {
if (number[j] == temp ) {
//相同,退出循环,重新生成temp
i--;
break;
} else{
//不同,直接存放
number[i] = temp;
}
}
}
}
//这一句是为了检查数据是否重复,真正编译时应该删掉
printf("%4d %4d %4d %4d\n",number[0],number[1],number[2],number[3]);
//将随机数按从小到大排列
for( i = 0; i < 4; i++){
for(int j = 0; j < i; j++)
{
if(number[i] < number[j]){
//使用第三方变量更方便,也更有效率
int temp = 0;
temp = number[i];
number[i] = number[j];
number[j] = temp;
}
}
}
//这一句是为了检查是否正确排序,真正编译时应该删掉
printf("%4d %4d %4d %4d\n",number[0],number[1],number[2],number[3]);
//输入数据并判断
int guess[4];
int count = 8;
int countA = 0;
int countB = 0;
do{
/*
int countA = 0;
int countB = 0; 定义只定义一次,所以应该在外部定义
*/
//提示用户输入数据
printf("请输入四个1~9的数字:\n");
for (int i = 0; i < 4; i++) {
scanf("%d",&guess[i]);
//判断数据是否在1-9区间内
while (guess[i] < 1 || 9 < guess[i]) {
printf("输入数据有误,请重新输入\n");
scanf("%d",&guess[i]);
}
}
printf("%4d %4d %4d %4d\n",guess[0],guess[1],guess[2],guess[3]);
//判断数字、位置是否相同并计数
for (i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
//判断数字是否相同
if (guess[i] == number[j]){
//数字相同,判断位置是否相同
if (i == j) {
//位置相同,A+1
countA++;
} else{
//位置不同,B+1
countB++;
}
}
}
}
printf("一共有 %dA,%dB\n",countA,countB);
//判断是否全部猜中
//全部猜中,游戏结束
if (countA == 4) {
printf("恭喜您!游戏成功\n");
getchar();
getchar();
exit(EXIT_SUCCESS);
}
//没猜中,次数-1,A、B清零
count--;
countA = 0;
countB = 0;
printf("还有%d次机会\n",count);
}while (count > 0);
//机会用完,游戏结束
printf("次数用完,游戏失败。\n");
getchar();
getchar();
return 0 ;
}
其实这个程序还有不完善的地方,比如说没有考虑用户输入相同数字时的处理等,但题目所需要的功能已经实现,玩一玩还是挺有意思的
还没有评论,来说两句吧...