c语言牌堆
程序就不写了,写下大致流程
//定义一个数组,或者列表,链表什么的随你
//共52个元素 记作card[52]
//card代表扑克牌的类,有花色(color 枚举,0,1,2,3),点数(枚举 A~K)等属性
card tmp;
for(int i=0;i<52;i++)
{
//计算一个0到52之间的随机数x
tmp=card[i];
card[i]=card[x];
card[x]=tmp;//其实就是交换两张牌
}
//循环下来肯定每张牌都被交换过,有它自己的新位置,也有可能凑巧还在原来的位置
//最后按下标顺序分四堆
‘贰’ C语言模拟掼蛋中一方最多炸弹数的数学期望
掼蛋是一种在江苏、安徽地区广为流传的牌类游戏。由地方的扑克牌局“跑得快”、“八十分”发展而来。牌局采用四人结对竞赛,输赢升级的方式进行。由于使用两副牌,并且有“逢人配”、“同花顺”规则,故炸弹的个数对于牌局来说非常重要。通过C语言模拟的方式,可以预估出一位玩家手中拿到的炸弹数的数学期望。对于评估自己的牌型有着一定的意义。
炸弹 :大于等于4张相同点数的牌,或4张王(称为天王炸弹),或同花顺
逢人配 :两张♥的主牌称为逢人配,在与其他牌配合时可以当除了王之外的任意花色任意点数的牌,主牌的点数可从2取到A
同花顺 :相同花色连续的五张牌,最大的为同花10JQKA,最小的为同花A2345,可当炸弹使用
程序完全模拟掼蛋的操作流程,总体上共有以下5个模块
1.印制牌:按照顺序给108张牌赋上花色和点数
2.洗牌:多次随机交换牌的位置,打乱牌的顺序
3.发牌:将洗完的牌轮流发给4位玩家
4.理牌:(按顺序排列玩家1手中的牌【可不做】)找出玩家1手中炸弹个数的最大值
5.循环重复以上步骤若干次,统计玩家1拿到炸弹个数的平均值并输出结果
其中,1、5在主程序中实现,2、3、4通过函数实现。
首先需要建立一个存储一张牌的花色与点数的结构体poker。
创建包含108个poker结构体的结构体数组deck(一套牌),随后第i张牌的点数即为i模13取余。第1-13、53-65张牌为第一种花色;第14-26、66-78张牌为第二种花色……以此类推,第105、106张牌为小王,算作第5种花色;第107、108张牌为大王,算作第6种花色。
将印制好的牌堆deck传入函数randsort。以 伪随机数种子 ——系统时间产生两个伪随机数i和j,将牌堆中的第i张牌和第j张牌 位置交换 ,重复上述操作1000次。
创建四个poker结构体的结构体数组p1、p2、p3、p4,用于存储4个玩家手中的牌。将结构体数组deck和p1,p2,p3,p4传入函数dealpoker,将deck中的第i张牌发给第j个人,其中j为i模4取余。
共分以下两种情况考虑炸弹的个数:
非同花顺:统计玩家1手中所有点数牌的张数和王的个数,找出所有张数大于等于4的点数,统计其个数,结果即为点数炸弹的炸弹数。 特别地,当某一个点数的牌张数为8张时,需要拆成两个炸弹使用,即炸弹数+1 ;当王的个数为4时,炸弹数+1.
同花顺:需要按顺序检索从A开头到10开头的同花顺。当检索A开头的同花顺时,首先指定一种花色,搜索同花顺的第1张牌,若找到,将这张牌与【非整理好的同花顺】的牌的最后一张交换位置,继续寻找第二张,若找到,将这张牌与【非整理好的同花顺】的牌的倒数第二张交换位置,继续寻找……依此类推。如果五张都能找到,检查这五个点数中牌的张数恰好为4的有几个。 若多于1个(如:22223455556),则不算作同花顺。若只有1个,则算作同花顺,同花顺个数+1,但是炸弹数-1 ,那五张牌称之为【整理好的同花顺】;若没有,则算作同花顺,同花顺个数+1。 考虑到可能出现两个完全一样的同花顺,上述5张牌检索的流程需要进行两遍。
最后,将炸弹数加上同花顺个数,得到最终结果
首先指定逢人配的点数,随后检索玩家一手中的逢人配的位置与个数。 将逢人配依次视作各张牌面的牌 ,再统计其炸弹数,选择最大值作为最终结果。
有两张逢人配时,同理。
重复上述操作相当大次数,计算出平均值,作为玩家一手中拿到最多炸弹个数的数学期望的估计值,并打印结果。
另外,也可单独统计同花顺的期望
当不算逢人配时,统计纯数字炸弹的期望,约为1.365
与贴吧大神的纯概率计算较为接近
炸弹不多是常事,且用且珍惜啊XD
‘叁’ c语言关于创建扑克牌的各种函数!!
LZ的compare函数第一个if (c1->value != c2->value)应该是if (c1->value == c2->value)吧,其他没问题。
其他函数:
makestandarddeck函数负责创建一副完整52张牌,我理解应该是创建一副洗好的顺序不规则的牌吧。我想到的思路大概有两种,最快的思路是每产生一张新牌,分配不重复的一种花色;另一种更容易的思路是先老实按点数和花色的顺序依次产生52张排好顺序的牌,之后洗牌。分别给出代码。
#include<stdlib.h>
card*makestandarddeck()//solution1
{
intgen[52]={0};
card*cards=malloc(52*sizeof(card));
inti,k,d;
srand(time(NULL));
for(i=0;i<52;i++)
{
k=rand()%52;
d=k%2?1:-1;
while(gen[k]==0)
{
k+=d;
}
gen[k]=1;
cards[i].suit=k%4;
cards[i].value=k/4+1;
}
returncards;
}
card*makestandarddeck()//solution2
{
inti;
card*cards=malloc(52*sizeof(card));
for(i=0;i<52;i++)
{
cards[i].suit=i%4;
cards[i].value=i/4+1;
}
shufflecards(cards);//洗牌
returncards;
}
find_index函数负责找牌,因为牌可能是乱序的,只能老实的遍历查找。
intfind_index(deck*d,intsuit,intvalue)
{
inti,n=d->num_cards;
card*cards=d->cards;
for(i=0;i<n;i++)
{
if(cards[i].value==value&&cards[i].suit==suit)
returni;
}
return-1;
}
‘肆’ C语言,写程序实现一堆扑克牌的排序。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void sort(int *p)
{int i,j,t,t1;
for(i=0;i<12;i++)
{
for(j=0;j<12-i;j++)
if(*(p+j)>*(p+j+1))
{t=*(p+j);
*(p+j)=*(p+j+1);
*(p+j+1)=t;
}
}
for(i=0;i<12;i++)
if(*(p+i)%13==0)
{
t=*(p+i);
t1=*(p+i)/13;
for(j=i;j<=12&&*(p+j)/13==t1;j++)
*(p+j-1)=*(p+j);
*(p+j-1)=t;
i=j-1;
}
}
int main()
{int a[52],i,j,t;
srand(time(0));
for(i=0;i<52;i++)a[i]=i;
for(i=51;i>1;i--) //洗牌、发牌(0~12为第一人,13~25为第二人。。。)
{j=rand()%(i+1);
t=a[i];a[i]=a[j];a[j]=t;
}
for(i=0;i<4;i++)//排序
sort(&a[i*13]);
for(i=0;i<52;i++)
{
switch(a[i]%13)//不同点数按不同输出
{
case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:
case 9: printf("%c%-2d ",3+a[i]/13,a[i]%13+1); break;
case 10: printf("%c%J ",3+a[i]/13); break;
case 11: printf("%c%Q ",3+a[i]/13); break;
case 12: printf("%c%K ",3+a[i]/13); break;
case 0: printf("%c%A ",3+a[i]/13);
}
if(i%13==12)printf(" ");
}
return 0;
}
‘伍’ C语言栈区、堆区的使用,typedef和sizeof的使用
1、栈区的使用
栈区写入内存的的顺序是先进后出。
存放的是函数的参数、返回值、局部变量
由编译器管理数据开辟和释放
变量的生命周期在该函数结束后自动释放
不要返回局部变量的值,因为局部变量在函数执行之后就释放掉了,无法读取原来的内存
2、堆区的使用
堆区的空间远远大于栈区
它没有先进后出的数据结构
由程序员手动开辟和释放,malloc、calloc开辟free释放
注意:
如果主调函数中没有给指针分配内存,那么被调函数中需要利用高级指针给主调函数中的指针分配内存
3.数据区放的是静态变量、全局变量以及常量
static静态变量: 编译阶段分配内存,只能在当前文件内使用,只初始化一次
ertern全局变量:C语言下默认的全局变量前都默认隐藏了该关键字
4.const修饰的变量
直接修改const修饰的全局变量:失败
简介修改const修饰的全局变量:失败,原因是放在常量区,受到保护
直接修改const修饰的局部变量:失败
直接修改const修饰的局部变量:成功,该局部变量其实放到了栈区,是伪常量
5.字符串常量
不同编译器的处理方式有所区别
ANSI并未指定它的修改方式
有些编译器可以修改字符串常量,但有些不可以,某些编译器将相同的字符串常量看做同一个字符串常量
6.void的使用方式
无类型,不可以创建变量,无法分配内存
限定函数返回值
限定函数参数列表
void*是万能指针,不需要强制转化就可以给其他指针赋值
7.sizeof的使用
sizeof的本质其实是一个运算符,类似于+-*/
当统计某类型占的空间时需要加()
当统计mou变量占的空间时无需加()
返回值的类型是无符号整形,即unsigned int
数组名称如果作为函数参数,会退化为指针,指向数组首元素
8.typedef的使用
它可以给类型起别名
简化struct关键字
区分数据类型
提高代码的可移植性
‘陆’ 如何用c语言编写纸牌发牌程序
发牌原程序见我的空间(http://hi..com/crazycola/blog/item/52402bd4b3f68705a08bb746.html),可选是否包含大小王,可选发牌列数。
以下为改过的版本,不包含大小王(即总数52张),只能发4堆。
另外附加了用户菜单,原程序中不含菜单部分。
代码如下:
---------------------------------------
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
int menu()
{
int choice;
printf("1 发牌/0 退出:");
scanf("%d",&choice);
return choice;
}
void main( void )
{
int i1, j, total;
int *iArr;
int tag = 0;
char* pok_C[] = { "黑桃", "红桃", "梅花", "方块" };
char* pok_N[] = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };
if(!menu()) exit(0);
total = 52;
srand( (unsigned)time( NULL ) );
iArr = (int*)malloc(total*sizeof(int));
for( i1=0; i1<total; i1++ )
{
iArr[i1]=rand()%total;
if( i1==0 ) continue;
do {
tag = 0;
for( j=0; j<i1; j++ )
if( iArr[j] == iArr[i1] )
{
iArr[i1]=rand()%total;
tag = 1;
}
} while( tag==1 );
}
for( i1=0; i1<total; i1++ )
{
printf("%s%s\t",pok_C[iArr[i1]%4],pok_N[iArr[i1]%13]);
if(i1%4==3) printf("\n");
}
free(iArr);
}
‘柒’ c语言堆和栈的区别
内存分配中的堆和栈
在 C 语言中,内存分配方式不外乎有如下三种形式:
从静态存储区域分配:它是由编译器自动分配和释放的,即内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在,直到整个程序运行结束时才被释放,如全局变量与 static 变量。
在栈上分配:它同样也是由编译器自动分配和释放的,即在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元将被自动释放。需要注意的是,栈内存分配运算内置于处理器的指令集中,它的运行效率一般很高,但是分配的内存容量有限。
从堆上分配:也被称为动态内存分配,它是由程序员手动完成申请和释放的。即程序在运行的时候由程序员使用内存分配函数(如 malloc 函数)来申请任意多少的内存,使用完之后再由程序员自己负责使用内存释放函数(如 free 函数)来释放内存。也就是说,动态内存的整个生存期是由程序员自己决定的,使用非常灵活。需要注意的是,如果在堆上分配了内存空间,就必须及时释放它,否则将会导致运行的程序出现内存泄漏等错误。
数据结构的堆和栈
在数据结构中,栈是一种可以实现“先进后出”(或者称为“后进先出”)的存储结构。假设给定栈 S=(a0,a1,…,an-1),则称 a0为栈底,an-1为栈顶。进栈则按照 a0,a1,…,an-1的顺序进行进栈;而出栈的顺序则需要反过来,按照“后存放的先取,先存放的后取”的原则进行,则 an-1先退出栈,然后 an-2才能够退出,最后再退出 a0。
在实际编程中,可以通过两种方式来实现:使用数组的形式来实现栈,这种栈也称为静态栈;使用链表的形式来实现栈,这种栈也称为动态栈。
相对于栈的“先进后出”特性,堆则是一种经过排序的树形数据结构,常用来实现优先队列等。假设有一个集合 K={k0,k1,…,kn-1},把它的所有元素按完全二叉树的顺序存放在一个数组中,并且满足:
则称这个集合 K 为最小堆(或者最大堆)。
由此可见,堆是一种特殊的完全二叉树。其中,节点是从左到右填满的,并且最后一层的树叶都在最左边(即如果一个节点没有左儿子,那么它一定没有右儿子);每个节点的值都小于(或者都大于)其子节点的值。