当前位置: 首页 > news >正文

猜数字游戏

本文面向C语言初学者,通过实现一个完整的猜数字游戏,带你掌握随机数生成、循环、条件判断等核心概念


一、项目简介

1.1 游戏规则

  • 电脑:自动生成 1~100 的随机数

  • 玩家:输入猜测的数字

  • 反馈:根据猜测提示"大了"或"小了"

  • 目标:在有限次数内猜中数字




1.2 学习目标

  • 掌握随机数生成原理

  • 熟练使用循环和条件语句

  • 理解用户输入和程序交互

  • 培养逻辑思维和调试能力





二、核心技术:随机数生成

2.1 为什么需要随机数?

在很多游戏中,随机元素让游戏更有趣、更具挑战性。比如:

  • 猜数字游戏中的神秘数字

  • 扑克游戏的洗牌

  • 游戏中的随机事件




2.2 C语言中的随机数函数

rand() 函数原型

int rand(void);

函数说明:
  • rand() 不需要任何参数

  • 生成一个伪随机数

  • 随机数范围:0 ~ RAND_MAX

  • RAND_MAX的大小依赖编译器实现,大部分编译器上是32767


rand() 函数生成伪随机数
#include <stdlib.h>int num = rand();


测试rand()函数

让我们实际测试一下rand函数,多次调用生成5个随机数:

#include <stdio.h>
#include <stdlib.h>int main() 
{printf("随机数测试:\n");printf("%d\n", rand());printf("%d\n", rand());printf("%d\n", rand());return 0;
}
运行结果:
随机数测试:
1804289383
846930886
1681692777

🔍(>﹏<) 发现问题:每次运行程序生成的"随机数"序列完全相同!



为什么总是相同的随机数?

  • rand() 生成的是伪随机数

  • 基于一个称为"种子"的基准值计算得出

  • 默认种子值为 1,所以每次结果相同



伪随机数 vs 真随机数:

  • 伪随机数:通过算法生成的看似随机的数列,实际上可预测

  • 真随机数:基于物理现象(如热噪声)生成,完全不可预测




2.3 解决方案:设置随机种子

srand() 函数原型

void srand(unsigned int seed);  // 设置随机数种子

功能说明:
  • 用于初始化随机数生成器

  • 参数 seed 是随机数种子

  • 相同的种子会产生相同的随机数序列


关键点:
  • 只需在程序开始时调用一次

  • 种子变化,随机数序列才会变化




2.4 time() 函数:获取时间戳

time() 函数原型

time_t time(time_t* timer);

时间戳背景及意义:
  • 定义:从1970年1月1日00:00:00 UTC到当前时刻的秒数

  • 别称:Unix时间戳、Epoch时间

  • 意义:提供持续变化的数值,是理想的变化种子源


时间戳的重要性:
  • 每时每刻都在变化

  • 不会重复(在同一秒内)

  • 是获取"变化值"的简单方法


time() 函数获取变化的值
#include <time.h>time_t current_time = time(NULL);  // 获取当前时间戳


时间戳知识拓展:

时间戳的统一标准意义:

现实生活中不同地区存在时差,时间戳为计算机界提供了统一的时间标准,让全球的计算机系统能够基于同一时间参照进行运作,确保日志系统、文件时间戳、网络通信等不会因为时区差异而混乱。


为什么选择1970年1月1日作为起点:
  • 这是Unix操作系统的设计者选择的纪元时间

  • 当时计算机存储空间有限,需要选择一个较近的日期

  • 现在已成为计算机行业的通用标准




2.5 正确的随机数生成方案

#include <stdio.h>
#include <stdlib.h>
#include <time.h>int main() 
{// 设置随机种子为当前时间srand((unsigned int)time(NULL));printf("真正的随机数:\n");for(int i = 0; i < 5; i++) {printf("%d\n", rand());}return 0;
}

运行效果:

  • 每次运行程序都会产生不同的随机数序列

  • 真正实现了"随机"效果




2.6 设置随机数范围

常用范围设置方法:

需求公式示例
0~99rand() % 100rand() % 100
1~100rand() % 100 + 1rand() % 100 + 1
100~200100 + rand() % 101100 + rand() % 101
a~ba + rand() % (b-a+1)10 + rand() % 21 (10~30)


数学原理:

  • rand() % N 产生 0 到 N-1 的随机数

  • 通过加法和乘法调整范围和起始值



生成1~100随机数:

int random_number = (rand() % 100 + 1;




三、猜数字游戏实现

3.1 基础版本:无限次猜测

#include <stdio.h>
#include <stdlib.h>
#include <time.h>int main() 
{int random_num = 0;int guess = 0;// 初始化随机数种子srand((unsigned int)time(NULL));// 生成1~100的随机数random_num = rand() % 100 + 1;printf("=== 猜数字游戏 ===\n");printf("我已经想好了1-100之间的一个数字,请开始猜吧!\n\n");while (1) {printf("请输入你猜的数字: ");scanf("%d", &guess);if (guess > random_num) {printf("太大了!再小一点试试\n\n");}else if (guess < random_num) {printf("太小了!再大一点试试\n\n");}else {printf("恭喜你!猜对了!\n");break;}}return 0;
}



3.2 增强版本:限制猜测次数

#include <stdio.h>
#include <stdlib.h>
#include <time.h>int main() 
{int random_num = 0;int guess = 0;int count = 0;const int max_attempts = 5;  // 最大尝试次数// 初始化随机数种子srand((unsigned int)time(NULL));// 生成1~100的随机数random_num = rand() % 100 + 1;printf("=== 猜数字游戏 ===\n");printf("数字范围:1-100\n");printf("你有%d次机会!\n\n", max_attempts);for (count = 1; count <= max_attempts; count++) {printf("第%d次尝试: ", count);scanf("%d", &guess);if (guess > random_num) {printf("太大了!");}else if (guess < random_num) {printf("太小了!");}else {printf("恭喜你!第%d次猜对了!\n", count);break;}// 显示剩余次数int remaining = max_attempts - count;if (remaining > 0) {printf("还有%d次机会\n\n", remaining);}}// 检查是否失败if (count > max_attempts) {printf("\n很遗憾,机会用完了!\n");printf正确答案是: %d\n", random_num);}return 0;
}



3.3 完整豪华版本(带进度条和颜文字)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>// 跨平台的头文件包含
#ifdef _WIN32#include <windows.h>
#else#include <unistd.h> `
#endifvoid delay(int);
void showLoadingBar();
void printWelcome();
int getDifficulty();
void showThinkingAnimation();
void giveHint(int, int, int, int);
void showVictoryAnimation(int);
void showDefeatAnimation();int main() 
{// 显示欢迎信息和加载进度printWelcome();showLoadingBar();// 选择难度int max_attempts = getDifficulty();// 显示思考动画showThinkingAnimation();// 游戏初始化srand((unsigned int)time(NULL));int target = rand() % 100 + 1;int guess, attempts = 0;printf("游戏开始!我已经想好了一个1~100之间的神秘数字  <( ̄︶ ̄)↗[GO!]\n");printf("让我们看看你能不能猜中它! ψ(`▽′)ψ\n\n");// 游戏主循环while(attempts < max_attempts) {attempts++;printf("第%d次猜测: ", attempts);if(scanf("%d", &guess) != 1) {printf("(; ̄Д ̄) 请输入有效的数字!\n");while(getchar() != '\n'); // 清空输入缓冲区attempts--; // 不计算这次无效输入continue;}// 检查输入范围if(guess < 1 || guess > 100) {printf(" 请输入1~100之间的数字!\n\n");attempts--;continue;}// 判断猜测结果if(guess == target) {showVictoryAnimation(attempts);printf("第%d次猜中!数字就是 %d!\n", attempts, target);// 根据表现给出评价if(attempts == 1) {printf("(/≧▽≦)/ 一击必中!你是预言家吗?\n");} else if(attempts <= max_attempts / 3) {printf("q(≧▽≦q) 太厉害了!直觉很准!\n");} else if(attempts <= max_attempts * 2 / 3) {printf("(^_-)db(-_^) 表现不错!很有潜力!\n");} else {printf("( ̄▽ ̄)~* 险胜!但还是很棒!\n");}break;} else if(guess > target) {printf("   (;′Д`)太大了!");giveHint(guess, target, attempts, max_attempts);} else {printf("  (⊙﹏⊙∥)太小了!");giveHint(guess, target, attempts, max_attempts);}// 显示进度int remaining = max_attempts - attempts;if(remaining > 0) {printf("还有%d次机会 ヾ( ̄□ ̄)o\n\n", remaining);}}// 游戏结束处理if(guess != target) {showDefeatAnimation();printf("正确答案是: %d\n", target);// 根据接近程度给出安慰int difference = abs(guess - target);if(difference <= 5) {printf(" 只差一点点了!下次一定能行!o(*^▽^*)┛\n");} else if(difference <= 15) {printf("已经很接近了,继续努力!(~ ̄▽ ̄)~\n");} else {printf("不要气馁,再来一次!ヾ(°Д°`)o\n");}}// 结束动画printf("\n");printf("感谢游玩");fflush(stdout);for(int i = 0; i < 3; i++) {delay(200);printf(".");fflush(stdout);}printf(" (*^▽^*)\n");return 0;
}// 跨平台的延迟函数
void delay(int milliseconds) 
{#ifdef _WIN32Sleep(milliseconds);#elseusleep(milliseconds * 1000);#endif
}void showLoadingBar() 
{printf("游戏初始化中");fflush(stdout);  // 刷新输出缓冲区for(int i = 0; i < 3; i++) {delay(300);  // 延迟300毫秒printf(".");fflush(stdout);}printf("\n");printf("[");// 进度条动画for(int i = 0; i <= 50; i++) {printf("=");fflush(stdout);delay(50);  // 延迟50毫秒// 在特定进度显示提示信息if(i == 10) {printf("] 生成随机数...\n[");fflush(stdout);} else if(i == 30) {printf("] 设置游戏参数...\n[");fflush(stdout);}}printf("] 完成!\n\n");
}// 显示欢迎信息
void printWelcome() 
{// 游戏界面加载动画 printf("界面初始化中 ");fflush(stdout);  // 刷新输出缓冲区char spinner[] = "|/-\\";for(int i = 0; i < 20; i++) {printf("\b%c", spinner[i % 4]);  // \b 退格字符fflush(stdout);delay(100);}printf("\b[完成!]\n");// 游戏界面    printf("=====================================\n");printf("############ 猜数字游戏 #############\n");printf("=====================================\n");printf("游戏规则:\n");printf("* 电脑生成 1~100 的随机数\n");printf("* 你有多次机会猜中它\n");printf("* 每次猜测后我会给你提示\n");printf("=====================================\n\n");
}// 选择难度
int getDifficulty() 
{int choice;printf("请选择难度:(oˇvˇ)ノ\n");printf("1. 简单模式 (8次机会) ( ̄▽ ̄)\n");printf("2. 普通模式 (5次机会) ( ̄ω ̄;)\n");printf("3. 困难模式 (3次机会) (;一_一)\n");printf("4. 地狱模式 (1次机会) (╯°□°)╯\n");printf("请选择(1-4): ");scanf("%d", &choice);switch(choice) {case 1: printf("已选择简单模式 ( ̄▽ ̄)\n");return 8;case 2: printf("已选择普通模式 ( ̄ω ̄;)\n");return 5;case 3: printf("已选择困难模式 (;一_一)\n");return 3;case 4:printf("已选择地狱模式 (╯°□°)╯\n");return 1;default: printf("(X﹏X) 无效选择,使用普通模式\n");return 5;}
}// 显示思考动画
void showThinkingAnimation() 
{printf("\n我正在想一个神秘数字");fflush(stdout);for(int i = 0; i < 5; i++) {delay(200);printf(".");fflush(stdout);}printf(" 想好了! ヾ(≧▽≦*)o\n\n");
}// 给出智能提示
void giveHint(int guess, int target, int attempt, int max_attempts) 
{int difference = abs(guess - target);if(attempt == 1 && difference > 40) {printf("    ╮( ╯-╰ ) ╭提示:和目标相差很远哦!\n");} else if(difference <= 3) {printf("    (☆▽☆) 超级接近!就差一点点了!\n");} else if(difference <= 8) {printf("    ╰(°▽°) ╯很接近了,继续加油!\n");} else if(difference <= 15) {printf("    <( ̄︶ ̄)ノ有点接近了!\n");}// 根据剩余机会给出策略提示int remaining = max_attempts - attempt;if(remaining == 1) {printf("   (っ °Д °;)っ最后一次机会了,要谨慎选择!\n");} else if(remaining <= 3) {printf("  ╮(╯_╰ ) ╭剩余机会不多了,好好思考!\n");}
}// 显示胜利动画
void showVictoryAnimation(int attempts) 
{printf("\n");for(int i = 0; i < 3; i++) {printf("★");fflush(stdout);delay(200);}printf(" (〃 ̄︶ ̄)人( ̄︶ ̄〃) 恭喜你! ");for(int i = 0; i < 3; i++) {printf("★");fflush(stdout);delay(200);}printf("\n");
}// 显示失败动画
void showDefeatAnimation() 
{printf("\n");for(int i = 0; i < 3; i++) {printf("@");fflush(stdout);delay(300);}printf(" /(ㄒoㄒ)/~~ 游戏结束! ");for(int i = 0; i < 3; i++) {printf("@");fflush(stdout);delay(300);}printf("\n");
}




四、代码详解

4.1 核心逻辑分解

1. 随机数生成

srand((unsigned int)time(NULL));  // 用当前时间设置种子
int target = rand() % 100 + 1;    // 生成1~100的随机数

(◕‿◕✿) 重要提示srand()只需要在程序开始调用一次,多次调用反而会影响随机性



2. 游戏循环结构

while(attempts < max_attempts) 
{// 1. 获取用户输入// 2. 验证输入有效性  // 3. 判断大小关系// 4. 给出反馈提示// 5. 检查游戏结束条件
}


3. 输入验证

if(scanf("%d", &guess) != 1) {printf("(; ̄Д ̄) 请输入有效的数字!\n");while(getchar() != '\n'); // 清空错误输入continue;
}



4.2 进度条功能详解

基础进度条

void showLoadingBar() 
{printf("加载中[");for(int i = 0; i < 20; i++) {printf("#");fflush(stdout);  // 立即显示输出delay(100);      // 延迟100毫秒}printf("] 完成!\n");
}


分段进度条

void segmentedLoadingBar() 
{printf("初始化系统");delay(500);printf("...[完成]\n");printf("生成随机数");delay(500);printf("...[完成]\n");printf("准备游戏界面");delay(500);printf("...[完成]\n");
}


动态进度条

void dynamicLoadingBar() 
{char spinner[] = "|/-\\";printf("处理中 ");for(int i = 0; i < 20; i++) {printf("\b%c", spinner[i % 4]);  // \b 退格字符fflush(stdout);delay(100);}printf("\b完成!\n");
}


关键技术点

  1. fflush(stdout) - 强制刷新输出缓冲区
  • 强制刷新输出缓冲区

  • 确保字符立即显示在屏幕上

  1. 延迟函数 - 跨平台兼容处理
  • Unix/Linux: usleep(微秒)

  • Windows: Sleep(毫秒)

  • 跨平台解决方案见上面的代码

  1. 进度显示 - 分段显示加载状态
  • 使用循环逐步增加进度字符

  • 可以添加百分比显示



动画设计原则

  1. 度原则
  • 动画时间不宜过长(1-3秒为宜)

  • 避免影响游戏流畅性

  1. 反馈及时
  • 每个操作都有相应的视觉反馈

  • 进度条显示当前状态

  1. 一致性
  • 保持动画风格统一

  • 使用相似的延迟时间



兼容性考虑

  1. 跨平台支持
  • 使用条件编译处理不同系统

  • 提供简化版本作为备选

  1. 性能优化
  • 在低配置设备上自动禁用复杂动画

  • 提供设置选项让用户选择





五、扩展练习

想要进一步提升?试试这些挑战:


挑战1:添加计分系统

根据猜测次数给予分数:

  • 1次猜中:100分 ٩(◕‿◕。)۶

  • 2-3次:80分 ( ̄ω ̄)

  • 4-5次:60分 (・ω・)

  • 失败:0分 (;一_一)

挑战2:实现游戏记录

保存玩家的最佳成绩,显示历史记录。

挑战3:增加数字范围选择

让玩家可以选择数字范围。

挑战4:添加双人模式

一个玩家设置数字,另一个玩家来猜。





六、常见问题解答

Q1: 为什么每次运行数字都一样?

A: 忘记调用srand((unsigned int)time(NULL))来设置变化种子。ヽ(;▽;)ノ

Q2: 如何生成不同范围的随机数?

A: 使用公式:最小值 + rand() % (最大值 - 最小值 + 1) (•̀ᴗ•́)و

Q3: 输入非数字时程序崩溃怎么办?

A: 使用scanf()返回值检查输入是否成功,失败时清空输入缓冲区。

Q4: 如何让游戏可以重复玩?

A: 在外层添加一个循环,询问玩家是否再来一局。





七、学习总结

通过这个猜数字游戏,我们学会了:

(✓) 随机数生成rand(), srand(), time()的配合使用
(✓) 循环结构while循环控制游戏流程
(✓) 条件判断if-else进行大小比较
(✓) 用户交互:输入输出和提示信息
(✓) 调试技巧:分段测试和错误处理
(✓) 用户体验:进度条和动画效果设计

(◕‿◕✿) 编程心法:从简单版本开始,逐步添加功能,每步都测试确保正确性。

这个项目虽然简单,但包含了完整程序的骨架。掌握了这些基础,你就能迈向更复杂的C语言项目了!


动手实践是学习编程的唯一捷径! 现在就开始编写你的第一个游戏吧! ヾ(≧▽≦*)o

如果有任何问题,欢迎在评论区留言讨论~ (´• ω •`)ノ

http://www.dtcms.com/a/554436.html

相关文章:

  • html5 手机网站 图标ui是什么意思
  • 中国建设人才信息网站官网网络推广策略概念
  • VSCode插件开发实战:从零到发布的技术大纲
  • 做旅游网站能成功网页设计图片素材关于设计
  • 如何自己建网站中牟县建设局网站
  • 网站建设描述怎么写高级网页设计师证
  • 华为云iot mqtt 异常停止消费
  • go-mysql-transfer 伪装从库实现 MySQL 到 Redis 数据同步(完整配置)
  • 重庆做网站建设哪家好destoon 手机网站模板
  • 自己建的网站能赚钱吗小程序定制开发解决方案
  • 论文笔记(九十七)PhysiAgent: An Embodied Agent Framework in Physical World
  • 4个可落地执行方法,深挖用户需求!
  • unity DoTween DoPath设置物体按照指定轨迹运动
  • 成都网站开发建设公司在网站加上一个模块怎么做
  • 企业网站开发服务器世界建设企业网站
  • 【VLNs篇】13:JanusVLN 数据说明
  • 打印机共享维护工具
  • 做钢管的去什么网站发信息wordpress插件选项
  • 【RPA教学】E-mail
  • 郑州网站设计 品牌 视觉中国教育建设协会网站
  • 过年做啥网站致富加强网站制度建设
  • 网站打不开 其它能打开怎么做网站 新手做网站
  • 记录:用proxy解决前后端跨域限制问题
  • ps如何做网站横幅网站seo优化多少钱
  • 构建AI智能体:八十、SVD知识整理与降维:从数据混沌到语义秩序的智能转换
  • 【Docker Desktop+wsl+Hyper-V】下载与安装(Windows系统Docker环境)
  • 网站管理规范朔州企业网站建设公司
  • Win10开机自启动怎么设置?关闭开机启动6大方法
  • 网站宣传语女装标题优化关键词
  • 国内网站建设推荐建立平台的步骤