发牌算法 的实现

本文介绍了发牌算法,用于模拟内存分配的页式存储系统,避免内存碎片。算法通过特定的取牌策略保证每次发的牌不重复,降低了时间复杂度。文章详细阐述了算法思想,并通过构建牌池、发牌、显示牌和排序等步骤展示了算法的实现过程,同时将这一概念与计算机处理内存分配的页式存储结构进行了类比。
摘要由CSDN通过智能技术生成

我们在了解计算机语言的时候,能够知道,当软件被使用时,会先调入内存,当调用完成,就释放空间。
那么。这些连续存储空间的分配和回收操作,存在一个问题:会产生“内存碎片
为了避免上述情况,现代计算机通常采用“页式存储系统”来实现内存申请与回收操作

那么,为了将这个例子更加形象地展示出来,我们这里用一个算法来解释这种操作的原理——发牌算法

发牌算法:

顾名思义,要求是,发出去的牌不会再次被发出

现在看到这个要求,我们的第一想法可能是用一个数组(先命名为arr数组)来存储取出的值,每当规定范围随机数产生数的时候,我们遍历arr数组,来看看这个值存在不存在这个数组中,若不存在,我们就将这个数输出,并将这个数存在arr数组中,以防下次输出此数。

若是今天本篇博文按照上述的思想去编程的话,可能会让知情的编程老手笑掉大牙吧,因为我们数据结构与算法的主要思想是编写的程序的时间复杂度尽可能地低,而若是按照上面的思想,无疑每产生一个数就要去遍历数组,有新的数产生的话,我们还要为数组赋值,这样看来,时间复杂度很高。

那么,现在,本人来介绍本篇博文的主题算法——发牌算法。用这个算法来实现我们上述的要求,时间复杂度非常低,只需遍历一个长度尽可能低的数组(即时间复杂度为O(n))

那么,发牌算法大致思想:
我们按照数组的下标取数,将已经取出的“牌”和未取出数组内的最后一张“牌”交换下标,并使得下一次“取牌”时的未取出的范围比这次的范围少1

现在我们来编写一些程序,来使得我们上述的逻辑更加清晰化、形象化:
我们现在要取牌,那么就先编写两个全局数组——花色数组牌值数组


const char *pokerType[] = {
   "黑桃", "红桃", "方块", "梅花"};	//[]比*优先级高,所以这个定义的意义是字符串数组

//10是两个字符,所以类型是char *
const char *pokerValue[] = 
	{
   "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};

那么,现在我们来编写一个构建牌池函数

#define POKERS_COUNT 52

void resetPoker(char *poker) {
   
	int i;

	for(i = 0; i < POKERS_COUNT; i++) {
   
		poker[i] = i;
	}
}

上面这个函数可能让好多人感觉一头雾水,为什么单纯的将相应下标存入数组相应单元的操作被我们称为取数函数呢?
因为一副扑克牌一共有52张,我们花色按照“黑桃、红桃、方块、梅花”,大小按照“A->K”的顺序,将所有牌从下标为0到51全部存入一个数组中,相当于将所有牌全部放在了poker数组中。

那么,有了牌池,我们现在就来为玩家发牌,即“取牌操作”了,现在我们来编写取牌函数

#define POKERS_COUNT	52
#define POKER_TYPE_COUNT	13

void dealPoker(char (*pokerSet)[POKER_TYPE_COUNT]) {
   
	char pokerSet[POKERS_COUNT];
	int range;
	int index = 0;

	resetPoker(pokerSet);
	srand(time(0));
	for(range = POKERS_COUNT; range > 
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值