我正在使用 CPP 制作二十一点游戏,但我一直坚持如何从我的 [4][13] 数组中随机选择一个元素而不重复它并且不打乱数组的顺序。在 VisualStudio 中工作。到目前为止,我只能找到有关如何使用一维数组执行此操作的答案。有人有建议吗?
8 回答
二维数组很容易被认为是一维数组。你只需要做一点数学。
如果您有一个适用于 52 元素一维数组的解决方案(一个随机排序的值 0-51 的新数组)。请执行下列操作:
- 生成你的随机元素,我们称之为 R(0 到 51 之间)。
- 现在,将该数字转换为您的二维阵列系统。(x,y 的形式)
x = R / 13
y = R % 13
用于std::random_shuffle
从 中随机打乱一个向量(比如vector<int> v
)0-51
。由于打乱random_shuffle
了给定的向量,v
现在是你随机打乱的向量。
v.back()
返回向量中的最后一个元素。因此,以下代码k
从向量中返回最后一个元素 ( ),然后将其删除。它还将其转换为 adouble
以便您可以计算k/13
.
double k = static_cast<double>(v.back());
v.pop_back();
现在,由于您的矩阵是 4x13,因此k
第 th 元素(行主要)位于 rowfloor(k/13)
和 column k%13
。
我建议你强烈考虑使用std::deque<T>
容器。一个代表牌组本身的双端队列,然后您可以在发牌时将“牌”推出并弹出。
好吧,这样做的一种方法是向bool
数组的元素添加一个字段,并且当数组的该元素被选中时,将其设置为 true。然后在未来的选择中,检查是否bool
为true
,如果是,则生成另一个随机元素。可能不是最有效的,但它很简单。
有了这个,您还可以轻松地创建一个方法来遍历数组并将所有 bool 字段设置为 false 以模拟随机播放。
附注:不要对数字 52 进行硬编码:您可能希望在同一个数组中洗牌多个牌组。在二十一点赌场的游戏中,经常在二十一点“鞋”中使用多副牌,特别是每张鞋有 4 副牌是很常见的。这对条件概率具有重要意义:正面朝上的牌和正面朝下的牌之间的相关性较小。你不想单独洗 52 张牌,你需要洗整个 N*52 张牌的鞋子。其他答案中提出的算法适用于 3-D 数组和 2-D 数组,只需稍作修改。
我一直喜欢的一种方法是获取 2d 数组,然后生成 2 个坐标进行交换。执行该n
次数,然后您可以使用 some 遍历 2D 数组for loops
。
有一个简单的解决方案涉及使用素数。如果你在你的数组中取一个随机的初始索引(为简单起见,让它是一个一维数组),然后将该索引增加一个大于数组长度的素数,并且只取除以数组长度后的提示,你将获得一个随机非重复索引的序列。
像这样的东西:
#include <cstdlib>
#include <iostream>
#include <time.h>
const int Cols = 4;
const int Rows = 13;
const int N = Cols * Rows;
const int NPrimes = 12;
const int primes[NPrimes] = {59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107};
int prime = primes[0];
int index = 0;
void shuffle()
{
srand(time(NULL)); // Random seed
prime = primes[rand() % NPrimes]; // Get random prime number
index = rand() % N; // Get random first index
}
// Compute next index in sequence
int nextIndex(int index)
{
return (index + prime) % N;
}
int _tmain(int argc, _TCHAR* argv[])
{
shuffle();
for (int i = 0; i < N; i++) {
int col = index / Rows;
int row = index % Rows;
std::cout << "[" << col << ", " << row << "] ";
index = nextIndex(index);
}
std::cout << std::endl;
return 0;
}
在 N 次迭代之后,该序列显然会重复自身。
我宁愿使用包含所有卡片的列表。如果您坚持使用 [4] 为套件 [13] 为数字的 2d 数组,则答案很简单,使甲板就位并且永不改变值,但是,使数组变量为布尔值。
生病写伪代码。
initialize cardsselected to zero
Choose Card
Randomly select 2 numbers 1 will be 0-3 and the other 0-12.
If the array at [random suite][random number] is not false
choose it
increment cardsselected
set value to false
return true
else if cardsselected equals 52 return false
else
run chooseCard()
return true
这只是一个解决方案。它不是很优化,可能需要很长时间。
对其进行优化。
您可以保留您的二维数组以将卡片固定在适当的位置,从而生成随机数。要优化随机数生成,您可以创建一个随机数列表 1-52 并从中随机选择。然后删除从列表中选择的号码。