扑克牌发牌程序设计

本程序实现了一般扑克牌游戏的洗牌、发牌和理牌过程,程序模拟了对四个玩家的发牌,且能让各自玩家按大小顺序整理自己的手牌。牌的大小顺序按斗地主的规则(但无大小王)。
   本程序定义了一个牌的结构体,其成员变量是两个字符指针。一个指向点数的字符数组,另一个指向花色的字符数组。考虑到牌的整理需要比较两张牌的大小,而字符不太好比较,从而构造了一个辅助函数Value来实现将字符转换为整数。程序得最后还对桌牌和手牌进行了检测,看是否有重复的牌。

算法说明:

发牌算法

Void Deal(CARD *Deck,CARD (*player)[13]){

     for (i = 0;i < 4; i++){

        // 遍历四个玩家

for (j = 0;j < 13; j++){

// 洗牌第i个玩家的第j张牌是手牌中的第4*j+i张(轮流发牌)

   player[i][j] = Deck[4*j+i];

    }

}

}

   排序算法

void InsertSort ( CARD *R) { // 对某一玩家R作直接插入排序,有13张牌
   for ( i=1; i<n; ++i ) {
  temp = R[i]; // 复制为监视哨
  for ( j=i-1; j>=0; --j )

if(Value(R[j].face)<Value(temp.face))break;//如果R[j]的牌比temp的小则调出循环,找到比temp小的牌          else if (Value(R[j].face) == Value(temp.face)  // 若face 相同 则比较suit

? Value(R[j].suit) < Value(temp.suit) ? 1 : 0 : 0) break;

for (k = j-1; k > j;k--)
       R[j+1] = R[j]; // 记录后移
        R[k+1] = temp; // 插入到正确位置
  }
  } // InsertSort

         测试算法

测试桌牌和手牌是否有重复的牌。其思想是从第一张开始与后面的牌一次比较,直到找到一张与待比较的牌相同的或者倒数第二张与最后一张牌比较后终止。

算法描述:

       For(I = 0; I < 13; I++ ){

           Temp = R[I]; // 将待检测的牌放入temp中

           If( Locat(Temp,R)){

            Print :ERROR! 

break; // 如果Temp在R[I+1…13]中则返回1 

}

// 若没有重复的牌不提示任何信息
         变量说明:

一. 张牌(Card)都用一个 strcut card 结构体类型来表示具体定义如下 struct card{

char *face;  // 指针 face 指向不同纸牌的点数

    char *suit;  // 指针 suit 指向不同纸牌的花色

} CARD;


再定义两个字符数组分别存储牌的点数和花色:

char *face[] = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K","A", "2"};
char *suit[] = {"/004", "/005", "/003", "/006"};
定义两个CARD型数组 deck[52],player[4][13],deck用与存储桌牌,player用于存储玩家手牌。

Code:
  1. // 扑克牌发牌游戏 -- 第一次上机作业  
  2. /* 整个程序由三部分组成 
  3.    1.扑克牌初始化 
  4.    2.洗牌 
  5.    3.发牌 
  6.    4.玩家各自将手牌排序(按黑红紫坊从小到大的排序,2点最大) 
  7.    */  
  8.   
  9. #include <stdio.h>  
  10. #include <stdlib.h>  
  11. #include <time.h>  
  12. #include <iostream>  
  13.   
  14. typedef struct card{  
  15.     // 每张牌(Card)都用一个 strcut card 结构体类型来表示  
  16.     char *face;  // 指针 face 指向不同纸牌的点数  
  17.     char *suit;  // 指针 suit 指向不同纸牌的花色  
  18. } CARD;   
  19. CARD deck[52], player[4][13];    
  20.      char *face[] = {"3""4""5""6""8""8""9""10""J""Q""K","A""2"};  
  21.      char *suit[] = {"/004""/005""/003""/006"};  
  22.  // 比较时用的牌值  
  23.   
  24. void InitDeck (CARD * , char *[] , char *[]);  
  25. void Shuffle (CARD *);  
  26. void Deal (CARD * , CARD (*)[13]);  
  27. void Sort (CARD (*)[13]);  
  28. int  Value (char *);  
  29. void Disply(void );  
  30. int Locat(CARD *, int , CARD , int (*)(CARD, CARD));  
  31. int Equl(CARD, CARD);  
  32. void Testcard(CARD *, CARD (*)[13]);  
  33.   
  34. int main(){  
  35.   
  36.     srand(time(NULL));    
  37.     InitDeck (deck, face, suit);  // 填新牌  
  38.     Shuffle (deck);  // 洗牌  
  39.     Deal (deck, player); // 发牌  
  40.     Sort (player);  // 对玩家的手牌进行排序  
  41.     Disply();  
  42.     Testcard(deck, player);  
  43.   
  44.     return 0;  
  45. }  
  46.   
  47. void InitDeck (CARD *pDeck, char *pface[], char *psuit[]){  
  48.     /* wDeck 结构体指针,指向待初始化桌牌 deck[52] 
  49.        wface 字符数组指针,指向点数 
  50.        wsuit 字符数组指针,指向花色 
  51.        该函数用于初始化桌牌 deck[52] 
  52.        */  
  53.     int i;  
  54.   
  55.     for (i = 0; i <= 51; i++){  
  56.         pDeck[i].face = pface[i%13];  // 点数初始化  
  57.         pDeck[i].suit = psuit[i/13];  // 花色初始化  
  58.     }  
  59. }  
  60.   
  61. void Shuffle (CARD *pDeck){  
  62.     // 用产生的随机数 j 依次与前面的牌交换  
  63.     int i, j;  
  64.     CARD temp;  
  65.   
  66.     for (i = 0; i <= 51; i++){  
  67.         // 洗牌  
  68.         j = rand()%52;  // 产生0到51之间的随机数  
  69.         temp = pDeck[i];  // 交换纸牌  
  70.         pDeck[i] = pDeck[j];  
  71.         pDeck[j] = temp;  
  72.     }  
  73. }  
  74.   
  75. void Deal (CARD *pDeck , CARD (*pplayer)[13]) {  
  76.     int i, j;  // i为玩家编号,j为手牌编号   
  77.   
  78.     for (i = 0;i < 4; i++){  
  79.         // 遍历四个玩家  
  80.         for (j = 0;j < 13; j++){  
  81.         // 洗牌第i个玩家的第j张牌是手牌中的第4*j+i张(轮流发牌)  
  82.         pplayer[i][j] = pDeck[4*j+i];  
  83.         }  
  84.     }  
  85. }  
  86.   
  87. void Sort (CARD (*pplayer)[13]){  
  88.     // 运用插入排序法分别对四个玩家的手牌排序  
  89.     int i, j, p, q;  // i为玩家编号,j为手牌编号,p, q 为工作指针  
  90.     CARD temp;  
  91.   
  92.     for (i = 0;i < 4; i++){  
  93.         // 外层循环,对四个玩家遍历  
  94.         for (j = 1;j < 13; j++){  
  95.             // 内层循环,开始排序  
  96.             // 先比较face 再比较suit  
  97.             temp = pplayer[i][j];  // 待插入的牌  
  98.             for (p = j-1; p >= 0; p--){  
  99.                 // 从后往前找出第一个小于temp的牌的序号  
  100.             if (Value(pplayer[i][p].face) < Value(temp.face))  // 找到比temp小的牌  
  101.                    break;  
  102.             else if (Value(pplayer[i][p].face) == Value(temp.face)  // 若face 相同 则比较suit  
  103.                 ? Value(pplayer[i][p].suit) < Value(temp.suit) ? 1 : 0 : 0) break;  
  104.             }  
  105.             for (q = j-1; q > p; q--){  // 插入操作  
  106.                 pplayer[i][q+1] = pplayer[i][q];  
  107.             }  
  108.             pplayer[i][q+1] = temp;  
  109.         }  
  110.     }  
  111. }  
  112.   
  113. int Value(char *str){  
  114.     // 字符映射函数  
  115.     int i = 0;  
  116.       
  117.     while(i < 4 && *str - *suit[i++]) ;  
  118.     if (i == 4) {  
  119.     i = 0;  
  120.     while(i < 13 && *str - *face[i++]) ;  
  121.     }  
  122.     return i;  
  123. }  
  124.   
  125. void Disply(){  
  126.     using namespace std;  
  127.     int i, j;  
  128.       
  129.     cout << "player1" << "player2" << "player3" << "player4" << endl;  
  130.     for (j = 0; j < 13; j++){  
  131.         // j为第 j 行  
  132.         for (i = 0; i < 4; i++){  
  133.             // i为第 i 位玩家  
  134.             cout << player[i][j].suit << player[i][j].face << "/t";  
  135.             if (i == 3) cout << endl;  
  136.         }  
  137.     }  
  138. }  
  139.   
  140. void Testcard(CARD *pdeck, CARD (*pplayer)[13]){  
  141.     using namespace std;  
  142.     int i, j;  
  143.     CARD temp;  
  144.    
  145.     for (i = 0; i < 51; i++){  
  146.         temp = pdeck[i];  
  147.         if (Locat(&deck[i+1],52,temp,Equl)){  
  148.             cout << "error! the deckcard are same"<< endl;  
  149.             break;  
  150.         }  
  151.     }  // 测试桌牌是否重复  
  152.     for (i = 0; i < 4; i++){  
  153.         for (j = 0; j < 13; j++){  
  154.             temp = pplayer[i][j];  
  155.             if(Locat(&pplayer[i][j+1],13,temp,Equl)){  
  156.                 cout << "error! the player's card are same" << endl;  
  157.                 break;  
  158.             }  
  159.         }  // 测试手牌是否重复  
  160.     }  
  161. }  
  162.   
  163. int Locat(CARD *pdecks, int len, CARD deck, int (*compare)(CARD , CARD )){  
  164.     // 若牌堆中有满足 compare() 的牌则返回1,没有则返回0  
  165.     // len牌堆的长度 有13和52  
  166.     CARD *p;  
  167.     int i = 0;  // 第一张牌  
  168.     p = pdecks;  // 第一张牌的地址  
  169.   
  170.     while (i < len && compare(*p++ , deck))   
  171.         ++i;  
  172.     if(i == len)  
  173.         return 0;  
  174.     else  
  175.         return 1;  
  176. }  
  177.   
  178. int Equl(CARD card1, CARD card2){  
  179.     // 比较card1 和 card2 是否相同,相同则返回0  
  180.     // 不同返回1  
  181.     int fval, sval;  
  182.     // fval 为点数字符差,sval 为花色字符差  
  183.   
  184.     fval = *card1.face - *card2.face;  
  185.     sval = *card1.suit - *card2.suit;  
  186.     if(fval || sval)  
  187.         return 1;  // 有一个不同就不相同  
  188.     else   
  189.         return 0;  
  190. }  


 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值