【发布时间】:2018-06-06 22:44:05
【问题描述】:
所以在我写的这个小游戏中,我有一副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完全符合您的预期,它只有 3 条语句。
n_C和n_H都是#define的常量,n_P是一个局部变量。
当我使用洗牌后的牌组和参数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 中都观察到了这种行为。
【问题讨论】:
-
"in C" - 那你为什么把它标记为
C++? -
在
for (size_t j = i - 1; j >= 0; j--)中,当i == 0外循环的第一次迭代时会发生什么?size_t类型是无符号的。这看起来像是一个糟糕的冒泡排序。 -
“我的编码能力没有问题,但编译器似乎在惹我。”永远怀疑这一点。
-
在我看来,我的编码技能并没有错, -- 所以你是说全世界成千上万的人和公司都在使用编译器无法正确执行您的简单代码?
-
在你的 C 编程生涯的这个阶段,假设如果编译器打算警告你一个问题,这意味着你有一个严重的错误。编译器没有错。也许在 30 年后你将有能力换一种思维方式,但我知道当编译器抱怨时我必须假设我有错,而且这种假设错误的情况非常罕见。