一个有趣的基于C++的模拟发牌程序

在内存中模拟出一副牌,然后模拟洗牌,发牌等动作。

流程是这样的:构建一副牌保存到一个数组中—洗牌—创建玩家—向玩家发牌–输出每个玩家的牌。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//定义扑克的花色
enum Suit{
    heart,
    spade,
    diamond,
    club,
    joker1,
    joker2
};
//一副牌的数量
#define CARD_COUNT 54
//定义扑克
typedef struct Card{
    int value;//牌的点数从1开始
    enum Suit suit;//花色
}Card;
//定义玩家
typedef struct Player{
    char name[64];//玩家的名字
    Card ** cards;//玩家分到的牌。每项是一个指针,指向原始一副牌数组中的一项,这样可以节省空间
    int cardsCount;//玩家分到的牌的数量
}Player;
//分牌完成后调用的函数的类型
typedef int (*COMPARE)(Card* ,Card*);
//函数声明们
char* getCardName(const Card*);
Card** shuffle(const Card*);
void dispatchCards(Player** ,int ,const Card** );
void sort(Card**,int,COMPARE);
int compare1(Card* ,Card*);
int compare2(Card* ,Card*);
void initOnePack();
//原始一副牌所在的数组
Card pokers[CARD_COUNT];
//入口函数
int main(void)
{
    //初始化一副牌
    initOnePack();

        //洗牌,shuffledPokers保存洗后的牌们
    Card** shuffledPokers = shuffle(pokers);
        //构建三个玩家
    Player player1;
    strcpy(player1.name,"隔壁老王");
    player1.cards=NULL;
    player1.cardsCount=0;
    Player player2;
    strcpy(player2.name,"小明");
    player2.cards=NULL;
    player2.cardsCount=0;
    Player player3;
    strcpy(player3.name,"田中龟孙");
    player3.cards=NULL;
    player3.cardsCount=0;
    //把三放到一个数组中,以传入发牌函数中
    Player* players[]={&player1,&player2,&player3};
        //发牌
    dispatchCards(players,sizeof(players)/sizeof(Player*),shuffledPokers);
        //洗后的牌用完了,释放之
    free(shuffledPokers);
    int i;
        //打印出每个玩家手中的牌
    for(i=0;i<sizeof(players)/sizeof(Player*);i++){
                //先打印玩家的名字
        printf("%s\n",players[i]->name);
                //需要对玩家手中的牌排序
        sort(players[i]->cards,players[i]->cardsCount,compare1);
                //打印玩家手中所有的牌
        int j;
        for(j=0;j<players[i]->cardsCount;j++){
            char * name = getCardName(players[i]->cards[j]);
            printf("%s ",name);
            free(name);
        }
        //每个玩家都需要换一次行
        printf("\n");
    }
        //释放玩家手中牌的数组
    for(i=0;i<sizeof(players)/sizeof(Player*);i++){
        free(players[i]->cards);
    }
    return 0;
}
//构造一副牌
void initOnePack(){
    int i=0;
    //前52张
    for(;i<CARD_COUNT-2;i++){
        pokers[i].value=i/4+1;
        pokers[i].suit = i%4;
    }
    //剩下的两张:大王和小王
    //joker1
    pokers[i].value=i/4+1;
    pokers[i].suit=joker1;
    //joker2
    pokers[i+1].value=i/4+2;
    pokers[i+1].suit=joker2;
}
//洗牌,参数是原始的一副牌,返回洗完后的牌
Card** shuffle(const Card* pokers){
    int i;
        //分牌返回牌数组的内存空间
    Card** retPokers = malloc(CARD_COUNT*sizeof(Card*));
    //为了不改动原始的一副牌,另建一个数组,保存原始牌的指针(注意每项不是牌,而是牌的指针)
    Card** pokers2 = malloc(CARD_COUNT*sizeof(Card*));
    for(i=0;i<CARD_COUNT;i++){
        pokers2[i] = &pokers[i];
    }
        //种下随机种子。种子取的是当前时间,
        //所以保证了每次运行程序时,产生的随机数序列不同
    srand(time(NULL));
        //取得随机序号,从pokers2取出序号所指的项,把它依次加到retPokers中。
    for(i=0;i<CARD_COUNT;i++){
        unsigned int index = rand()%CARD_COUNT;
        if(pokers2[index] != NULL){
            retPokers[i] = pokers2[index];
            pokers2[index]=NULL;
        }else{
            i--;
        }
    }
    free(pokers2);

        //返回洗完后的数组
    return retPokers;
}
//发牌
//players是玩家数组
//playerCount是玩家数量
//shuffledCards是洗完后的一副牌
void dispatchCards(Player** players,int playerCount,const Card** shuffledCards){
    //计算每个玩家手中牌的数组的容量,如果每个玩家手中的牌不一样,
    //最多就差一张,加1是为了保证数组分配的空间足够容纳分到的牌。
    int numberCards = CARD_COUNT/playerCount+1;
    //为每个玩家的牌数组分配空间
    int i;
    for(i=0;i<playerCount;i++){
        Card* cards = malloc(numberCards*sizeof(Card*));
        players[i]->cards = cards;
    }
    //轮流向每个玩家发牌
    for(i=0;i<CARD_COUNT;i++){
        //取当前玩家
        Player *curPlayer = players[i%playerCount];
        //向玩家发牌
        curPlayer->cards[curPlayer->cardsCount] = shuffledCards[i];
        //玩家手中实际的牌数增加
        curPlayer->cardsCount++;
    }
}
//排序函数
//cards是要排序的牌,每一项是牌的指针
//cardsCount是牌的数量
//compare_func是比较函数
void sort(Card** cards,int cardsCount,COMPARE compare_func){
    int i;
    for(i=0;i<cardsCount-1;i++){
        int j;
        for(j=0;j<cardsCount-i-1;j++){
                if(compare_func(cards[j],cards[j+1])){
                    int tmp=cards[j];
                    cards[j]=cards[j+1];
                    cards[j+1]=tmp;
                }
        }
    }
}
//比较函数,先比较点数再比较花色
int compare1(Card* a,Card* b){
    if(a->value > b->value){
        return 1;
    }else if(a->value < b->value){
        return 0;
    }else{
        if(a->suit > b->suit)
            return 1;
        else
            return 0;
    }
}
//比较函数,先比较点数再比较花色
int compare2(Card* a,Card* b){
    if(a->value > b->value){
        return 0;
    }else if(a->value < b->value){
        return 1;
    }else{
        if(a->suit > b->suit)
            return 0;
        else
            return 1;
    }
}
//获取牌的名字
//返回牌的名字字符串,调用者用完后需要free()之。
char* getCardName(const Card* card){
    //存放花色名字
    char suitStr[16]={0};//0==‘\0‘
    switch (card->suit) {
    case heart:
        strcpy(suitStr,"红桃");
        break;
    case spade:
        strcpy(suitStr,"黑桃");
        break;
    case diamond:
        strcpy(suitStr,"方块");
        break;
    case club:
        strcpy(suitStr,"梅花");
        break;
    }
    //存放点数名字
    char valueStr[16];
    switch(card->value){
    case 1:
        strcpy(valueStr,"A");
        break;
    case 11:
        strcpy(valueStr,"J");
        break;
    case 12:
        strcpy(valueStr,"Q");
        break;
    case 13:
        strcpy(valueStr,"K");
        break;
    case 14:
        strcpy(valueStr,"小王");
        break;
    case 15:
        strcpy(valueStr,"大王");
        break;
    default:
        sprintf(valueStr,"%d",card->value);
        break;
    }
    //动态分配足够的空间
    char * ret = malloc(16);
    //将两个名字合并到ret中
    sprintf(ret,"%s%s",suitStr,valueStr);
    return ret;
}
时间: 2024-11-08 20:23:56

一个有趣的基于C++的模拟发牌程序的相关文章

基于UDP协议模拟的一个TCP协议传输系统

TCP协议以可靠性出名,这其中包括三次握手建立连接,流控制和拥塞控制等技术. 我写的这个系统基于UDP协议模拟了一个TCP协议,所实现的功能如下: 1.三次握手 2.一个计时器,用来判断传输超时行为 3.快速重传 4.能处理不同的MSS(maximum segment size) 5.没有被接收方确认收到的包会被存在发送方,最大可以存MWS个(Maximum Window size) 6.能处理包丢失的情况 7.接收方一旦收到包,立刻发送确认信息给发送方 8.接收方的超时时间是固定的 9.接收方

一个有趣的模拟光照的shader

一个有趣的模拟光照的shader(类似法线贴图) http://www.cnblogs.com/flytrace/p/3395911.html -----  可否用于需UI中需要加灯的模型.

基于利用Jquery模拟Extjs的Panel界面的开发

JQuery 是一个强大js 选择器的开源框架脚本,有了他,本来要写20多行的js脚本,现在只需要10行就能完成,可惜的是,在界面方面,他虽然有Jquery-ui, 但他并没有建立一整套开源成熟的组件,如果他像Extjs/sencha那么成熟的套件,相信会更多人爱他.而像extjs的juqery成熟的开发库 miniUI 却要收费. 所以我尝试,仿照Extjs,模拟重写像Extjs的一套Panel窗口 ,但代码量足足比Extjs/sencha少了50%. 下载连接: https://github

关于java除法的一个有趣例子。

今天逛贴吧的时候偶然发现吧友的一个有趣例子. public class Demo{     public static void main(String[]args){         System.out.println(24/0);  //会抛byzero异常         System.out.println(24.0/0.0) //可以输出,输出为Infinity:     } } 目前对于第二句为什么不会报byzero异常也不知道.先做个标记.理解了再补充上.

一个有趣的SQL Server 层级汇总数据问题

看SQL Server大V宋大侠的博客文章,发现了一个有趣的sql server层级汇总数据问题. 具体的问题如下: parent_id emp_id emp_name total_amout     NULL 2 Andrew 200     2 1 Nancy 100     2 3 Janet 120     3 4 Michael 80     1 5 Robert 50     每个员工的总销售额=自己的销售额+其下级员工的总销售额,     比如:     Andrew = 200_

一个有趣的Timer应用

import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class TraditionalTimerTest { static int count; public static void main(String[] args) { class MyTimerTask extends TimerTask { @Override public void run() { count = (cou

一个有趣的现象(苹果的bug Or 坑?),关于区分真机和模拟器的预编译宏

TARGET_IPHONE_SIMULATOR和TARGET_OS_IPHONE 是苹果的两个宏定义, 在真机sdk中位于ios->usr/include/targetconditionals.h中, 在模拟器sdk中位于simulator->usr/include/targetconditionals.h中 (笔者此时使用的xcode版本为5.1,sdk版本是7.1) 仔细看其模拟器sdk中的定义: #define TARGET_OS_IPHONE            1 #define

妞一个斗地主发牌程序!!!

学习java三个星期,利用所学的知识做了一个三人斗地主发牌程序,闲话少叙,上代码 1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.List; 4 5 /** 6 * 三人斗地主程序 功能:将一副牌随机分发给地主(20张牌),农民A(17张牌),农民B (17张牌) 7 * 步骤:1.洗牌阶段:将54张牌储存到ArraryList 容器中(批量储存,for循环) 8 * 2.发牌阶段:

Nim Game,一个有趣的游戏,也是一道入门算法题。

Nim Game,其实很多人都玩过.其实就是我们玩的划线游戏. 一张纸上,画若干条线,双方一人划一次,每次划掉1~3条线.可以选择画1条,也可以划2条,也可以3条.具体划去几条线完全看自己的策略.谁划掉最后一条线,就是赢家. 如上图,蓝方获胜. 正在看这篇文章的你一定是一个聪明人,每一步都是最优解,而你的对手,也跟你一样聪明,每步都是最优的解法. 现在你作为先手,在线条总数为多少的时候,你必赢呢,又在多少的时候必输呢? 可不可以用一个函数来判断在线条总是为x时你的输赢情况呢?这样你以后跟别人玩这