以下是一些可以帮助您安排事情的随机想法:
-
在 C / C++ 中,二维数组实际上是一维结构(一块连续的内存)。在 C 和 C++ 中,二维数组以 row-major 形式存储,这意味着我们将整个第一行放在内存中,然后将整个第二行放在内存中,依此类推。例如,如果我们有以下
二维数组
0 1 2 <--- columns
0 a b c
1 d e f
2 g h i
^
+-- rows
它将在内存中表示(假设我们使用 char 作为底层数据类型):
+---+---+---+---+---+---+---+---+---+
| a | b | c | d | e | f | g | h | i |
+---+---+---+---+---+---+---+---+---+
这种安排很有用,因为我们可以轻松地在一维内存数组中的索引和我们的二维数组概念之间进行转换。在以下等式中,R 表示我们的二维数组中的最大行数(本例中为 3),C 表示我们的二维数组中的最大列数(本例中为 3)。最后一点,我们对行和列使用零基数;因此元素'a'在第0行,第0列,以下缩写为[0,0]..
所以如果我们对 [r,c] 中的内容感兴趣,我们需要生成一个索引 n,via;
n = r * C + c
例如,如果我们对 [1,1] 感兴趣,我们会计算:
n = 1 * 3 + 1 = 4
换句话说,[1,1] 处的元素位于第四个索引处(再次记住数组是从零开始的)。
我们还可以通过使用将索引 n 转换回行列表示法;
r = n / C and c = n % C
例如,位于第六个内存位置(索引 = 5)的元素将是
r = 5 / 3 and c = 5 % 3 or [1,2]
-
树的放置相当简单,如果我们使用 n x n 数组,那么我们知道我们的索引从 [0, n$^2$-1] 运行,所以我们只生成该范围内的随机数,只是确保不要两次使用相同的数字。一些伪代码可能用于排列 t 树:
// assume that our game board is in a data-structure called `world'
len <- n*n; // maximum number in our range
trees <- t; // number of trees to place
do
ndx <- rand() % len // generate random number in range [0,len-1]
if ( world[ndx] == 0) // picked an empty space
world[ndx] = 8; // plant a tree
trees -= 1; // decrement tree's remaining
while (trees > 0);
-
在哪里放置帐篷也很容易。考虑二维数组与内存模型之间的关系,如果一棵树位于给定索引 ndx 处,则可能的帐篷位置列表为:
L = ndx - 1; // this is due left of the tree
R = ndx + 1; // this is due right of the tree
B = ndx + C; // this is below the tree
A = ndx - C; // this is above the tree
当然,我们必须确保我们不会离开这个世界。就个人而言,我会将它们存储在一个数组中,而不是四个变量中。
-
帐篷限制实际上只是说明八个相邻单元中的任何一个都不能有帐篷。考虑下图,我们在单元格中用 T 标记了一个帐篷。如果这个单元格的索引是 n,那么周围的单元格显示我们需要检查的索引。
+---+---------+-----+----------+---+
| | | | | |
+---+---------+-----+----------+---+
| | n-C - 1 | n-C | n-C + 1 | |
+---+---------+-----+----------+---+
| | n-1 | T | n +1 | |
+---+---------+-----+----------+---+
| | n+C -1 | n+C | n+C +1 | |
+---+---------+-----+----------+---+
-
让我们把 3 和 4 放在一起。我们首先创建一个函数placeTents,它采用一个放置树的索引数组。这是一个简单的函数,它会按照 {top, left, right, bottom} 的顺序创建一个潜在的树位置数组,如果这些位置中的任何一个超出范围,我们将在数组中设置一个负值。最后,我们尝试为
函数placeTent(P)中的帐篷;如果 placeTent 失败,我们将无法满足约束条件,并且从您的问题描述来看,您目前还不清楚您想做什么,对于本次讨论,我只是表示退出程序
placeTents(trees):
max <- R * C -1 // max index
for each tree in trees
if (tree - C) > 0 then P[0] = tree - C else P[0] = -1;
if (tree - 1) > 0 then P[1] = tree - 1 else P[1] = -1;
if (tree + 1) < max then P[2] = tree + 1 else P[2] = -1;
if (tree + C) < max then P[3] = tree + C else P[3] = -1;
if (!placeTent(P))
exitError;
对于 placeTent,我们需要检查所有八个邻居(可能不存在),为简单起见,我们只需在第一个可用位置放置一个帐篷。再次记住,placeTent 接受一个可能放置帐篷的位置列表,然后检查每个位置的可行性。同样,我们假设游戏板位于名为world的数组中
bool placeTent(P)
ret <- false;
max <- R * C - 1;
for each loc in P
if loc == -1 continue;
// calculate indexes we want to look at....
trial[0] <- loc - Col - 1;
trial[1] <- loc - Col;
.....
trial[6] <- loc + Col;
trial[7] <- loc + Col + 1;
for each t in trial
if ((t < 0) || (t > max)) continue; // we fell of the world.....splat!
if (world[t] == 0)
world[t] = 4;
return true;
return false; // failed to find a place to pitch our tent
最后,真正的挑战是为帐篷找到一个可行的位置,为此我会考虑递归,这样当我找不到可行的位置时,我们可以展开这些位置并尝试不同的路径。
看到这个旋转成的长度......对不起,可能是漫无边际的方式,太多了......我将把递归部分留到以后。
编辑/添加:
还有一件事我忘了说,上面的内容是非常确定的,即我们允许尝试在树上放置一个帐篷,然后逆时针移动。在某些时候人们会发现这一点,因此您可能希望随机化检查位置的顺序(即在 P 数组上为每棵树创建一个排列。)