算法:扑克牌相关的一个简单功能示意(纯C实现)

中午逛博园的时候看到这个题目,兴致盎然,稍微实现了一下

题目以及原文地址:C++算法编程题(一)扑克牌发牌

题目要求:

程序描述:

  一副纸牌有52张,4种花色,每种花色13张。我们能用一个整数m就表示出所有的52种情况,规则是:

    m / 13: =0: 红心,=1: 方块,=2: 梅花,=3: 黑桃

    m % 13:  =0:2,=1:3,=2:4 ....  =8:10,=9:J,=10:Q,=11: K,=12:A

  比如:m = 15 就表示:方块4  m=38表示:梅花A

  我们希望用程序模拟1副扑克牌随机抽取13张,发给某人的过程。

  发牌后需要排序:规则是:先按花色,再按点数。花色的大小顺序是:梅花、方块、红心、黑桃。点数的顺序是:2、3、4、…. 10、J、Q、K、A。

  然后,挑选出最大的连续牌型。规则是:连续张数多的大。张数相等的则花色大的大(此时与点数无关)。

直接上代码吧

  1 // -*- encoding: utf-8 -*-
  2 
  3 /**
  4  * Copyright 博客园-本文作者. All Rights Reserved.
  5  * Author: kevin
  6  * since: 2013-11-29 
  7  */
  8 #include<stdio.h>
  9 #include<stdlib.h>
 10 #include<stdbool.h>
 11 
 12 #define POKER_NUM 52
 13 #define EACH_SUIT_NUM 13
 14 #define CARDS_NUM 13
 15 
 16 int main(int argc, char *argv[]){
 17     void printCards(int [], int);
 18     void initCards(int [], int);
 19     int cmp(const void *, const void *);
 20     int find(int [], int, int []);
 21 
 22     // 1. 发牌
 23     int cards[CARDS_NUM];
 24     initCards(cards, CARDS_NUM);
 25     printf("发牌: ");
 26     printCards(cards, CARDS_NUM);
 27 
 28     // 2. 排序
 29     qsort(cards, CARDS_NUM, sizeof(int), cmp);
 30     printf("排序: ");
 31     printCards(cards, CARDS_NUM);
 32 
 33     // 3. 挑出最大牌型
 34     int result[CARDS_NUM];
 35     int num = find(cards, CARDS_NUM, result);
 36     printf("结果: ");
 37     printCards(result, num);
 38 
 39     return 0;
 40 }
 41 
 42 
 43 /* 
 44  * 随机挑出num张牌
 45  * 如果只是从52张不同牌里先后挑出13张牌,
 46  * 本函数的do-while的重复使用几率低于19.5%
 47  */
 48 void initCards(int cards[], int num){
 49     srand(time(NULL));
 50 
 51     bool existed = false;
 52     int chosen;
 53     int i;
 54     for(i=0; i < num; i++){
 55         do{
 56             existed = false;
 57             chosen = rand() % POKER_NUM;
 58 
 59             int j;
 60             for(j = 0; j < i; j++){
 61                 if(cards[j] == chosen){
 62                     existed = true;
 63                     break;
 64                 }
 65             }
 66         }while(existed);
 67         cards[i] = chosen;
 68     }
 69 }
 70 
 71 
 72 /**
 73  * 按照规则(题目设定有点怪)
 74  * 编号规则: 0-红心 1-方块 2-梅花 3-黑桃
 75  * 排序规则: 梅花 > 方块 > 红心 > 黑桃
 76  * 此处排完后,不管花色还是点数都是从小到大
 77  *
 78  * * 如果题设排序有变化,修改下本函数就可以了
 79  */
 80 int cmp(const void * a, const void * b){
 81     int aa = *(int *)a, bb= *(int *)b;
 82     int aSuit = suit(aa), bSuit = suit(bb);
 83     int aValue = value(aa), bValue = value(bb);
 84     if(aSuit == 3){
 85         if(bSuit == 3)
 86             return intcmp(aValue, bValue);
 87         else
 88             return -1;
 89     }else{
 90         if(bSuit == 3)
 91             return 1;
 92         else{
 93             int t = intcmp(aSuit, bSuit);
 94             if(t != 0)
 95                 return t;
 96             else
 97                 return intcmp(aValue, bValue);
 98         }
 99     }
100 }
101 
102 /**
103  * 注意: 
104  * 1. 参数result初始长度必须大于或等于返回结果
105  * 2. 参数cards内的值必须是排好序的
106  */
107 int find(int cards[], int len, int result[]){
108     int magic[EACH_SUIT_NUM] = {0};  //存储每个起点后的跟随个数
109     int max = magic[0];   //记录每个串的跟随长度(串存在的话)
110     int pos = 0;      //记录最长串的起始位置
111 
112     int i = 0;
113     while(i < len){
114         int x = i;  //保存下起始位置
115         while(next(cards[i]) == cards[++i]){
116             magic[x] += 1;
117         }
118         if(max < magic[x]){
119             max = magic[x];
120             pos = x;
121         }
122     } // 本问题的核心部分应该是在这个嵌套循环里,结果在magic数组里
123 
124     // 将最长串复制到结果数组里
125     for(i = 0; i < max + 1; i++){
126         result[i] = cards[pos++];
127     }
128     return max+1;
129 }
130 
131 // 本张牌的下一张,-1表示下一张牌没有
132 int next(int m){
133     if(value(m) >= EACH_SUIT_NUM - 1)
134         return -1;
135     else
136         return m + 1;
137 }
138 
139 // 比较整型大小
140 inline int intcmp(int a, int b){
141     if(a < b) return -1;
142     else if(a > b) return 1;
143     else return 0;
144 }
145 
146 // 花色:0-红心 1-方块 2-梅花 3-黑桃
147 inline int suit(int a){
148     return a / EACH_SUIT_NUM;
149 }
150 
151 // 计算同花色内的序号值
152 inline int value(int a){
153     return a % EACH_SUIT_NUM;
154 }
155 
156 /**
157  * 打印输出函数,此处输出形式与其它部分无关,可自行定义
158  * 此处每个中文按3个char算,英文按1个char算
159  */
160 const char values[][3]= {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};
161 const char suits[][7] = {"红心", "方块", "梅花", "黑桃"};
162 void printCards(int cards[], int len){
163     int s, v;
164     int i;
165     for(i = 0; i < len; i++){
166         s = suit(cards[i]);
167         v = value(cards[i]);
168         printf("%s%s  ", suits[s], values[v]);   
169     }
170     printf("
");
171 }
172 
173 //END
View Code

* 非windows系统下完美运行,win系统下推荐使用MinGW编译器; 2000年以前的编辑器编译器就把最后个打印函数改改吧,也能跑

认真写好每份代码,认真权衡每种模式应用范围和场景,认真理解工具和库的优劣,认真做自己。
原文地址:https://www.cnblogs.com/kevindobest/p/3395990.html