используя qsort для сортировки массива - PullRequest
0 голосов
/ 15 августа 2010

Предполагается, что эта программа сортирует карты, группирует их в 5 групп, называемых руками, по-видимому, код делает именно это, однако по какой-то причине я не уверен, я не могу определить победителя. Предполагается, что победителем будет значение, показанное как наивысшее среди пар. если в первой руке король является самой старшей парой, а в руке 3 - самая старшая пара, то первая рука должна быть объявлена ​​победителем.

#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;
}

Ответы [ 2 ]

1 голос
/ 15 августа 2010

Одна вероятная проблема - в конце цикла сравнения:

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

Поскольку в это время «cd» находится вне диапазона, вы получите странные результаты.Вы должны были бы объяснить больше, чтобы мы были уверены, что правильно.

Вам следует выполнить модульное тестирование своего кода сортировки.Сдвиг не является действительно необходимым;битовая маскировка гарантирует, что значения монотонно возрастают, игнорируя масти, что, вероятно, и смещается.


Я посмотрел полный код (в котором отсутствует пара закрывающих скобок)до определения функции findpairs()).Для компиляции не требуется заголовок <windows.h>, и это хорошо.Основной код - то, что тасует карты и т. Д. - кажется достаточно надежным.Я бы сделал множество мелких изменений, но это нормально.

Одна тонкая деталь: процедура сравнения карт не сортирует массив '2H 2C 2S 2D 3S', так что двойкив любом конкретном порядке костюма.Это может иметь значение позже;человек с '2C 2S' может победить человека с '2D 2H', потому что 2S оценивается выше, чем любая другая двойка.И если это не так, вам все равно нужно записать правила.Вам также необходимо учитывать, сколько пар в раздаче '2H 2C 2S 2D 3S' - разумный ответ - 6.

Код findpairs() имеет интересную фигуру в середине;Я думаю, что вы должны использовать двойной цикл, при котором внутренний цикл находит конец диапазона карт равной стоимости.

Строки, которые я выделил, - это то, с чего начинаются ваши проблемы - я не думаю, что выправильно сформулировать, как вы определяете победителя, потому что вы не храните необходимую информацию.Условие 'numpairs!=0' всегда выполняется, поскольку numpairs является массивом, а указатель никогда не является нулевым указателем.

Кроме того, когда вызывается функция findwinner(), cd равно 6,и, следовательно, поведение не определено.Поскольку вы сразу же выбрасываете возвращенное значение, некоторые из них не имеют значения.

Очевидно, вам нужно усердно работать над:

  • Как обрабатывать тройки и четверки
  • Как определить победителей

Но на ваш первоначальный вопрос об использовании qsort() можно ответить "вы используете его в порядке".

Попутно отмечу, чтоэто места, где вы сравниваете значения карт на равенство с такими выражениями, как:

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

В этом нет необходимости ссылаться на массив values.Работает нормально, но это не нужно.


Пересмотренный код - определение победителя не определено, но в некоторых отношениях немного более аккуратно.Может быть скомпилирован с '-DVERBOSE_NAMES', чтобы распечатать карточки с длинными именами.В противном случае он использует короткие имена: «AC» для туза треф, «2H» для двойки червей, «TD» для десяти бриллиантов и «KS» для короля пиков.Для этого требуется компилятор C99 (или C ++) из-за способа объявления переменных в циклах и использования встроенных функций и т. Д. (Протестировано: GCC 4.5.1 и G ++ 4.5.1 на MacOS X 10.6.4.)

#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;
}
0 голосов
/ 15 августа 2010
  1. Если вам действительно нужно только это, чтобы получить максимальную пару, это действительно неправильная стратегия: слишком сложная и излишне медленная.Просто используйте петлю for, чтобы пробежаться по вашей колоде и выберите самую большую пару, которую вы когда-либо видели.
  2. Код сравнения карт показывает, что вы недостаточно модулировали свою программу.Если вы настаиваете на том, чтобы закодировать свои карты в целое число, как кажется, не используйте сдвиги и тому подобное для доступа к различным частям, но к битовым полям.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...