在种子随机生成器中使用Timestemp作为种子,但输出始终相同

时间:2017-08-09 18:15:28

标签: javascript date random functional-programming

我开始制作一个创建随机新地下城的地下城游戏。因为我有seededRandom功能。从我的测试来看,这个功能是正确的。

function seededRandom (seed, min = 0, max = 1) {
  const random = ((seed * 9301 + 49297) % 233280) / 233280
  return min + random * (max - min)
}

它将在createDungeon函数内调用Date.now()作为seed的参数

function createDungeon(numberOfRooms, rooms = []) {
  ...
  const randomWidth = Math.floor(Generator.seededRandom(Date.now(), 10, 20))
  const randomHeight = Math.floor(Generator.seededRandom(Date.now(), 10, 20))
  const randomTopLeftCoordinate = Coordinate.create(
    Math.floor(Generator.seededRandom(Date.now(), 10, previousRoom.width)), // x position
    Math.floor(Generator.seededRandom(Date.now(), 10, previousRoom.height)) // y position
  )
  ...
}

在我的测试中,我记录了start timestempcreateDungeon return valueend timestemp,显然Date.now()还不够。

1502301604075 // start timestemp
[ 
  { width: 19, height: 19, topLeftCoordinate: { x: 18, y: 18 } },
  ...
  { width: 19, height: 19, topLeftCoordinate: { x: 18, y: 18 } },
  { width: 19, height: 19, topLeftCoordinate: { x: 18, y: 18 } } 
] 
1502301604075 // end timestemp

问题

我可以使用什么作为种子在每个对象中根据种子获得不同的值?

1 个答案:

答案 0 :(得分:1)

与上述评论一样:有几个种子随机数库,应该非常适合您的应用程序。我在我的例子中使用了this one

关键是在获取地牢的属性之前创建一个种子随机数生成器

const DungeonCreator = seed => {
  const rnd = new Math.seedrandom(seed);

  return nrOfRooms => ({
    width: inRange(rnd(), 0, 20),
    height: inRange(rnd(), 0, 20),
    topLeft: {
      x: inRange(rnd(), 0, 10),
      y: inRange(rnd(), 0, 10)
    },
    nrOfRooms
  })
}

此方法返回一个地牢生成器,每次调用它时都会为您提供一个新的地牢。 然而,使用相同种子创建的生成器将为您提供相同的地下城。

虽然不是“纯粹”,但它使代码可以测试。

const DungeonCreator = seed => {
  const rnd = new Math.seedrandom(seed);
  
  return nrOfRooms => ({
    width: inRange(rnd(), 0, 20),
    height: inRange(rnd(), 0, 20),
    topLeft: {
      x: inRange(rnd(), 0, 10),
      y: inRange(rnd(), 0, 10)
    },
    nrOfRooms
  })
}

const myDungeonCreator1 = DungeonCreator("seedOne");
const myDungeonCreator2 = DungeonCreator("seedTwo");
const myDungeonCreator3 = DungeonCreator("seedOne");

const roomSizes = [1, 3, 6, 3, 2, 6];

const dungeons1 = roomSizes.map(myDungeonCreator1);
const dungeons2 = roomSizes.map(myDungeonCreator2);
const dungeons3 = roomSizes.map(myDungeonCreator3);

console.log("Creator 1 & 3 created the same dungeons:",
  dungeonsEqual(dungeons1, dungeons3)
);

console.log("Creator 1 & 2 created the same dungeons:",
  dungeonsEqual(dungeons1, dungeons2)
);

console.log("Creator 2 & 3 created the same dungeons:",
  dungeonsEqual(dungeons2, dungeons3)
);


// Util
function inRange(value, min, max) {
  return min + Math.floor(value * (max - min));
};

function dungeonEqual(d1, d2) {
  return (
  d1.nrOfRooms === d2.nrOfRooms &&
  d1.width === d2.width &&
  d1.height === d2.height &&
  d1.topLeft.x === d2.topLeft.x &&
  d1.topLeft.y === d2.topLeft.y
  );
}

function dungeonsEqual(ds1, ds2) {
  return ds1.every((d, i) => dungeonEqual(d, ds2[i]));
};
<script src="//cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.3/seedrandom.min.js">
</script>