首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >猜数字游戏

猜数字游戏

作者头像
Nullmian
发布2025-12-24 15:10:05
发布2025-12-24 15:10:05
80
举报

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


一、项目简介

1.1 游戏规则

  • 电脑:自动生成 1~100 的随机数
  • 玩家:输入猜测的数字
  • 反馈:根据猜测提示"大了"或"小了"
  • 目标:在有限次数内猜中数字



1.2 学习目标

  • 掌握随机数生成原理
  • 熟练使用循环和条件语句
  • 理解用户输入和程序交互
  • 培养逻辑思维和调试能力




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

2.1 为什么需要随机数?

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

  • 猜数字游戏中的神秘数字
  • 扑克游戏的洗牌
  • 游戏中的随机事件



2.2 C语言中的随机数函数

rand() 函数原型
代码语言:javascript
复制
int rand(void);

函数说明:
  • rand() 不需要任何参数
  • 生成一个伪随机数
  • 随机数范围:0 ~ RAND_MAX
  • RAND_MAX的大小依赖编译器实现,大部分编译器上是32767

rand() 函数生成伪随机数
代码语言:javascript
复制
#include <stdlib.h>

int num = rand();


测试rand()函数

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

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>

int main() 
{
    printf("随机数测试:\n");
    printf("%d\n", rand());
    printf("%d\n", rand());
    printf("%d\n", rand());
    
    return 0;
}
运行结果:
代码语言:javascript
复制
随机数测试:
1804289383
846930886
1681692777

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



为什么总是相同的随机数?
  • rand() 生成的是伪随机数
  • 基于一个称为"种子"的基准值计算得出
  • 默认种子值为 1,所以每次结果相同


伪随机数 vs 真随机数:
  • 伪随机数:通过算法生成的看似随机的数列,实际上可预测
  • 真随机数:基于物理现象(如热噪声)生成,完全不可预测



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

srand() 函数原型
代码语言:javascript
复制
void srand(unsigned int seed);  // 设置随机数种子

功能说明:
  • 用于初始化随机数生成器
  • 参数 seed 是随机数种子
  • 相同的种子会产生相同的随机数序列

关键点:
  • 只需在程序开始时调用一次
  • 种子变化,随机数序列才会变化



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

time() 函数原型
代码语言:javascript
复制
time_t time(time_t* timer);

时间戳背景及意义:
  • 定义:从1970年1月1日00:00:00 UTC到当前时刻的秒数
  • 别称:Unix时间戳、Epoch时间
  • 意义:提供持续变化的数值,是理想的变化种子源

时间戳的重要性:
  • 每时每刻都在变化
  • 不会重复(在同一秒内)
  • 是获取"变化值"的简单方法

time() 函数获取变化的值
代码语言:javascript
复制
#include <time.h>

time_t current_time = time(NULL);  // 获取当前时间戳


时间戳知识拓展:
时间戳的统一标准意义:

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


为什么选择1970年1月1日作为起点:
  • 这是Unix操作系统的设计者选择的纪元时间
  • 当时计算机存储空间有限,需要选择一个较近的日期
  • 现在已成为计算机行业的通用标准



2.5 正确的随机数生成方案

代码语言:javascript
复制
#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~99

rand() % 100

rand() % 100

1~100

rand() % 100 + 1

rand() % 100 + 1

100~200

100 + rand() % 101

100 + rand() % 101

a~b

a + rand() % (b-a+1)

10 + rand() % 21 (10~30)



数学原理:
  • rand() % N 产生 0 到 N-1 的随机数
  • 通过加法和乘法调整范围和起始值


生成1~100随机数:
代码语言:javascript
复制
int random_number = (rand() % 100 + 1;




三、猜数字游戏实现

3.1 基础版本:无限次猜测

代码语言:javascript
复制
#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 增强版本:限制猜测次数

代码语言:javascript
复制
#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 完整豪华版本(带进度条和颜文字)

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// 跨平台的头文件包含
#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h> `
#endif

void 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 _WIN32
        Sleep(milliseconds);
    #else
        usleep(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. 随机数生成
代码语言:javascript
复制
srand((unsigned int)time(NULL));  // 用当前时间设置种子
int target = rand() % 100 + 1;    // 生成1~100的随机数

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



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


3. 输入验证
代码语言:javascript
复制
if(scanf("%d", &guess) != 1) {
    printf("(; ̄Д ̄) 请输入有效的数字!\n");
    while(getchar() != '\n'); // 清空错误输入
    continue;
}



4.2 进度条功能详解

基础进度条
代码语言:javascript
复制
void showLoadingBar() 
{
    printf("加载中[");
    for(int i = 0; i < 20; i++) 
    {
        printf("#");
        fflush(stdout);  // 立即显示输出
        delay(100);      // 延迟100毫秒
    }
    printf("] 完成!\n");
}


分段进度条
代码语言:javascript
复制
void segmentedLoadingBar() 
{
    printf("初始化系统");
    delay(500);
    printf("...[完成]\n");
    
    printf("生成随机数");
    delay(500);
    printf("...[完成]\n");
    
    printf("准备游戏界面");
    delay(500);
    printf("...[完成]\n");
}


动态进度条
代码语言:javascript
复制
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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、项目简介
    • 1.1 游戏规则
    • 1.2 学习目标
  • 二、核心技术:随机数生成
    • 2.1 为什么需要随机数?
    • 2.2 C语言中的随机数函数
      • rand() 函数原型
      • 测试rand()函数
      • 为什么总是相同的随机数?
      • 伪随机数 vs 真随机数:
    • 2.3 解决方案:设置随机种子
      • srand() 函数原型
    • 2.4 time() 函数:获取时间戳
      • time() 函数原型
      • 时间戳知识拓展:
    • 2.5 正确的随机数生成方案
      • 运行效果:
    • 2.6 设置随机数范围
      • 常用范围设置方法:
      • 数学原理:
      • 生成1~100随机数:
  • 三、猜数字游戏实现
    • 3.1 基础版本:无限次猜测
    • 3.2 增强版本:限制猜测次数
    • 3.3 完整豪华版本(带进度条和颜文字)
  • 四、代码详解
    • 4.1 核心逻辑分解
      • 1. 随机数生成
      • 2. 游戏循环结构
      • 3. 输入验证
    • 4.2 进度条功能详解
      • 基础进度条
      • 分段进度条
      • 动态进度条
      • 关键技术点
      • 动画设计原则
      • 兼容性考虑
  • 五、扩展练习
    • 挑战1:添加计分系统
    • 挑战2:实现游戏记录
    • 挑战3:增加数字范围选择
    • 挑战4:添加双人模式
  • 六、常见问题解答
    • Q1: 为什么每次运行数字都一样?
    • Q2: 如何生成不同范围的随机数?
    • Q3: 输入非数字时程序崩溃怎么办?
    • Q4: 如何让游戏可以重复玩?
  • 七、学习总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档