使用qsort对数组进行排序
该程序应该对卡片进行排序,并将它们分组为5个组,称为手,但代码完全是这样做的,但由于某种原因我不太确定,我无法确定该winer。优胜者应该是在双人中显示最高的价值。如果手牌有最高的国王,而手牌3有最高的7副,那么手牌应该被宣布为赢家。使用qsort对数组进行排序
#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()
前失踪一对右括号的定义)。它不需要<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++)编译器,因为它在循环中声明变量并使用内联函数等。(测试:Mac OS 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;
}
如果没有全部代码,我真的觉得很难解释,我已经发布了所有的代码。尽管如此,你可以简单地执行它,然后你会马上看到你在说什么!我无法宣布获胜者,这应该来自排序的对。 – 2010-08-15 08:41:14
- 如果你真的只需要这个得到 的最大配对,这真的是 错误的策略:太复杂了, 不必要的慢。只需使用
for
循环遍历你的套牌,并选择 到目前为止看到的最大的一对。 - 您的卡片 的比较代码表明您没有将您的程序模块化为 。如果 您坚持认为您的卡的编码为 整数,看起来不要使用 班次,并且不要使用 不同的部分,而是使用位域。
是你通常如何格式化你的C代码? – 2010-08-15 04:36:00
也许你可以添加声明'手','甲板'以及'卡'的代码? – 2010-08-15 04:43:10