数组中的随机数而不连续两次重复相同的数字?
Random number from an array without repeating the same number twice in a row?
我正在使用 Swift 和 SpriteKit 制作游戏,我将对象移动到基于数组的随机位置。
CGPoints组成的数组:
let easyArray = [CGPointMake(0,0), CGPointMake(126.6,0), CGPointMake(253.4,0), CGPointMake(0,197.5), CGPointMake(126.7,197.5), CGPointMake(253.4,197.5), CGPointMake(0,395), CGPointMake(126.7,395), CGPointMake(253.4,395)]
我用这个函数生成一个随机数:
func randomNumber(maximum: UInt32) -> Int {
var randomNumber = arc4random_uniform(maximum)
while previousNumber == randomNumber {
randomNumber = arc4random_uniform(maximum)
}
previousNumber = randomNumber
return Int(randomNumber)
}
我用它根据生成的随机数移动对象:
let greenEasy = randomNumberNew(9)
let moveSelector = SKAction.moveTo(easyArray[greenEasy], duration: 0)
selector.runAction(moveSelector)
我在网上做了一些阅读,发现 "While" 条件应该可以使相同的随机数不会连续生成两次。但它仍然发生。
任何人都可以帮助我如何做到这一点,这样我就不会连续两次得到相同的数字吗?
下面的代码不会随机生成相同的数字。
var currentNo: UInt32 = 0
func randomNumber(maximum: UInt32) -> Int {
var randomNumber: UInt32
do {
randomNumber = (arc4random_uniform(maximum))
}while currentNo == randomNumber
currentNo = randomNumber
return Int(randomNumber)
}
我觉得 其实很聪明。
easyArray.append(easyArray.removeAtIndex(Int(arc4random_uniform(UInt32(easyArray.count)-1))))
selector.runAction(SKAction.moveTo(easyArray.last!, duration: 0))
我建议不要将 while() 循环与随机化器一起使用。
从理论上讲,在最坏的情况下它会导致无限循环,在更积极的情况下它只需要几个循环就可以得到想要的结果。
相反,我会建议制作一个包含所有值的 NSArray,从这个 NSArray 中删除最后一个随机化元素,并从这样的数组中随机化任何其他现有元素 - 这是仅在一次随机化迭代后的保证结果。
在Objective-C中创建NSArray类别即可轻松实现:
- (id) randomARC4Element
{
if(self.count > 0)
{
return [self objectAtIndex:[self randomIntBetweenMin:0 andMax:self.count-1]];
}
return nil;
}
- (int)randomIntBetweenMin:(int)minValue andMax:(int)maxValue
{
return (int)(minValue + [self randomFloat] * (maxValue - minValue));
}
- (float)randomFloat
{
return (float) arc4random() / UINT_MAX;
}
如果您可以使用 linq,那么您可以 select 一个与上一个值不匹配的随机值。然后对于任何剩余的值,您可以遍历并找到插入它们的有效位置。
它不是最有效的,但它确实有效。
public static List<int> Randomize(List<int> reps, int lastId) {
var rand = new Random();
var newReps = new List<int>();
var tempReps = new List<int>();
tempReps.AddRange(reps);
while (tempReps.Any(x => x != lastId)) {
var validReps = tempReps.FindAll(x => x != lastId);
var i = rand.Next(0, validReps.Count - 1);
newReps.Add(validReps[i]);
lastId = validReps[i];
tempReps.Remove(validReps[i]);
}
while (tempReps.Any()) {
var tempRep = tempReps.First();
bool placed = false;
for (int i = 0; i < newReps.Count; i++) {
if (newReps[i] == tempRep) {
continue;
}
else if ((i < newReps.Count - 1) && (newReps[i + 1] == tempRep)) {
continue;
}
else {
newReps.Insert(i + 1, tempRep);
placed = true;
break;
}
}
if (placed) {
tempReps.Remove(tempRep);
}
else {
throw new Exception("Unable to randomize reps");
}
}
return newReps;
}
我正在使用 Swift 和 SpriteKit 制作游戏,我将对象移动到基于数组的随机位置。
CGPoints组成的数组:
let easyArray = [CGPointMake(0,0), CGPointMake(126.6,0), CGPointMake(253.4,0), CGPointMake(0,197.5), CGPointMake(126.7,197.5), CGPointMake(253.4,197.5), CGPointMake(0,395), CGPointMake(126.7,395), CGPointMake(253.4,395)]
我用这个函数生成一个随机数:
func randomNumber(maximum: UInt32) -> Int {
var randomNumber = arc4random_uniform(maximum)
while previousNumber == randomNumber {
randomNumber = arc4random_uniform(maximum)
}
previousNumber = randomNumber
return Int(randomNumber)
}
我用它根据生成的随机数移动对象:
let greenEasy = randomNumberNew(9)
let moveSelector = SKAction.moveTo(easyArray[greenEasy], duration: 0)
selector.runAction(moveSelector)
我在网上做了一些阅读,发现 "While" 条件应该可以使相同的随机数不会连续生成两次。但它仍然发生。
任何人都可以帮助我如何做到这一点,这样我就不会连续两次得到相同的数字吗?
下面的代码不会随机生成相同的数字。
var currentNo: UInt32 = 0
func randomNumber(maximum: UInt32) -> Int {
var randomNumber: UInt32
do {
randomNumber = (arc4random_uniform(maximum))
}while currentNo == randomNumber
currentNo = randomNumber
return Int(randomNumber)
}
我觉得
easyArray.append(easyArray.removeAtIndex(Int(arc4random_uniform(UInt32(easyArray.count)-1))))
selector.runAction(SKAction.moveTo(easyArray.last!, duration: 0))
我建议不要将 while() 循环与随机化器一起使用。
从理论上讲,在最坏的情况下它会导致无限循环,在更积极的情况下它只需要几个循环就可以得到想要的结果。
相反,我会建议制作一个包含所有值的 NSArray,从这个 NSArray 中删除最后一个随机化元素,并从这样的数组中随机化任何其他现有元素 - 这是仅在一次随机化迭代后的保证结果。
在Objective-C中创建NSArray类别即可轻松实现:
- (id) randomARC4Element
{
if(self.count > 0)
{
return [self objectAtIndex:[self randomIntBetweenMin:0 andMax:self.count-1]];
}
return nil;
}
- (int)randomIntBetweenMin:(int)minValue andMax:(int)maxValue
{
return (int)(minValue + [self randomFloat] * (maxValue - minValue));
}
- (float)randomFloat
{
return (float) arc4random() / UINT_MAX;
}
如果您可以使用 linq,那么您可以 select 一个与上一个值不匹配的随机值。然后对于任何剩余的值,您可以遍历并找到插入它们的有效位置。
它不是最有效的,但它确实有效。
public static List<int> Randomize(List<int> reps, int lastId) {
var rand = new Random();
var newReps = new List<int>();
var tempReps = new List<int>();
tempReps.AddRange(reps);
while (tempReps.Any(x => x != lastId)) {
var validReps = tempReps.FindAll(x => x != lastId);
var i = rand.Next(0, validReps.Count - 1);
newReps.Add(validReps[i]);
lastId = validReps[i];
tempReps.Remove(validReps[i]);
}
while (tempReps.Any()) {
var tempRep = tempReps.First();
bool placed = false;
for (int i = 0; i < newReps.Count; i++) {
if (newReps[i] == tempRep) {
continue;
}
else if ((i < newReps.Count - 1) && (newReps[i + 1] == tempRep)) {
continue;
}
else {
newReps.Insert(i + 1, tempRep);
placed = true;
break;
}
}
if (placed) {
tempReps.Remove(tempRep);
}
else {
throw new Exception("Unable to randomize reps");
}
}
return newReps;
}