我在滑动益智游戏中定位精灵,但我无法随机化平铺位置
如何检查是否已经进行了随机移动(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;
答案 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次移动都是唯一的。
希望它有帮助..快乐的编码!