繁体   English   中英

使用qsort对数组进行排序

[英]using qsort to sort an array

这个程序应该对卡片进行分类,将它们分组并分成5组,称为手,显然,代码确实做到了这一点,但是由于某种原因,我不确定,我无法确定获胜者。 获胜者应该是成对显示的最高值。 如果第一手将王者作为最高对,而第三手将王者作为最高对,则应宣布第一手为赢家。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include <windows.h>


typedef unsigned char card;
typedef unsigned char pairs;

static char *suits[] = {"Hearts","Diamonds","Clubs","Spades"};
static char *values[]= {"Ace","Two","Three","Four","Five","Six",\
                    "Seven","Eight","Nine","Ten","Jack",\
                    "Queen","King"};
static char *colour[]= {"Black","Red"};

void printcard(card c); /* Displays the value of a card*/
void printdeck(card deck[52]); /* prints an entire deck of cards*/
void filldeck(card deck[52]); /* Populates a deck of cards */
void shuffle(card deck[52]); /* Randomizes the order of cards */
int compareface(const void* c1,const void *c2); 

 pairs findpairs(card *hand); /* finds any pairs in a hand */
 int findwinner(card *hand);


 int main()
 {

 card deck[52],*deckp,*temp3,max;
 card hands[5][5],handssorted[5][5];
 pairs numpairs[5],highest;
 int hand,cd,winner=0,temp2;
 char loop;

 { 
 printf("\n(__)(__)(__)(__) CARD GAME(__)(__)(__)(__)(__)\n\n");
 printf("\n(__)(__)(__)(__)(__)(__)(__)(__)(__)(__)(__)(__)\n\n");
 printf("\n\t ====== Before Shuffling =====\n\n");
 srand(time(NULL));  /* seed the random number generator */

  filldeck(deck);//printdeck(deck);
  printdeck(deck);
  printf("\n\t ========== Shuffled Cards ========\n\n");
  shuffle(deck);//printdeck(deck);
  printdeck(deck);

 int i=0;
 for(cd=0;cd<5;cd++)
 {
    for(hand=0;hand<5;hand++){
        hands[hand][cd]=deck[i];
        i++;
    }
  }

 printf("\n\t ============= Hands ===========\n\n");
for(hand=0;hand<5;hand++)
 { 
    qsort(hands[hand],5,sizeof(card),compareface);;

    int kok=0;

    printf("\tHand %i:\n",hand+1);

    for( cd=0;cd<5;cd++)
    {            
        printcard(hands[hand][cd]);
    }

    numpairs[hand]=findpairs(hands[hand]);
    printf("\n\tNumber of pairs:%i\n\n",numpairs[hand]);
    temp2=0;
    if(numpairs!=0)
        temp2=findwinner(hands[cd]);
 }
 pairs findpairs(card *hand)
{     int cd=0,dd=0;

  card temp;
  pairs numpairs=0;

  for (cd=0;cd<4;cd++)
  {
  if (values[(hand[cd]&0x3c)>>2] == values[(hand[cd+1]&0x3c)>>2])
  {
      dd++;
      temp=hand[cd];
  }

  switch (dd)
  {
         case 0:numpairs=0;
         break;
         case 1:numpairs=1;
         break;
         case 2:
              if ((values[(hand[1]&0x3c)>>2] !=values[(hand[3]&0x3c)>>2])&&
               (values [(hand[0]&0x3c)>>2]\
                   !=values[(hand[2]&0x3c)>>2])&&(values[(hand[2]&0x3c)>>2] !=values
                [(hand[4]&0x3c)>>2]))numpairs=2;

              else 
                   numpairs=1;   
                   break;
         case 3:numpairs=2;
         break;
         case 4:numpairs=2;
         break;
         }}
         printf("\tHighest pair is:");
         if (numpairs!=0)
         printf("\t%s",values[(temp&0x3c)>>2]);         
  return numpairs;
 }

int findwinner(card *hand){     
int cd=0,temp2=0,winner=0;
for (cd=0;cd<4;cd++)
  {
   if (values[(hand[cd]&0x3c)>>2] == values[(hand[cd+1]&0x3c)>>2])
  {
    // temp2=cd;
    winner=cd;
  }}

  return winner;
 }


void filldeck(card deck[52])
 {
 card suit,value;
 int i=0;

 for(suit=0;suit<4;suit++)
 {
     for(value=0;value<13;value++)
     {
         deck[i]=suit|(value<<2);                     
         if(suit<2)

           deck[i]|=0x40;  /*card is red, so do red stuff */                         
         i++;
     }
 }

return;
 }
void printdeck(card deck[52])
{
  int i;
  for(i=0;i<52;i++)
  printcard(deck[i]);
   return;
}

void printcard(card c)
{
  printf("\t%s\t of  %-8s  is  %s\n",values[(c&0x3c)>>2],suits[c&0x3],
  colour[(c&0x40)  >>6]);
  return;
}

void shuffle(card deck[52])
{
  int i,rnd;
  card c;
  for(i=0;i<52;i++)
 {
  rnd=rand() * 52.0 / RAND_MAX; 
  c=deck[rnd];
  deck[rnd]=deck[i];
  deck[i]=c;  
 } 
  return;
 }


int compareface(const void* c1, const void *c2)
  {

    card cd1,cd2;
    cd1=*((card*) c1);
    cd2=*((card*) c2);

    cd1= (cd1&0x3c)>>2;
    cd2= (cd2&0x3c)>>2;

    if(cd1>cd2)
        return 1;

    if(cd1==cd2)
        return 0;

    return -1;
}

一个可能的问题是“比较”循环的结尾:

if(numpairs!=0)
    temp2=findwinner(hands[cd]);

由于“ cd”当时超出范围,您将得到奇怪的结果。 您必须为我们解释更多信息,以确保正确的方法。

您应该对您的排序代码进行单元测试。 这种转变并不是真正必要的。 位屏蔽可确保值单调递增而忽略了顺服,这大概是被移出的东西。


我看了完整的代码(在定义功能findpairs()之前缺少一对findpairs()括号)。 它不需要<windows.h>标头来编译,这很好。 核心代码-洗牌的代码-似乎足够牢固。 我会做很多挑剔的更改,但是还可以。

一个微妙的细节:卡比较例程不会对数组'2H 2C 2S 2D 3S'进行排序,因此,演绎方式是按照任何特定的西装顺序排列的。 稍后可能会很重要。 具有“ 2C 2S”的人可能会胜过具有“ 2D 2H”的人,因为2S的排名高于其他任何派彩。 如果不是这种情况,您仍然需要确定规则。 您还需要考虑“ 2H 2C 2S 2D 3S”手牌有多少对-6是一个合理的答案。

findpairs()代码中间有一段有趣的代码; 我认为您应该使用双重循环,而内部循环会找到等值卡范围的末端。

我最初强调的行是问题开始的地方-我认为您没有适当地制定如何确定获胜者的方法,因为您没有保留必要的信息。 条件' numpairs!=0 '始终为true,因为numpairs是一个数组,并且指针永远不是空指针。

此外,当findwinner()函数时, cd为6,因此行为未定义。 由于您立即丢弃了返回的值,因此其中的某些无关紧要。

显然,您需要努力:

  • 如何处理三元组和四元组
  • 如何确定获奖者

但是,有关使用qsort()原始问题可以回答“您正在使用它,确定”。

顺便说一句,我注意到在某些地方,您可以使用以下表达式比较卡片值的相等性:

if (values[(hands[hand][cd]&0x3C)>>2] == values[(hands[hand][cd]&0x3C)>>2])

在此不需要引用values数组。 可以,但是没有必要。


修改后的代码-不能确定获胜者,但在其他方面则稍显整洁。 可以使用'-DVERBOSE_NAMES'进行编译,以打印出长名称的卡片。 否则,它使用短名称:“ A”表示俱乐部的王牌,“ 2H”表示心的减少,“ TD”表示十个钻石,“ KS”表示黑桃王。 由于它在循环中声明变量和使用内联函数等方式,因此它需要C99(或C ++)编译器。(已测试:MacOS X 10.6.4上的GCC 4.5.1和G ++ 4.5.1。)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

enum { NUM_HANDS      =  5 };
enum { CARDS_PER_HAND =  7 };
enum { CARDS_PER_DECK = 52 };

typedef unsigned char card;
typedef unsigned char pairs;

static const char *values[]=
{
    "Ace", "Two", "Three", "Four", "Five", "Six",
    "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"
};
#ifdef VERBOSE_NAMES
static const char *suits[] = { "Hearts", "Diamonds", "Clubs", "Spades" };
static const char *colour[]= { "Black", "Red" };
#endif /* VERBOSE_NAMES */

static void printcard(card c); /* Displays the value of a card*/
static void printdeck(card deck[CARDS_PER_DECK]); /* prints an entire deck of cards*/
static void filldeck(card deck[CARDS_PER_DECK]); /* Populates a deck of cards */
static void shuffle(card deck[CARDS_PER_DECK]); /* Randomizes the order of cards */
static int  compareface(const void* c1, const void *c2);
static pairs findpairs(card *hand); /* finds any pairs in a hand */

static inline int card_value(card c)  { return((c & 0x3C) >> 2); }
static inline int card_suit(card c)   { return((c & 0x03)); }
static inline int card_colour(card c) { return((c & 0x40) ? 1 : 0); }

static void deal(card deck[CARDS_PER_DECK], card hands[NUM_HANDS][CARDS_PER_HAND])
{
    int i = 0;
    for (int cd = 0; cd < CARDS_PER_HAND; cd++)
    {
        for (int hand = 0; hand < NUM_HANDS; hand++)
            hands[hand][cd] = deck[i++];
    }
}

static void printhand(int num, card hand[CARDS_PER_HAND])
{
#ifdef VERBOSE_NAMES
    printf("\tHand %i:\n", num);
#else
    printf("\tHand %i:", num);
#endif /* VERBOSE_NAMES */
    for (int cd = 0; cd < CARDS_PER_HAND; cd++)
    {
        printcard(hand[cd]);
    }
}

static void printhands(card hands[NUM_HANDS][CARDS_PER_HAND])
{
    int i;
    for (i = 0; i < NUM_HANDS; i++)
    {
        printhand(i+1, hands[i]);
        putchar('\n');
    }
}

int main()
{
    card deck[CARDS_PER_DECK];
    card hands[NUM_HANDS][CARDS_PER_HAND];
    pairs numpairs[NUM_HANDS];

    printf("(__)(__)(__)(__) CARD  GAME (__)(__)(__)(__)(__)\n");
    printf("(__)(__)(__)(__)(__)(__)(__)(__)(__)(__)(__)(__)\n\n");
    printf("\t====== Before Shuffling =====\n\n");
    srand(time(NULL));  /* seed the random number generator */

    filldeck(deck);
    printdeck(deck);
    printf("\t========== Shuffled Cards ========\n\n");
    shuffle(deck);
    printdeck(deck);
    deal(deck, hands);
    printf("\t============= Hands ===========\n\n");
    printhands(hands);
    putchar('\n');

    printf("\t============= Analysis ===========\n\n");
    for (int hand = 0; hand < NUM_HANDS; hand++)
    {
        qsort(hands[hand], CARDS_PER_HAND, sizeof(card), compareface);;
        printhand(hand+1, hands[hand]);
        numpairs[hand] = findpairs(hands[hand]);
    }

    return 0;
}

static pairs findpairs(card *hand)
{
    card pair = 0;
    pairs numpairs = 0;

    for (int cd1 = 0; cd1 < CARDS_PER_HAND; cd1++)
    {
        for (int cd2 = cd1 + 1; cd2 < CARDS_PER_HAND; cd2++)
        {
            if (card_value(hand[cd1]) == card_value(hand[cd2]))
            {
                numpairs++;
                pair = hand[cd1];
            }
        }
    }

    if (numpairs > 0)
        printf("    %d pairs - highest pair is: %s\n", numpairs,
              values[card_value(pair)]);
    else
        printf("    0 pairs\n");
    return numpairs;
}

void filldeck(card deck[CARDS_PER_DECK])
{
    int i = 0;
    for (int suit = 0; suit < 4; suit++)
    {
        for (int value = 0; value < 13; value++)
        {
            deck[i] = suit | (value<<2);
            if (suit < 2)
                deck[i] |= 0x40;  /*card is red, so do red stuff */
            i++;
        }
    }
}

void printdeck(card deck[CARDS_PER_DECK])
{
    for (int i = 0; i < CARDS_PER_DECK; i++)
    {
        printcard(deck[i]);
        if ((i % 13) == 12)
            putchar('\n');
    }
    putchar('\n');
}

#ifndef VERBOSE_NAMES
static char abbr_card_value(card c)
{
    static const char abbr_values[] = "A23456789TJQK";
    return abbr_values[card_value(c)];
}
static char abbr_card_suit(card c)
{
    static const char abbr_suits[] = "CDHS";
    return abbr_suits[card_suit(c)];
}
#endif /* VERBOSE_NAMES */

void printcard(card c)
{
#ifdef VERBOSE_NAMES
    printf("\t%s\t of  %-8s  is  %s\n", values[card_value(c)], suits[card_suit(c)],
           colour[card_colour(c)]);
#else
    printf("  %c%c", abbr_card_value(c), abbr_card_suit(c));
#endif /* VERBOSE_NAMES */
}

void shuffle(card deck[CARDS_PER_DECK])
{
    for (int i = 0; i < CARDS_PER_DECK; i++)
    {
        int rnd = rand() * 52.0 / RAND_MAX;
        card c = deck[rnd];
        deck[rnd] = deck[i];
        deck[i] = c;
    }
}

int compareface(const void* c1, const void *c2)
{
    card cd1 = *((card*) c1);
    card cd2 = *((card*) c2);

    cd1 = card_value(cd1);
    cd2 = card_value(cd2);

    if (cd1 > cd2)
        return +1;
    else if (cd1 < cd2)
        return -1;
    else
        return  0;
}
  1. 如果您真的只需要这个来获得最大的配对数,那么这确实是错误的策略:过于复杂且不必要地缓慢。 只需使用for循环遍历您的牌组,然后选择到目前为止已看到的最大对。
  2. 卡的比较代码表明您尚未对程序进行足够的模块化。 如果您坚持要用似乎是整数的形式对卡进行编码,请不要使用shifts之类的东西来访问不同的部分,而要使用位域。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM