zoukankan      html  css  js  c++  java
  • 算法:扑克牌相关的一个简单功能示意(纯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年以前的编辑器编译器就把最后个打印函数改改吧,也能跑

    认真写好每份代码,认真权衡每种模式应用范围和场景,认真理解工具和库的优劣,认真做自己。
  • 相关阅读:
    第二章Maven安装与配置
    第一章 Maven简介
    什么是Maven?
    jbpm与OA项目-oa概念
    Hadoop学习常用的Linux命令
    包名命名规则
    判断网络类型
    webview的设置
    AlertDialog的实现
    SharedPreferences保存用户偏好参数
  • 原文地址:https://www.cnblogs.com/kevindobest/p/3395990.html
Copyright © 2011-2022 走看看