C语言随机数生成机制与猜数字游戏实现

1 伪随机数生成的核心机制

C语言标准库通过rand函数提供随机数生成能力,但其本质属于伪随机数(Pseudo-Random Number),而非物理意义上的真随机数。

1.1 rand 函数的工作特性

rand函数原型如下:

c 复制代码
int rand(void);

该函数返回一个介于0RAND_MAX之间的整数。在大多数编译器中,RAND_MAX的值为 32767

关键特性:

  • rand并非真正随机,而是通过确定性算法计算得出;
  • 其输出依赖于一个称为 种子 (seed) 的初始值;
  • 默认情况下,种子固定为1,因此每次程序运行生成的随机数序列完全一致。

若不更改种子,多次运行程序将得到相同的"随机"结果,这在游戏或安全场景中是不可接受的。

2 种子初始化与 srand 函数

为使随机数序列发生变化,必须在调用rand之前初始化种子。

srand函数用于设置随机数生成器的种子,原型为:

c 复制代码
void srand(unsigned int seed);

只要种子发生变化,rand生成的序列就会随之改变。

然而,这引出了一个递归问题:

若想生成随机数,需先有一个随机的种子;但获取随机种子本身又需要随机数。

为了解决该矛盾,通常采用时间作为种子来源。

3 基于时间戳的动态种子

3.1 time函数与时间戳

C语言提供time函数以获取当前时间,其原型为:

c 复制代码
time_t time(time_t *timer);
  • 返回值表示从 1970年1月1日 00:00:00 UTC 到当前时刻的秒数,称为时间戳;
  • 参数通常为NULL,仅返回时间差值;
  • 返回类型为time_t,本质是整数类型。

3.2 完整初始化流程

结合timesrand,即可实现动态种子初始化:

c 复制代码
#include <stdlib.h>
#include <time.h>

srand((unsigned int)time(NULL));

注意:srand只需在程序生命周期中调用一次,频繁调用(尤其在短时间内)会导致种子重复,进而产生相同随机数。

4 猜数字游戏的综合实现

猜数字游戏是分支与循环结构的典型综合应用,其核心逻辑包括:随机数生成、用户输入、条件判断与循环控制。

c 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void menu() {
	printf("===================================\n");
	printf("=======Number Guessing Game========\n");
	printf("===== 1 PLAY === 0 GAME OVER ======\n");
	printf("===================================\n");
}

void play() {
	int sysget = rand() % 100 + 1;
	printf("%d\n", sysget);
	printf("******************************************\n");
	printf("Please enter an integer between 1 and 100:\n");
	int get = 0;
	int count = 0;
	while (sysget != get) {
		count++;
		scanf("%d", &get);
		if (get > sysget) {
			printf("[COUNT:%d] WARNING: too high.\n", count);
		}
		else if (get < sysget) {
			printf("[COUNT:%d] WARNING: too low.\n", count);
		}
		else {
			printf("Congratulations to you.\n");
			printf("\n");
			break;
		}
		if (count == 5) {
			printf("Maximum attempts reached, GAME FAILED.\n");
			printf("\n");
			break;
		}
	}
}

int main() {
	int input = 0;
	srand((unsigned int)time(NULL));
	do {
		menu();
		printf("Please Select:\n");
		scanf("%d", &input);
		switch (input) {
		case 1:
			play();
			break;
		case 0:
			printf("Exit Game\n");
			break;
		default:
			printf("Input error.\n");
			break;
		}
	} while (input);
	return 0;
}
相关推荐
coder!mq22 分钟前
说几个常见的语法糖?
java·开发语言·算法
gugucoding24 分钟前
38. 【Java】Stream API(下):高级操作与性能
java·开发语言
Lhan.zzZ32 分钟前
在 Visual Studio 2022 中打造可扩展的动态链接库模块:从零搭建到原理解析
开发语言·c++·visual studio
LuminousCPP1 小时前
数据结构-双向循环链表
c语言·数据结构·笔记·链表
心平气和量大福大1 小时前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言
码哥DFS1 小时前
构造函数、实例对象、对象原型 ----三者关系
开发语言·javascript·原型模式
quantdash_cc2 小时前
告别自建 Requests/BS4 网页爬虫:基于 QuantDash 搭建零维保的高性能量化行情流水线
开发语言·爬虫·python·pandas·量化·quantdash
ydd1001002 小时前
寻找两个正序数组的中位数 Java 题解,二分分割详解
java·开发语言
半亩码田2 小时前
C#转Python第3.1篇:Python 的 class 没有访问修饰符?面向对象的另一条路
开发语言·python·c#
Wzx1980123 小时前
python沙箱和docker沙箱你选对了吗?
开发语言·python·docker