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



我开始制作一个随机创建新地下城的地下城游戏。在那里,我有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

问题

我可以使用什么作为种子在每个对象中基于种子的不同值?

就像提到的评论一样:有几个种子随机数库应该非常适合您的应用程序。我在我的示例中使用了这个。

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

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>

最新更新