将扑克牌发给四个阵列
Posted
技术标签:
【中文标题】将扑克牌发给四个阵列【英文标题】:Dealing playing cards to four arrays 【发布时间】:2021-03-06 23:14:10 【问题描述】:当我尝试使用结构向四个玩家发 52 张牌时,代码可以运行,但问题是在输出中出现了一些错误:
#include <stdio.h>
#include <time.h>
typedef struct
char *value;
char *type;
card;
int main()
srand(time(NULL));
int i, r;
char name[4][9] = "diamonds","clubs","hearts","spades";
char num[13][6] = "ace","two","three","four","five","six","seven","eight","nine","ten","jack","queen","king";
card c[52];
card temp;
card player1[13], player2[13], player3[13], player4[13];
for (i=0 ; i<52 ; i++)
c[i].type = name[i % 4];
c[i].value = num[i % 13];
for (i=0 ; i<52 ; i++)
r= rand() % 52;
temp = c[i];
c[i] = c[r];
c[r] = temp;
for (i=0 ; i<52 ; i++)
switch(i+1 % 4)
case 0:
player1[i].type= c[i].type;
player1[i].value= c[i].value;
break;
case 1:
player2[i].type= c[i].type;
player2[i].value= c[i].value;
break;
case 2:
player3[i].type= c[i].type;
player3[i].value= c[i].value;
break;
default:
player4[i].type= c[i].type;
player4[i].value= c[i].value;
printf("Player 1 \n");
for (i=0 ; i<13 ; i++)
printf("%s %s\n" , player1[i].type, player1[i].value);
printf("\n");
printf("Player 2 \n");
for (i=0 ; i<13 ; i++)
printf("%s %s\n" , player2[i].type, player2[i].value);
printf("\n");
printf("Player 3 \n");
for (i=0 ; i<13 ; i++)
printf("%s %s\n" , player3[i].type, player3[i].value);
printf("\n");
printf("Player 4 \n");
for (i=0 ; i<13 ; i++)
printf("%s %s\n" , player4[i].type, player4[i].value);
printf("\n");
return 0;
输出: 玩家 1 红心九 钻石王 心十 钻石十 黑桃杰克 俱乐部之王 红心四 黑桃八 黑桃王 俱乐部杰克 黑桃二 钻石杰克 心杰克
玩家 2 黑桃六 红心皇后 钻石王牌 黑桃五 钻石六 红心七 俱乐部八 俱乐部七 黑桃王牌 三颗心 红心王 钻石二 俱乐部六
玩家 3 黑桃三 钻石七 俱乐部女王 红心六 红心五 钻石三 黑桃九 俱乐部三 黑桃皇后 俱乐部王牌 俱乐部二 钻石四 心王
玩家 4 à└ëD$@ï╪☼ê°♥ (null) (空) (空) 两颗心 红心八 钻石九 俱乐部五 黑桃七 俱乐部九 黑桃四 俱乐部十 钻石八 钻石皇后 俱乐部四
它进入了播放器 4 空和奇怪的字符,请任何解决方案。
【问题讨论】:
交易循环for (i=0 ; i<52 ; i++)
会发生什么,例如player1[i]
?播放器阵列有多大? (提示:不是52
)
一个播放器数组包含13个元素
i > 12
时会发生什么? (提示:Undefined Behavior 由超出数组边界的写入引起)
switch(i+1 % 4)
==> 如果必须... switch((i+1) % 4)
并添加default
案例
【参考方案1】:
当您循环for (i=0 ; i<52 ; i++)
设置player1[i]
、player2[i]
等时,您的问题出现在您的交易循环中。你用13
元素声明你的播放器数组。所以在你的循环中,当i > 12
你调用Undefined Behavior 试图写入13th
元素及以后。
要解决此问题,您需要将玩家索引限制为0-12
,您可以使用i % 13
,例如
for (i=0 ; i<52 ; i++)
switch (i % 4)
case 0:
player1[i%13] = c[i];
break;
case 1:
player2[i%13] = c[i];
break;
case 2:
player3[i%13] = c[i];
break;
default:
player4[i%13] = c[i];
或者为您的玩家索引保留单独的计数器,并在发牌时递增每个计数器。 进行更改,您将拥有,例如
int p1 = 0, p2 = 0, p3 = 0, p4 = 0;
...
for (i=0 ; i<52 ; i++)
switch (i % 4)
case 0:
player1[p1++] = c[i];
break;
case 1:
player2[p2++] = c[i];
break;
case 2:
player3[p3++] = c[i];
break;
default:
player4[p4++] = c[i];
(注意:你可以简单地分配结构,不需要单独的值。你可以从switch (i % 4)
中删除+1
。)
现在您的手将在没有 SegFault 的情况下处理。
【讨论】:
为什么这是正确答案?为什么使用 4 个不同的数组?此外,代码还有许多其他问题...***.com/a/64982690/14273548 你也可以用我的例子来做,修改代码,或者让播放器成为指向数组中那个索引的指针,有 4 个数组是不好的做法...@superzer101 @UriyaHarpeness 使用一维数组还是二维数组完全无关紧要。从微优化的角度来看,一维阵列具有性能优势。 首先,在这个概念上,您也可以避免使用一维数组,其次,它需要更多的内存,并且可读性要低得多。 @DavidC.Rankin 它占用的内存不多也不少——句号。你是从哪里想到的?数组是nelements * sizeof(type)
字节的连续块,无论是一维还是二维。不同之处在于二维数组,您需要计算正在完成的偏移量。【参考方案2】:
这是一个可能的实现,可以满足您的要求:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define PLAYERS_NUM 4
#define CARDS_PER_PLAYER 13
#define NAMES_NUM 4
#define VALUES_NUM 13
#define TOTAL_CARDS NAMES_NUM*VALUES_NUM
typedef struct
char *value;
char *type;
card;
int main()
srand(time(NULL));
unsigned int i, j, r;
char *name[NAMES_NUM] = "diamonds", "clubs", "hearts", "spades";
char *num[VALUES_NUM] = "ace", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "jack",
"queen", "king";
// Initialize pile.
card cards[TOTAL_CARDS];
for (i = 0; i < NAMES_NUM; i++)
for (j = 0; j < VALUES_NUM; j++)
cards[(i * VALUES_NUM) + j] = (card) name[j], num[i];
card tmp;
// Shuffle pile.
for (i = 0; i < TOTAL_CARDS; i++)
r = rand() % TOTAL_CARDS;
tmp = cards[r];
cards[r] = cards[i];
cards[i] = tmp;
card players[PLAYERS_NUM][CARDS_PER_PLAYER];
// Deal cards.
for (i = 0; i < PLAYERS_NUM; i++)
for (j = 0; j < CARDS_PER_PLAYER; j++)
players[i][j] = cards[i * CARDS_PER_PLAYER + j];
// Printing.
for (i = 0; i < PLAYERS_NUM; i++)
printf("Player %d\n", i);
for (j = 0; j < CARDS_PER_PLAYER; j++)
printf("%s %s\n", players[i][j].type, players[i][j].value);
printf("\n");
return 0;
几点:
您没有包含#include <stdlib.h>
。
您没有发牌,可能有重复的牌,此实现会洗牌并发牌,不会重复。
您不需要 4 个数组来保存玩家,二维数组更好(也可以稍后传递给函数)。
如果您使用定义的值而不是一遍又一遍地重复它们,代码看起来会更简洁,这样它们也可以在一个地方更改并在任何地方生效。
您不需要定义名称和值的大小,如果您不打算更改它们,它们将是静态常量字符串,因此只需定义为char *
,这样就不需要找出最长的字符串,分配无用的数据。
【讨论】:
【参考方案3】:由于您声明 Player 结构数组大小为 13,但您传递的最大为 52,这就是它显示空名称的原因。您应该始终在Player
结构中传递<13
索引。为此,通过 Mod 为 13 传递 player[i%13]
值。
player[i%13].type= c[i].type;
player[i%13].value= c[i].value;
当你传递for(i=0 ; i<52 ; i++)
你的循环传递大尺寸。 Mod 13 表示一个玩家最多可以获得 12 个值。
#include <stdio.h>
#include<math.h>
typedef struct
char *value;
char *type;
card;
int main()
int i, r;
char name[4][9] = "diamonds","clubs","hearts","spades";
char num[13][6] = "ace","two","three","four","five","six","seven","eight","nine","ten","jack","queen","king";
card c[52];
card temp;
card player1[13], player2[13], player3[13], player4[13];
for (i=0 ; i<52 ; i++)
c[i].type = name[i % 4];
c[i].value = num[i % 13];
for (i=0 ; i<52 ; i++)
r= rand() % 51;
temp = c[i];
c[i] = c[r];
c[r] = temp;
for (i=0 ; i<52 ; i++)
int ind=i+1;
switch(ind % 4)
case 0:
player1[i%13].type= c[i].type;
player1[i%13].value= c[i].value;
break;
case 1:
player2[i%13].type= c[i].type;
player2[i%13].value= c[i].value;
break;
case 2:
player3[i%13].type= c[i].type;
player3[i%13].value= c[i].value;
break;
default:
player4[i%13].type= c[i].type;
player4[i%13].value= c[i].value;
printf("Player 1 \n");
for (i=0 ; i<13 ; i++)
printf("%s %s\n" , player1[i].type, player1[i].value);
printf("\n");
printf("Player 2 \n");
for (i=0 ; i<13 ; i++)
printf("%s %s\n" , player2[i].type, player2[i].value);
printf("\n");
printf("Player 3 \n");
for (i=0 ; i<13 ; i++)
printf("%s %s\n" , player3[i].type, player3[i].value);
printf("\n");
printf("Player 4 \n");
for (i=0 ; i<13 ; i++)
printf("%s %s\n" , player4[i].type, player4[i].value);
printf("\n");
return 0;
【讨论】:
以上是关于将扑克牌发给四个阵列的主要内容,如果未能解决你的问题,请参考以下文章