2012-09-15 102 views
1

我对编码和开发第一个Javascript项目非常陌生。我试图创建一个随机选择一个设置的小型随机字符生成器,​​以及两个数组中的字符原型。我的问题是我不断得到重复,可能是由于列表的小尺寸。防止随机操作在Javascript中返回两次相同的值

<html> 
<head> 
<script type="text/javascript"> 

    var setting=new Array('Steampunk', 
         'Fuedal Japanese', 
         'Post Apocalyptic', 
         'Horror', 
         'Fantasy', 
         'Cyberpunk', 
         'Western', 
         'Pulp', 
         'Military', 
         'Space Opera', 
         'Medieval', 
         'Ancient', 
         'Mythological', 
         'Urban', 
         'Trans-Humanist', 
         'Renaissance', 
         'Dystopian', 
         'Retro Futuristic', 
         'Nordic', 
         'Colonial'); 

    var Archetype=new Array('Ninja', 
          'Samurai', 
          'Viking', 
          'Cowboy', 
          'Rogue', 
          'Wizard', 
          'Wrestler/Luchador', 
          'Knight', 
          'Scientist', 
          'Gadgeteer', 
          'Druid', 
          'Performer', 
          'Pirate', 
          'Alien', 
          'Superhero/Villain', 
          'Robot', 
          'Soldier', 
          'Vampire', 
          'Werewolf', 
          'Bounty Hunter'); 

    function resetSettingAndArchetype() 
    { 
    var whichsetting = Math.floor(Math.random()*(setting.length)); 
    var whicharchetype = Math.floor(Math.random()*(Archetype.length)); 

如何获得随机操作永不会返回相同的值两次?

回答

4

您可以对数组进行混洗(例如,使用Fisher-Yates shuffle),然后在混洗阵列上逐个迭代。当你到达一个结尾时,只需再洗一次。

+0

我想在这里添加一件事。如果你想保留原始数组,然后创建原始数组的副本,然后使用复制的数组进行混洗。 – Anoop

+0

Fisher-Yates可用于高效地初始化阵列(制作混洗副本)或执行就地洗牌。 – nneonneo

1

您可以使用下面的方法洗牌:

function shuffle(o){ //v1.0 
    for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); 
    return o; 
}; 
shuffle(setting); 
shuffle(Archetype); 

reference

1

我想创建数组的一个额外的指标,我可以遍历得到引用。这将创建数组中所有元素的随机顺序,当遍历所有元素时,将重置为第一个元素,并以相同的顺序再次遍历。

此方法也与混洗副本兼容,如其他任何答案中所述。你可以使用更好的洗牌算法,这个算法很幼稚。由于您的阵列非常小,因此性能提升会很小。如果要制作混洗副本,则不需要映射索引,只需在创建对象时创建副本。

此代码未经测试。我不知道有关的Math.random的间隔,但我在这里假设0 < x < 1

var RandomWalk = function(items) { 
    var self = this; 
    if (!items.length) { 
    // throw some error 
    } 

    this.index = 0; 
    this.index_map = (function(items) { 
    var map = [], i = 0; 
    while(map.length < items.length) { 
     i = Math.floor(Math.random() * items.length); 
     if (map.indexOf(i) === -1) { 
     map.push(i); 
     } 
    } 
    return map; 
    })(items); // Note that this function is evaluated, index_map is not a function 
    this.index_max = this.index_map.length - 1; 
    this.next = function() { 
    var r = self.index_map[self.index]; 
    if (self.index == self.index_max) { 
     self.index = 0; 
    } else { 
     self.index += 1; 
    } 
    return r; 
    } 
    return this; 
} 

然后你会做这样的事情:

// define settings and archetype 
var archetype_walk = new RandomWalk(archetype); 
function resetSettingAndArchetype() 
{ 
    ... 
    var arch_index = archetype_walk.next(), 
     arch = archetypes[arch_index] 
    // arch is in ['Ninja', 'Samurai', 'Druid' ...] 

顺便说一句,“原型”可能是一个不好的变量名称。它看起来像一个功能。我在这里使用'archetype'。

相关问题