【C】随机抽取塔罗牌的小程序

文章来源:CSDN 发布日期:2024-04-19 分类:小程序博客 阅读( )

目录

头文件内容

源文件内容

#程序主体

#内部函数

1.菜单函数

2.抽卡函数

part 1 确定抽几张牌

part 2 洗牌

part 3 用常量指针数组储存塔罗牌名称

part 4 塔罗牌正位/逆位的生成,以及结果的打印

重点

1.生成伪随机数

2.指针数组


头文件内容

#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h>#include<stdlib.h>  //包含srand、rand函数声明#include<time.h>  //包含time函数声明

源文件内容

#程序主体

主菜单循环

int main(){	int  input = 0;	do //采用do……while循环,保证菜单能直接打印出来(至少打印一次)	{		menu(); //【菜单函数】		printf("Please select[Input: 1/0]:>/n");		scanf("%d", &input);		switch (input)		{      输入1开始抽卡		case 1: 			printf("*DRAW CARDs*/n");			tarot(); //【抽卡函数】			break;      输入0直接退出		case 0:			printf("EXIT:</n");			break;      输入其他数报错		default:			printf("Error, please reselect:>/n");		}	} while (input);//抽完一次或输错数自动跳回主菜单 //输0直接跳出	return 0;}

#内部函数

1.菜单函数

打印菜单

void menu(){    printf("***************************/n");    printf("		/n");    printf("	1. DRAW CARDs/n");    printf("		/n");    printf("	0. EXIT/n");    printf("		/n");    printf("		/n");    printf("***************************/n");}
2.抽卡函数
void tarot(){//part 1/	//确定抽几张牌	int cardnum = 0;	printf("The number of cards drawn:");	scanf("%d", &cardnum);//part 2/	//初始化数组card[]	int card[79] = { 0 };	for (int i = 0; i < 79; i++) 	{		card[i] = i;	}	//随机打乱数组card[]	for (int i = 0; i < 79; i++) 	{		srand(time(NULL)); //初始化随机数种子		for (int i = 78; i > 0; i--) 		{			int j = rand() % (i + 1); //打乱范围逐步缩小,后面已经打乱过的数不变			int temp = card[i];			card[i] = card[j];			card[j] = temp;		}	}//part 3/	const char* tarotcard[79] = {		"Fool", "Magician", "High Priestess", "Empress", "Emperor",		"Hierophant", "Lovers", "Chariot", "Strength", "Hermit",		"Wheel of Fortune", "Justice", "Hanged Man", "Death", "Temperance",		"Devil", "Tower", "Star", "Moon", "Sun",		"Judgement", "World", "King of Swords", "Queen of Swords", "Knight of Swords",		"Page of Swords", "Ace of Swords", "Two of Swords", "Three of Swords", "Four of Swords",		"Five of Swords", "Six of Swords", "Seven of Swords", "Eight of Swords", "Nine of Swords",		"Ten of Swords", "King of Wands", "Queen of Wands", "Knight of Wands", "Page of Wands",		"Ace of Wands", "Two of Wands", "Three of Wands", "Four of Wands", "Five of Wands",		"Six of Wands", "Seven of Wands", "Eight of Wands", "Nine of Wands", "Ten of Wands",		"King of Cups", "Queen of Cups", "Knight of Cups", "Page of Cups", "Ace of Cups",		"Two of Cups", "Three of Cups", "Four of Cups", "Five of Cups", "Six of Cups",		"Seven of Cups", "Eight of Cups", "Nine of Cups", "Ten of Cups", "King of Pentacles",		"Queen of Pentacles", "Knight of Pentacles", "Page of Pentacles", "Ace of Pentacles", "Two of Pentacles",		"Three of Pentacles", "Four of Pentacles", "Five of Pentacles", "Six of Pentacles", "Seven of Pentacles",		"Eight of Pentacles", "Nine of Pentacles", "Ten of Pentacles","Blank card"	};//part 4/	printf("/n/n");	//生成正位、逆位	char dirct[2] = { 'U','R' };	srand(time(NULL));	for (int n = 0; n < cardnum; n++)	{		//打印		printf("[%c]%s/n",  dirct[direction()], tarotcard[(card[n])]);	}	printf("/n/n");}
part 1 确定抽几张牌
	int cardnum = 0;	printf("The number of cards drawn:");	scanf("%d", &cardnum);
part 2 洗牌
  1. 初始化
    塔罗牌通常由79张卡牌组成。这个标准的塔罗牌牌组包含了22张大阿卡纳牌Major Arcana、56张小阿卡纳牌Minor Arcana以及1张空白牌Blank card
    我们定义一个有79个元素的整形数组来表示塔罗牌:
    	int card[79] = { 0 };//使用for循环将数组用0-78依次填满	for (int i = 0; i < 79; i++) 	{		card[i] = i;	} 
  2. 随机打乱数组
    此处涉及
    随机数的生成
    for (int i = 0; i < 79; i++) 	{		srand(time(NULL)); //初始化随机数种子		for (int i = 78; i > 0; i--) 		{			int j = rand() % (i + 1); //打乱范围逐步缩小,后面已经打乱过的数不变			int temp = card[i];			card[i] = card[j];			card[j] = temp;		}	}
part 3 用常量指针数组储存塔罗牌名称

此处涉及⭐常量指针数组的应用

	const char* tarotcard[79] = {		"Fool", "Magician", "High Priestess", "Empress", "Emperor",		"Hierophant", "Lovers", "Chariot", "Strength", "Hermit",		"Wheel of Fortune", "Justice", "Hanged Man", "Death", "Temperance",		"Devil", "Tower", "Star", "Moon", "Sun",		"Judgement", "World", "King of Swords", "Queen of Swords", "Knight of Swords",		"Page of Swords", "Ace of Swords", "Two of Swords", "Three of Swords", "Four of Swords",		"Five of Swords", "Six of Swords", "Seven of Swords", "Eight of Swords", "Nine of Swords",		"Ten of Swords", "King of Wands", "Queen of Wands", "Knight of Wands", "Page of Wands",		"Ace of Wands", "Two of Wands", "Three of Wands", "Four of Wands", "Five of Wands",		"Six of Wands", "Seven of Wands", "Eight of Wands", "Nine of Wands", "Ten of Wands",		"King of Cups", "Queen of Cups", "Knight of Cups", "Page of Cups", "Ace of Cups",		"Two of Cups", "Three of Cups", "Four of Cups", "Five of Cups", "Six of Cups",		"Seven of Cups", "Eight of Cups", "Nine of Cups", "Ten of Cups", "King of Pentacles",		"Queen of Pentacles", "Knight of Pentacles", "Page of Pentacles", "Ace of Pentacles", "Two of Pentacles",		"Three of Pentacles", "Four of Pentacles", "Five of Pentacles", "Six of Pentacles", "Seven of Pentacles",		"Eight of Pentacles", "Nine of Pentacles", "Ten of Pentacles","Blank card"	};
part 4 塔罗牌正位/逆位的生成,以及结果的打印

此处涉及伪随机数的生成

在塔罗牌中,每张牌都有正位(Upright)和逆位(Reversed)两种状态

	//用数组储存塔罗牌的两种状态 U-正位,R-逆位    char dirct[2] = { 'U','R' };	srand(time(NULL));	for (int n = 0; n < cardnum; n++)	{		//打印结果		printf("[%c]%s/n",  dirct[rand() % 2], tarotcard[(card[n])]);        //rand() % 2 生成一个[0,1]的随机数→即随机打印数组dirct[2]中的下标为0/1的元素	}

这里依次输出随机打乱后的数组的前几项(输出个数是 "part 1 确定抽几张牌" 确定的)

重点

1.生成伪随机数

在C语言中,通常使用srand函数rand函数以及time(NULL)来生成伪随机数

  1. time(NULL)返回一个整数,表示从某个起始时间到当前时间所经过的秒数
    具体来说,time(NULL)返回的是从某个特定的起始时间(通常是1970年1月1日 00:00:00 UTC)到当前时间所经过的秒数——∴time(NULL)返回的是一个不断变化的整数
    //具体的返回值取决于系统和环境设置

  2. rand函数是C语言中的一种伪随机数生成器函数,它用于生成伪随机数
    伪随机数生成器本质上是一个确定性算法,它利用一个初始种子值生成看似随机的整数序列
    rand函数通过访问伪随机数生成器的状态,并对其进行一系列的操作(如移位、异或…),从而生成一个随机数
    种子seed:在随机数生成中,种子是起始值或初始状态的一种表示,它作为一个参数传递给伪随机数生成器算法,用于确定随机数序列的起始点

  3. srand函数用于设置rand函数的初始种子值
    一旦使用srand函数设置了种子值,后续的伪随机数生成器算法(rand函数)都可以接收到这个种子值,并基于该种子值生成对应的随机数

总结⭐

当调用srand(time(NULL))时,time(NULL)返回的是当前时间的秒数作为初始种子值,并将这个初始种子值传递给srand函数。
在经过一定时间后调用rand函数,此时rand函数会采用
当前种子值(当前种子值会根据初始种子值和经过的时间自动更新)通过一些列运算得到最终的伪随机数
※换言之——初始种子值只会影响一次随机数生成器的初始化,而后续的rand函数调用会使用当前种子值进行计算--当前种子值会基于初始种子值和经过的时间自动更新,以确保每次调用rand函数都使用不同的种子值,从而生成不同的随机数序列

*通过取模(%)来确定生成随机数的范围:

    rand() % N  //表示生成一个取值范围为[0 , N)的随机数

为什么不直接用time(NULL)当作随机值?

  • 时间精度:time(NULL)的精度通常是秒级别的,这意味着如果程序在同一秒内多次运行,那么得到的种子值将是相同的。这会导致在相同秒份内生成的伪随机数序列相同,可能无法满足某些需求
  • 预测性:由于时间是可预测的,恶意用户可能会尝试通过分析程序启动的时间来推测伪随机数的生成序列。这对于某些安全或加密相关的应用场景来说是不可取的。

使用srand函数、rand函数以及time(NULL)生成的为什么叫伪随机数?伪在哪?

"伪"指的是生成随机数的算法是基于确定性计算的,并不是真正的随机性。换句话说,伪随机数生成器是通过一系列的计算步骤来生成看似随机的数值序列,而不是真实地依赖于无法预测的自然事件。

在使用srand函数和rand函数生成随机数时,它们实际上都是基于一个确定性算法(通常是线性同余生成器)进行计算的。这意味着,给定相同的种子值,每次运行程序时生成的随机数序列将是相同的,而不是真正的随机。

虽然伪随机数生成器能够模拟许多随机性的特征,但其生成的序列实际上是可重现的。因此,我们称之为"伪随机数",以与真正的随机数(由物理过程或环境因素产生)进行区别。

需要注意的是,尽管伪随机数生成器是基于算法的,但在很多实际应用中,伪随机数已经足够满足大多数需求。对于一些特殊的应用场景,比如密码学、模拟等,可能需要使用更高质量的随机数生成器来满足更严格的随机性要求。

2.指针数组

指针数组是一个数组,其元素都是指针类型。每个指针指向内存中的某个位置,而这个位置可以存储数据或者其他对象的地址。

在C语言中,字符串是以字符数组的形式存储的--而字符数组本质上是一种连续的内存空间,其中每个元素都是字符类型
指针数组可用于存储字符串--我们可以定义一个指针数组,每个元素都指向一个字符串的首地址

E.g.

#include <stdio.h>int main() {    char* names[] = {"Alice", "Bob", "Charlie"};        for (int i = 0; i < sizeof(names) / sizeof(names[0]); i++)     {        printf("%s/n", names[i]);    }        return 0;}

names[ ]是一个指针数组,它包含了三个指针类型的元素——每个元素分别指向字符串 "Alice"、"Bob" 和 "Charlie" 的首地址。
通过for循环遍历指针数组,并使用%s(字符串形式)格式化字符串输出,我们可以依次打印出每个字符串

*常量指针数组:通过指向常量字符串的指针定义的字符串是不可修改的。这样的区分主要是为了保护字符串常量的完整性和安全性。

最新文章:

二维码