本文完全原创!!!!!
本文完全原创!!!!!
本文完全原创!!!!!
如有雷同请联系作者
目录
前言
代码一览
代码剖析
总结
前言
因为学校期末原因,一直没有更新博客。距离上一篇博客居然已有一个多月,在2021年的最后一天痛定思痛,好好反省,怒肝一文。(当然不是为了应付学校作业啦。
游戏已制作成应用程序链接:https://pan.baidu.com/s/1tGO1JNHVPx4ww6G7MMyuQA? 提取码:v6v9?
另外需要原码的可以上作者的码云下载C-learning: 一个小白的仓库 - Gitee.com
主要用到函数、指针的内容,较为简单剖析过程会带过easy的部分。 代码实现了猜数字游戏几乎所有功能,包括以下:
代码一览
本项目仍与三子棋、扫雷一样,通过多文件形式实现,更为直观,可读性更高。准备动手准备动手
头文件head.h:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <time.h>
#include <windows.h>
#include <stdlib.h>
void Num(int* p, int n, int N);
int guess(int* p2, int* p1,int n);
int guess2(int* p2, int* p1, int n,int N);
源文件test.c(主文件):
#include "head.h"
void game2()//闯关模式
{
int i = 0;
int ch = 0;
for (i = 1; i <= 5; i++)
{
system("cls");
int chance = 0;//记录猜测次数
int number = rand() % (int)pow(10, i);
int* p1 = (int*)malloc(sizeof(int) * i);
int* p2 = (int*)malloc(sizeof(int) * i);
printf("欢迎来到第%d关,本关限制次数为%d次,过关所需分数为%d分,干巴爹!\n",i,5*i,4*i);
Num(p1, number, i);
do
{
chance++;
ch = guess2(p2, p1, i,chance);
} while (ch&&chance<5*i);
free(p1);
free(p2);
p1 = p2 = NULL;
if (ch == 2)
break;
}
}
void game()//普通模式
{
system("cls");
int level = 0;
int ch=0;
printf("请选择游戏难度\n");
scanf("%d", &level);
int number = rand() % (int)pow(10, level);//根据难度设置要猜的数字位数
int* p1 = (int*)malloc(sizeof(int) * level);//动态数组存放数字的每一位
Num(p1, number, level);
int* p2 = (int*)malloc(sizeof(int) * level);
do
{
ch=guess(p2, p1, level);
} while (ch);
free(p1);
free(p2);
p1 = p2 = NULL;
}
void menu()
{
printf("***********************\n");
printf("*******请选择***********\n");
printf("*******0.exit**********\n");
printf("*******1.普通模式*******\n");
printf("*******2.闯关模式*******\n");
printf("*******3.游戏说明*******\n");
printf("*******4.开发人员*******\n");
printf("***********************\n");
}
void test_game()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏,886靓仔\n");
break;
case 2:
game2();
break;
case 3:
system("cls");
printf("普通模式规则:\n用户输入难度后输入相应的数字。\n若猜错则给出相应提示(位数和数字均正确的有几个位和数字正确但位置不正确的有几个位),猜测次数不限\n闯关模式规则:\n有猜测次数限制,过关条件有两个,用户在指定次数内猜对数字或得分超过指定值则过关\n得分要求:\n(a) 用户猜的某位数字与 H 中相对应数字相同时,用户得分 2 个公牛(分)。\n(b)用户猜的某位数字与H中相对应数字不相同但却与H中其他位数字相同时,用户得分 1 母牛(分)。\n");
break;
case 4:
system("cls");
printf("无敌帅哥吴英杰(版权警告)\n");
break;
default:
system("cls");
printf("李在赣神魔?这都能选错的?重选。\n");
break;
}
} while (input);
}
int main()
{
test_game();
return 0;
}
?源文件game.c:
#include "head.h"
void Num(int* p, int n, int N)
{
int i = 0;
for (i = N; i > 0; i--)
{
*(p + i-1) = n % 10;
n /= 10;
}
}
int guess(int* p2, int* p1,int n)
{
int i = 0;
int j = 0;
int count1 = 0;
int count2 = 0;
int guess = 0;
int tmp = 0;
printf("请输入一个%d位数\n", n);
scanf("%d", &guess);
tmp = guess;
for (i = n; i > 0; i--)//把猜的每一位都放到数组p2中
{
*(p2 + i - 1) = tmp % 10;
tmp /= 10;
}
//开始比较猜的数
for (i = 0; i < n; i++)
{
if (*(p2 + i) == *(p1 + i))
{
count1++;//位置且数字均相同
}
for (j = 0; j < n; j++)
{
if (*(p2 + i) ==*(p1 + j))
{
count2++;//数字相同的个数
break;
}
}
}
if (count1 == n)
{
printf("恭喜你猜对了\n");
return 0;
}
else
{
printf("输入的数值位置都正确的个数为%d\n数值正确但位置不正确的个数为%d\n", count1, count2 - count1);
return 1;
}
}
int guess2(int* p2, int* p1, int n,int N)
{
int score = 0;//记录分数
int i = 0;
int j = 0;
int count1 = 0;
int count2 = 0;
int guess = 0;
int tmp = 0;
printf("请进行第%d次猜测\n", N);
printf("请输入一个%d位数\n", n);
scanf("%d", &guess);
tmp = guess;
for (i = n; i > 0; i--)//把猜的每一位都放到数组p2中
{
*(p2 + i - 1) = tmp % 10;
tmp /= 10;
}
//开始比较猜的数
for (i = 0; i < n; i++)
{
if (*(p2 + i) == *(p1 + i))
{
count1++;//位置且数字均相同
}
for (j = 0; j < n; j++)
{
if (*(p2 + i) == *(p1 + j))
{
count2++;//数字相同的个数
score++;
break;
}
}
}
score += count1;
if (count1 == n)
{
printf("恭喜您在%d次内猜对,已过关,牛的\n", 5 * n);
return 0;
}
else if (score>=4*n)
{
printf("恭喜你的分数达到%d,已过关,牛的\n",score);
return 0;
}
else
{
printf("输入的数值位置都正确的个数为%d\n数值正确但位置不正确的个数为%d\n", count1, count2 - count1);
if (N == 5 * n)//最后一次猜又猜错了
{
printf("恭喜你过关失败,G啦\n");
return 2;
}
return 1;
}
}
相信看到这里不少大佬已经胸有成竹,躺在床上闭眼用脚一顿输出都能写出比我更好的代码。
代码剖析
下面从思路开始剖析,与前面三子棋和扫雷一样的思路,我们要做的第一件事是从玩家的角度出发,思考他们第一眼会看到什么。
面板实现:
打印完菜单肯定是要选择的呀,直接switch语句上手
void test_game()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏,886靓仔\n");
break;
case 2:
game2();
break;
case 3:
system("cls");
printf("普通模式规则:\n用户输入难度后输入相应的数字。\n若猜错则给出相应提示(位数和数字均正确的有几个位和数字正确但位置不正确的有几个位),猜测次数不限\n闯关模式规则:\n有猜测次数限制,过关条件有两个,用户在指定次数内猜对数字或得分超过指定值则过关\n得分要求:\n(a) 用户猜的某位数字与 H 中相对应数字相同时,用户得分 2 个公牛(分)。\n(b)用户猜的某位数字与H中相对应数字不相同但却与H中其他位数字相同时,用户得分 1 母牛(分)。\n");
break;
case 4:
system("cls");
printf("无敌帅哥吴英杰(版权警告)\n");
break;
default:
system("cls");
printf("李在赣神魔?这都能选错的?重选。\n");
break;
}
} while (input);
}
这部分代码比较简单不再解释。
下面是普通模式和闯关模式的代码
void game()//普通模式
{
system("cls");
int level = 0;
int ch=0;
printf("请选择游戏难度\n");
scanf("%d", &level);
int number = rand() % (int)pow(10, level);//根据难度设置要猜的数字位数
int* p1 = (int*)malloc(sizeof(int) * level);//动态数组存放数字的每一位
Num(p1, number, level);//把要猜的数字每一位放到数组
int* p2 = (int*)malloc(sizeof(int) * level);
do
{
ch=guess(p2, p1, level);
} while (ch);
free(p1);
free(p2);
p1 = p2 = NULL;
}
普通模式的代码首先让用户输入难度,难度分别对应了数字的位数。这里使用了两个动态数组来分别存放电脑自动生成的随机数和玩家猜的数字的每一位,记住是每一位数字。切记这里用完动态数组是要释放内存的,也要把用完的指针赋值为空指针(避免野指针出现)
下面开始进行猜数字
int guess(int* p2, int* p1,int n)
{
int i = 0;
int j = 0;
int count1 = 0;
int count2 = 0;
int guess = 0;
int tmp = 0;
printf("请输入一个%d位数\n", n);
scanf("%d", &guess);
tmp = guess;
for (i = n; i > 0; i--)//把猜的每一位都放到数组p2中
{
*(p2 + i - 1) = tmp % 10;
tmp /= 10;
}
//开始比较猜的数
for (i = 0; i < n; i++)
{
if (*(p2 + i) == *(p1 + i))
{
count1++;//位置且数字均相同
}
for (j = 0; j < n; j++)
{
if (*(p2 + i) ==*(p1 + j))
{
count2++;//数字相同的个数
break;
}
}
}
if (count1 == n)
{
printf("恭喜你猜对了\n");
return 0;
}
else
{
printf("输入的数值位置都正确的个数为%d\n数值正确但位置不正确的个数为%d\n", count1, count2 - count1);
return 1;
}
}
这里分别比较两个数字的每一位,得出数字和位置均一样和只有数字一样的数目,然后打印,作为提示(欧洲人一次猜对就不需要了奥),猜对了返回0退出循环,猜错了返回1继续猜。非常简单的逻辑
下面来看闯关版本,与上面的大同小异
void game2()//闯关模式
{
int i = 0;
int ch = 0;
for (i = 1; i <= 5; i++)
{
system("cls");
int chance = 0;//记录猜测次数
int number = rand() % (int)pow(10, i);
int* p1 = (int*)malloc(sizeof(int) * i);
int* p2 = (int*)malloc(sizeof(int) * i);
printf("欢迎来到第%d关,本关限制次数为%d次,过关所需分数为%d分,干巴爹!\n",i,5*i,4*i);
Num(p1, number, i);
do
{
chance++;
ch = guess2(p2, p1, i,chance);
} while (ch&&chance<5*i);
free(p1);
free(p2);
p1 = p2 = NULL;
if (ch == 2)
break;
}
}
这里一共有五关(随机数最大产生五位数),因此进行五次循环,每次循环都会产生不同的随机数,而不是一样的,这里可以去测试一下,我已经测试过了。
这里的猜的函数判断输赢条件和上面有些不同
int guess2(int* p2, int* p1, int n,int N)
{
int score = 0;//记录分数
int i = 0;
int j = 0;
int count1 = 0;
int count2 = 0;
int guess = 0;
int tmp = 0;
printf("请进行第%d次猜测\n", N);
printf("请输入一个%d位数\n", n);
scanf("%d", &guess);
tmp = guess;
for (i = n; i > 0; i--)//把猜的每一位都放到数组p2中
{
*(p2 + i - 1) = tmp % 10;
tmp /= 10;
}
//开始比较猜的数
for (i = 0; i < n; i++)
{
if (*(p2 + i) == *(p1 + i))
{
count1++;//位置且数字均相同
}
for (j = 0; j < n; j++)
{
if (*(p2 + i) == *(p1 + j))
{
count2++;//数字相同的个数
score++;
break;
}
}
}
score += count1;
if (count1 == n)
{
printf("恭喜您在%d次内猜对,已过关,牛的\n", 5 * n);
return 0;
}
else if (score>=4*n)
{
printf("恭喜你的分数达到%d,已过关,牛的\n",score);
return 0;
}
else
{
printf("输入的数值位置都正确的个数为%d\n数值正确但位置不正确的个数为%d\n", count1, count2 - count1);
if (N == 5 * n)//最后一次猜又猜错了
{
printf("恭喜你过关失败,G啦\n");
return 2;
}
return 1;
}
}
注意看规则,位置和数字都相同的要加2分,所以for遍历完以后score还要再加一边count1,也就是位置和数字都相同的个数。如果最后一次猜的时候还是猜错了,那么过关失败,返回2,退出本次闯关。
总结
代码还是有很多不足,比如清屏功能的实现、面板的美化(真的丑,但是我懒得搞了)。大家有问题可以积极私信留言讨论,如果有问题和更好的建议也欢迎指出,阿里嘎多。学校要到1.20才能放假回家,估计又要停更很久了。期末必胜,绩点高高。
?溜了!
|