因此,在我写的这个小游戏中,我有一副n_C
卡片,每张卡片都有一个唯一的整数值。有n_P
球员各自手持n_H
卡。
甲板和手共用一个阵列,如下所示:玩家i_P
的手牌包含从deck[i_P * n_H
到deck[i_P * (n_H + 1) - 1]
的所有牌。所有球员组合总是比n_C
卡少。
现在我想对每个玩家的牌进行排序,但不是整个牌组(显然,因为这会在牌手之间移动一些牌)。我这样做是这样的:
void sort_hands(char * deck, size_t n_P) {
for (size_t i_P = 0; i_P < n_P; i_P++)
sort_cards(deck + i_P * n_H, n_H);
}
然后,使用插入排序(此函数将对整个数组进行排序):
void sort_cards(char * cards, size_t n) {
for (size_t i = 0; i < n; i++) {
for (size_t j = i - 1; j >= 0; j--) {
if (cards[j] > cards[j + 1])
card_swap(cards, j, j + 1);
else
break;
}
}
*注意:card_swap
does正是你所期望的,它只有3个陈述。
n_C
and和n_H
都是#define
'd常数,n_P
是局部变量。当我用一个洗牌的甲板和params n_C = 104, n_H = 10, n_P = 3
运行上面的代码时,我得到:
0:74 31 53 46 42 75 72 77 70 49
1:76 86 99 78 11 94 61 14 41 87
2:40 26 92 5 9 3 66 63 101 98
在子阵列排序之前,例如:
0:3 5 9 11 31 42 46 49 53 74
1:61 70 75 72 76 77 78 86 94 99
2:14 26 40 41 63 66 87 92 98 101
然后。正如我们所看到的,有些牌在他们不应该的时候已经移动了。但是牌组并没有按照所有牌的方式进行分类(例如参见玩家2手中的14
。这怎么可能?我看到它的方式,我的编码技巧没有错,但编译器似乎在弄乱我。
我用VS15 C ++编译器和GCC都观察到了这种行为。
我编译了你的sort_cards()
函数(在提供缺少的}
之后),在Mac上使用GCC 7.2.0和命令行:
gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
-Wstrict-prototypes -c cards53.c
有了这些选项(关键的一个是-Wextra
),它会立即发出警告:
cards53.c:31:34: error: comparison of unsigned expression >= 0 is always true [-Werror=type-limits]
for (size_t j = i - 1; j >= 0; j--)
这表明存在严重问题。特别是在外环的第一次迭代中,i
是0
,所以i - 1
是一个非常大的数字。坦率地说,你声称该函数将成功排序整个数组是虚假的。它不会。并且我不会运行无法使用显示的命令行编译的代码。
如果您修复了该功能,那么您的代码就可以了。我用了:
#include <stdio.h>
#define n_H 10
#define n_C 104
static inline void card_swap(char *deck, int i1, int i2)
{
char t = deck[i1];
deck[i1] = deck[i2];
deck[i2] = t;
}
static void sort_cards(char *cards, size_t n)
{
for (size_t i = 1; i < n; i++)
{
for (size_t j = i; j-- > 0; )
{
if (cards[j] > cards[j + 1])
card_swap(cards, j, j + 1);
else
break;
}
}
}
static void sort_hands(char *deck, size_t n_P)
{
for (size_t i_P = 0; i_P < n_P; i_P++)
sort_cards(deck + i_P * n_H, n_H);
}
static void dump_hands(const char *tag, const char *deck, size_t n_P)
{
printf("%s:\n", tag);
for (size_t p = 0; p < n_P; p++)
{
printf("Player %zu:", p + 1);
const char *hand = deck + p * n_H;
for (int i = 0; i < n_H; i++)
printf(" %3d", hand[i]);
putchar('\n');
}
}
int main(void)
{
char deck[n_C] =
{
74, 31, 53, 46, 42, 75, 72, 77, 70, 49,
76, 86, 99, 78, 11, 94, 61, 14, 41, 87,
40, 26, 92, 5, 9, 3, 66, 63, 101, 98,
};
int n_P = 3;
dump_hands("Before", deck, n_P);
sort_hands(deck, n_P);
dump_hands("After", deck, n_P);
return 0;
}
使用您提供的样本数据初始化数组;残留物全部为零,但这对于此练习无关紧要。
样本输出:
Before:
Player 1: 74 31 53 46 42 75 72 77 70 49
Player 2: 76 86 99 78 11 94 61 14 41 87
Player 3: 40 26 92 5 9 3 66 63 101 98
After:
Player 1: 31 42 46 49 53 70 72 74 75 77
Player 2: 11 14 41 61 76 78 86 87 94 99
Player 3: 3 5 9 26 40 63 66 92 98 101
检查显示每个子数组已正确排序。