1

我对编码非常陌生,并且正在从事我的第一个 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

3 回答 3

5

您可以对数组进行洗牌(例如,使用Fisher-Yates shuffle),然后在洗牌后的数组上一个接一个地进行迭代。当你到达一个结束时,只需再次洗牌。

于 2012-09-15T07:27:15.137 回答
1

I would create an additional index of the array that I could loop over to get references. This will create a constant random order of all elements in the array, that when having traversed all elements would reset to the first one and traverse again in the same order.

This method is compatible with a shuffled copy as well, such as is described in any other answer. And you can use a better shuffling algorithm, this one is naive. Since your arrays are so small however, the performance increase will be minimal. If you want to make a shuffled copy you won't need to map the index, you only need to create the copy when creating the object.

This code is not tested. I'm not sure about the interval of Math.random, but I'm assuming 0 < x < 1 here:

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;
}

Then you'd do something like 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' ...]

By the way, 'Archetype' might be a bad variable name. It looks like a function. I use 'archetype' here.

于 2012-09-15T09:48:28.447 回答
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);

参考

于 2012-09-15T08:39:44.373 回答