检查是否已经进行了随机移动,并忽略随机化过程中的先前移动?

时间:2014-05-13 16:39:57

标签: cocos2d-iphone

我在滑动益智游戏中定位精灵,但我无法随机化平铺位置

如何检查是否已经进行了随机移动(arc4random),并忽略了随机化过程中的先前移动?

瓷砖做随机/重新洗牌,但有时重复随机移动 例如,瓷砖23滑动到瓷砖24的位置并向后滑动几次,计为随机移动 (这意味着董事会没有正确洗牌)

int count = 0;
int moveArray[5];
int GameTile;
int EmptySq;

//loop through the board and find the empty square
for (GameTile = 0; GameTile <25; ++GameTile) {
    if (boardOcc[GameTile]== kEMPTY) {
        EmptySq = GameTile;
        break;
    }
}

int RowEmpty = RowNumber[GameTile];
int colEmpty = ColHeight[GameTile];

if (RowEmpty <4) moveArray[count++] = (GameTile +5);//works out the current possible move
if (RowEmpty >0) moveArray[count++] = (GameTile -5);//to avoid unsolvable puzzles
if (colEmpty <4) moveArray[count++] = (GameTile +1);
if (colEmpty >0) moveArray[count++] = (GameTile -1);

int RandomIndex = arc4random()%count;
int RandomFrom = moveArray[RandomIndex];

boardOcc[EmptySq] = boardOcc[RandomFrom];
boardOcc[RandomFrom] = kEMPTY;

1 个答案:

答案 0 :(得分:1)

很少 - 如果没有多少可能性。

一种可能性是创建一个类似堆栈的缓冲区数组,它包含10个步骤。 (堆叠 - 从一端进入,从另一端出去)

例如:

NSMutableArray *_buffer = [NSMutableArray new];

所以 - 游戏开始,缓冲区数组为空。您生成第一个随机移动,并将其插入缓冲区数组:

[_buffer insertObject:[NSNumber numberWithInt:RandomIndex] atIndex:0];

然后检查我们的数组是否包含多于10个元素,如果是,则删除最后一个元素:

if([_buffer count] > 10)
{
    [_buffer removeObjectAtIndex:10];
}

我们只需删除一个项目,因为我们每次只添加一个对象。

然后我们添加检查,以便下一个'RandomIndex'将是除了前10个索引之外的其他内容。我们将'RandomIndex'设置为某个中性值(-1),然后启动while循环(将'RandomIndex'设置为某个随机值,第二次检查'_buffer'是否包含这样的值。如果它包含,它将重新生成' RandomIndex'并再次检查..它可以无限期地这样做,但如果'count'是一个更大的数字,那么它将需要2-3个while循环,无需担心。

int RandomIndex = -1;

while(RandomIndex == -1 || [_buffer containsObject:[NSNumber numberWithInt:RandomIndex]])
{
    RandomIndex = arc4random()%count;
}

但你可以添加一些安全性,以便在5个周期之后允许它突破循环:(但是它会保留重复值......)

int RandomIndex = -1;

int safetyCounter = 0;

while(RandomIndex == -1 || [_buffer containsObject:[NSNumber numberWithInt:RandomIndex]])
{
    RandomIndex = arc4random()%count;

    if(safetyCounter == 5)
    { 
        break;
    }

    safetyCounter++;
}

您还可以将缓冲区大小减小到-3或5,然后它将在99.9999999%的情况下完美地工作,甚至100%。只是为了禁用那种情况,当它随机时它会像你描述的那样每秒选择相同的数字。无论如何 - 不用担心。

但是仍然。让我们讨论另一种 - 更先进和更安全的方式。

其他可能性是创建两个单独的缓冲区。一个 - 如前例所示 - 将用于存储最后10个值,第二个将具有所有其他可能的唯一移动。

所以:

NSMutableArray *_buffer = [NSMutableArray new];
NSMutableArray *_allValues = [NSMutableArray new];

一开始'_buffer'为空,但对于'_allValues',我们添加了所有可能的动作:

for(int i = 0; i < count; i++)
{
    [_allValues addObject:[NSNumber numberWithInt:i]];
}

再次 - 当我们计算一个随机值时 - 我们将它添加到'_buffer'并从'_allValues'中删除

[_buffer insertObject:[NSNumber numberWithInt:RandomIndex] atIndex:0];
[_allValues removeObject:[NSNumber numberWithInt:RandomIndex]];

之后 - 我们再次检查_buffer是否大于10.如果是,我们删除最后一个对象,并添加回_allValues:

if([_buffer count] > 10)
{
    [_allValues addObject:[_buffer objectAtIndex:10]];

    [_buffer removeObjectAtIndex:10];
}

最重要的是 - 我们从_allValues的计数中计算'RandomIndex并获取相应对象的intValue:

RandomIndex = [[_allValues objectAtIndex:(arc4random()%[_allValues count])] intValue];

因此 - 我们不需要任何安全检查,因为这样,每次计算的值对于最后10次移动都是唯一的。

希望它有帮助..快乐的编码!