将数组的特定元素移动到新数组

Moving a particular element of an array to a new array

本文关键字:数组 新数组 元素 移动      更新时间:2023-10-16

我有一个长度为 52 的一维数组(一副牌),有 4 组介于 1-13 之间的数字。

目前,我有它,以便随机数生成器选择一个元素,如果该数字在某个范围之间,则是一种颜色,在另一个范围之间是不同的颜色,等等。

我希望能够删除 RNG 选择的元素,将其移动到另一个数组,即播放器,并将其转换为具有相应颜色的二维数组。 我想每次都使数组更小,这样就不会有重复项。 现在,我一次显示13个数字,还有很长的路要走。

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
int x = 51;
while (x >=1)
{
int ar[x] = {1,2,3,4,5,6,7,8,9,10,11,12,13,1,2,3,4,5,6,7,8,9,10,11,12,13,1,2,3,4,5,6,7,8,9,10,11,12,13,1,2,3,4,5,6,7,8,9,10,11,12,13};
int ft = 14;
srand(time(NULL));
int rNumber = rand() % x;
if (rNumber < ft)
{
cout << ("yellow") << ar[rNumber] << "n";
x--;
}
else if (rNumber < ft * 2)
{
cout << ("blue") << ar[rNumber] << "n";;
x--;
}
else if (rNumber < ft * 3)
{
cout << ("red") << ar[rNumber] << "n";
x--;
}
else cout << ("black") << ar[rNumber] << "n";
x--;
}
}

如果我理解你的问题,你有很多问题阻止你达到你的目标,即按花色将 52 张牌分成四个数组,以收集一些花色的"手">牌,其中任何一套花色中没有一张牌是 (1 - 13), 例如"王牌->王

"。如果我有这个权利,那么你想要使用rand在你的牌组上循环选择一个"牌号",然后你用它来用你的if (rNumber < FT) ...逻辑对牌进行分类,结果类似于:

YELLOW     BLUE      RED    BLACK
13       12        5       11
7        8        1        5
8       13       13        1
10        1       12        7
6        7        3       12
3        4       11        3
11        3        2        4
0        0        9        6
0        0        6        2

(其中0只是意味着"未发牌",例如,与9 = RED and BLACK牌相比,这次运行中只生成了7 - YELLOW and BLUE cards。(代表生成的重复卡片的总数和52之间的差异)为了确保完整的交易,您需要在生成的每张唯一卡上循环while (x < 52)递增x,而不是简单地循环52次 - 这留给您)

正如其他人在评论中建议的那样,您可以使用 C++ 提供的容器来简化事情,同时使您的代码不易出错,例如vectormap等情况下,自动内存管理和内置的边界检查迭代例程可以防止您误入未定义的行为。也就是说,理解和学习如何处理普通的旧数组并没有错。(你会在过去 30 年写的许多C++中经常找到它们)。既然您已经选择了数组,那么让我们继续解决您的问题。

为了实现一些合理的卡片分配,您有许多问题需要解决。您遇到的两个主要问题是返回一个递减的数字,int rNumber = rand() % x;返回一个递减的数字,该数字以及您选择的ft = 14和比较确保您生成的BLACK卡为零(或非常接近零)。

每次迭代生成的随机卡号应该是0 - 51中的有效卡号,以对应于ar数组的有效索引,例如

#define SUITS  4    /* no. of suits */
#define FT    13    /* cards per-suit (left as FT as your original was ft) */
#define CARDS 52    /* cards per-deck */
...
int rNumber = rand() % CARDS;   /* mod with total cards not x */

接下来,"如果statements黄色<14, then蓝色<28and红色<42, that's not right, that only leaves10possible cards for黑色,则should not be14. Think about your"。相反,您需要:

if (rNumber < FT) { /* separate into suit, copy to deal array */
...

(这样13 - cards的有效索引(例如0 - 12)精确映射到每张花色每张牌的相应数组元素)

要将卡片分成单独的 2D 数组,其中每行代表一个花色,然后每列都可以容纳每个花色的每个唯一卡片,只需声明一个足够大小的 2D 数组,例如

int deal[SUITS][FT] = {{0}},    /* 2D array holding cards by suit */
count[SUITS] = {0},         /* count per-suit in deal */

(其中count只持有deal添加到每个花色中的牌数,例如当一张牌被添加到deal[YELLOW][n]时,你递增count[YELLOW]++;)

为了让自己更轻松,您可以创建一个全局enum,将您的西装颜色映射到适当的值,以便在代码的其余部分使用,例如

enum { YELLOW, BLUE, RED, BLACK };  /* color constants */

现在您有了常量YELLOW = 0BLUE = 1RED = 2BLACK = 3,这允许在分离条件期间轻松映射您的卡片以适应,例如

if (rNumber < FT) { /* separate into suit, copy to deal array */
cout << ("yellow - ") << ar[rNumber] << "n";
if (isunique (deal[YELLOW], count[YELLOW], ar[rNumber]))
deal[YELLOW][count[YELLOW]++] = ar[rNumber];
}
else if (rNumber < FT * 2) {
cout << ("blue - ") << ar[rNumber] << "n";
if (isunique (deal[BLUE], count[BLUE], ar[rNumber]))
deal[BLUE][count[BLUE]++] = ar[rNumber];
}
...

差不多就是这样。在卡牌全部分离后,您可以遍历count数组并找到任何一种花色中的最大牌数,然后输出您的deal数组,显示如何随机选择卡牌并过滤到不同的花色中。把它放在一个简短的例子中,你可以做这样的事情:

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <ctime>
using namespace std;
#define SUITS  4    /* no. of suits */
#define FT    13    /* cards per-suit */
#define CARDS 52    /* cards per-deck */
enum { YELLOW, BLUE, RED, BLACK };  /* color constants */
/* function to scan 'a' for 'val`
* returning 1 if 'val` doesn't exist, 0 otherwise
*/
int isunique (int *a, int sz, int val)
{
for (int i = 0; i < sz; i++)
if (a[i] == val)
return 0;
return 1;
}
int main (void) {
int ar[] = { 1,  2,  3,  4,  5,  6,  7,  8,  9, 10,
11, 12, 13,  1,  2,  3,  4,  5,  6,  7,
8,  9, 10, 11, 12, 13,  1,  2,  3,  4,
5,  6,  7,  8,  9, 10, 11, 12, 13,  1,
2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
12, 13 },
deal[SUITS][FT] = {{0}},    /* 2D array holding cards by suit */
count[SUITS] = {0},         /* count per-suit in deal */
maxcount = 0,               /* max cards per-suit in deal */
x = CARDS;
srand (time(NULL));
while (x--)     /* loop 52 times */
{   /* get card number (0 - 51) */
int rNumber = rand() % CARDS;   /* mod with total cards not x */
if (rNumber < FT) { /* separate into suit, copy to deal array */
cout << ("yellow - ") << ar[rNumber] << "n";
if (isunique (deal[YELLOW], count[YELLOW], ar[rNumber]))
deal[YELLOW][count[YELLOW]++] = ar[rNumber];
}
else if (rNumber < FT * 2) {
cout << ("blue - ") << ar[rNumber] << "n";
if (isunique (deal[BLUE], count[BLUE], ar[rNumber]))
deal[BLUE][count[BLUE]++] = ar[rNumber];
}
else if (rNumber < FT * 3) {
cout << ("red - ") << ar[rNumber] << "n";
if (isunique (deal[RED], count[RED], ar[rNumber]))
deal[RED][count[RED]++] = ar[rNumber];
}
else {
cout << ("black - ") << ar[rNumber] << "n";
if (isunique (deal[BLACK], count[BLACK], ar[rNumber]))
deal[BLACK][count[BLACK]++] = ar[rNumber];
}
}
for (int i = 0; i < SUITS; i++) /* find max cards in any one suit */
if (count[i] > maxcount)
maxcount = count[i];
/* output deal */
printf ("n%8s %8s %8s %8snn", "YELLOW", "BLUE", "RED", "BLACK");
for (int i = 0; i < maxcount; i++)
printf ("%8d %8d %8d %8dn",
i < count[YELLOW] ? deal[YELLOW][i] : 0,
i < count[BLUE] ? deal[BLUE][i] : 0,
i < count[RED] ? deal[RED][i] : 0,
i < count[BLACK] ? deal[BLACK][i] : 0);
}

示例使用/输出

当您确信原始卡号以您想要的方式按预期方式按花色分隔时,您可以删除每个if(..) else if (..)...中的原始cout语句。它们被留在下面(为了便于阅读,在颜色和数字之间添加了空格和连字符),因为这就是你拥有原始代码的方式。

$ ./bin/card_array
blue - 12
black - 11
red - 5
blue - 8
red - 1
black - 5
blue - 8
yellow - 13
blue - 8
blue - 8
blue - 13
blue - 1
blue - 12
red - 13
black - 1
black - 7
black - 5
red - 12
blue - 7
red - 3
blue - 8
red - 11
red - 2
yellow - 7
yellow - 8
black - 12
red - 5
yellow - 13
blue - 4
black - 7
red - 12
black - 3
black - 4
blue - 3
yellow - 10
blue - 4
red - 9
yellow - 6
yellow - 6
yellow - 3
blue - 13
red - 5
black - 6
black - 11
black - 6
red - 6
black - 5
red - 11
black - 6
yellow - 11
black - 2
yellow - 13
YELLOW     BLUE      RED    BLACK
13       12        5       11
7        8        1        5
8       13       13        1
10        1       12        7
6        7        3       12
3        4       11        3
11        3        2        4
0        0        9        6
0        0        6        2

虽然您可以通过使用C++容器来简化逻辑,例如vectormap等,学习如何处理简单的数组并没有错(在过去的30年里,有很多C++代码专门使用它们)。仔细查看,如果您有其他问题,请告诉我。

要删除数组的某个元素,我查看数组中的最后一个索引,然后将其与要删除的索引交换。然后,减小数组的大小。 例如:

int arr [] = {1,2,3,4,5};
int itemCount = 5; 

如果我想删除数组中的第二个项目,我会这样做:

arr[1] = arr[itemCount-1]; //Assigns 4th Index of array to 2nd Index.
itemCount--;

如果显示新数组,它将如下所示:

{1,5,3,4}