我正在尝试创建由PRNG程序生成的1和0的无限映射,但仅存储可查看的7x7网格。例如在屏幕上,你会看到一个7x7的网格,它显示了1和0的地图的一部分,当你向右推它时,然后将1和0移过并放置下一行到位。
如果然后向左移动,因为它是伪随机生成的,它会重新生成并显示原始图像。你将能够无限地向上和向下移动。
我遇到的问题是初始地图看起来不是随机的,当你向右或向左滚动时,模式会重复,我认为这与我如何生成数字有关。例如您可以从查看x = 5000和y = 10000开始,因此需要从这两个值生成唯一的种子。
(复杂性是视口大小的变量)
void CreateMap(){
if(complexity%2==0) {
complexity--;
}
if (randomseed) {
levelseed=Time.time.ToString();
}
psuedoRandom = new System.Random(levelseed.GetHashCode());
offsetx=psuedoRandom.Next();
offsety=psuedoRandom.Next();
levellocation=psuedoRandom.Next();
level = new int[complexity,complexity];
middle=complexity/2;
for (int x=0;x<complexity;x++){
for (int y=0;y<complexity;y++){
int hashme=levellocation+offsetx+x*offsety+y;
psuedoRandom = new System.Random(hashme.GetHashCode());
level[x,y]=psuedoRandom.Next(0,2);
}
}
}
这是我用于左右移动的内容,
void MoveRight(){
offsetx++;
for (int x=0;x<complexity-1;x++){
for (int y=0;y<complexity;y++){
level[x,y]=level[x+1,y];
}
}
for (int y=0;y<complexity;y++){
psuedoRandom = new System.Random(levellocation+offsetx*y);
level[complexity-1,y]=psuedoRandom.Next(0,2);
}
}
void MoveLeft(){
offsetx--;
for (int x=complexity-1;x>0;x--){
for (int y=0;y<complexity;y++){
level[x,y]=level[x-1,y];
}
}
for (int y=0;y<complexity;y++){
psuedoRandom = new System.Random(levellocation+offsetx*y);
level[0,y]=psuedoRandom.Next(0,2);
}
}
要提取它,我需要能够设置
等级[X,Y] = Returnrandom(OFFSETX,OFFSETY)
int RandomReturn(int x, int y){
psuedoRandom = new System.Random(Whatseedshouldiuse);
return (psuedoRandom.Next (0,2));
}
答案 0 :(得分:2)
我认为你的问题是你正在创造一个新的&#39;循环中随机...不要像你一样重新声明内部循环...而是在类级别声明它,然后简单地使用psuedoRandom.Next,例如见this SO post for an example of the issue you are experiencing
而不是像你一样在每次迭代时重新实例化一个Random()类:
for (int x=0;x<complexity;x++){
for (int y=0;y<complexity;y++){
int hashme=levellocation+offsetx+x*offsety+y;
psuedoRandom = new System.Random(hashme.GetHashCode());
level[x,y]=psuedoRandom.Next(0,2);
}
}
做更像
的事情for (int x=0;x<complexity;x++){
for (int y=0;y<complexity;y++){
// Give me the next random integer
moreRandom = psuedoRandom.Next();
}
}
编辑:正如Enigmativity在本文下面的评论中指出的那样,在每次迭代中重新定位也是浪费时间/资源。
P.S。如果你真的需要这样做,那么为什么不使用&#39;时间相关的默认种子值&#39;而不是指定一个?
答案 1 :(得分:0)
SipHash网站列出了两个C#实现:
答案 2 :(得分:0)
我发挥了一点作用来创建rnd(x, y, seed)
:
class Program
{
const int Min = -1000; // define the starting point
static void Main(string[] args)
{
for (int x = 0; x < 10; x++)
{
for (int y = 0; y < 10; y++)
Console.Write((RND(x, y, 123) % 100).ToString().PadLeft(4));
Console.WriteLine();
}
Console.ReadKey();
}
static int RND(int x, int y, int seed)
{
var rndX = new Random(seed);
var rndY = new Random(seed + 123); // a bit different
// because Random is LCG we can only move forward
for (int i = Min; i < x - 1; i++)
rndX.Next();
for (int i = Min; i < y - 1; i++)
rndY.Next();
// return some f(x, y, seed) = function(rnd(x, seed), rnd(y, seed))
return rndX.Next() + rndY.Next() << 1;
}
}
它有效,但是非常实现(因为Random
是LCG),它应该给出一个大致的想法。它的内存效率高(没有数组)。可接受的折衷方案是实现值缓存,然后在位于地图周围值的某些部分时,将从缓存中获取而不是生成。
对于相同的x
,y
和seed
,您将始终获得相同的值(反过来可以将其用作单元种子)。
TODO:找到一种方法,使Rnd(x)
和Rnd(y)
没有LCG,并且初始化效率非常低(带周期)。
答案 3 :(得分:0)
在你提出所有建议的方法之后,我用这个解决了它。
"$(arr[@]}"