【问题标题】:"Random-looking" sequence generator“随机外观”序列生成器
【发布时间】:2013-08-13 20:03:02
【问题描述】:

我想不出一个好的方法来做到这一点,如果可能的话,希望能得到一些帮助!

恐怕我还没有任何代码可以发布,因为我还没有到那一步。

我需要从 0-999 范围内的 3 个(或更多)参数生成一系列值。

对于给定的输入,该值必须始终相同,但在上下边界之间分布公平,以便显得随机。

例如:

function (1, 1, 1) = 423

function (1, 1, 2) = 716

function (1, 2, 1) = 112

这些必须相当快地生成,我的意思是我应该能够在网页加载期间生成 100-200 而没有明显的延迟。

该方法必须在 C# 和 JavaScript 中都可以使用,否则我可能会使用 CRC32 或 MD5 哈希算法。

如果有帮助,这将用作程序生成例程的一部分。

我之前曾尝试过问这个问题,但我认为我的解释质量差让我失望。

如果措辞不当,我深表歉意。如果是这样,请告诉我,我会尝试进一步解释。

非常感谢您的帮助。

【问题讨论】:

  • 您可能会使用Random 类,从而提供一个特定的种子值,您将基于输入的数字。也许从 3 个整数输入中构建一个散列以生成一个新整数然后您将其输入您的 new Random(seed) 实例。编辑:哦,JavaScript 也...没关系! :)
  • 是否需要 C# 和 JS 为相同的输入生成相同的输出?
  • 我理解你的问题......你需要做一些研究并实际尝试一些东西。查看种子随机数。 See herean example for random numbers in a range
  • 如果不出意外,你可以看看 perlin 噪声
  • 如果你想要的用途类似于@ChrisSinclair 解释的那样,你可以计算每个数字:number ^ positionand sum all the results。

标签: c# javascript procedural-generation


【解决方案1】:

这是一个:

function sequence(x, y, z) {
    return Math.abs(441*x-311*y+293*z) % 1000;
}

它甚至会从您的示例中生成输出!

【讨论】:

  • 嘿嘿,这可能不是最好的哈希函数,我只是想匹配给出的示例;)
  • 同意,但我喜欢 :)
【解决方案2】:

使用来自 Wiki 的 Marsaglia 生成器

public class SimpleMarsagliaRandom
{
    private const uint original_w = 1023;
    private uint m_w = original_w;    /* must not be zero */
    private uint m_z = 0;    /* must not be zero, initialized by the constructor */

    public SimpleMarsagliaRandom()
    {
        this.init(666);
    }

    public void init(uint z)
    {
        this.m_w = original_w;
        this.m_z = z;
    }

    public uint get_random()
    {
        this.m_z = 36969 * (this.m_z & 65535) + (this.m_z >> 16);
        this.m_w = 18000 * (this.m_w & 65535) + (this.m_w >> 16);
        return (this.m_z << 16) + this.m_w;  /* 32-bit result */
    }

    public uint get_random(uint min, uint max)
    {
        // max excluded
        uint num = max - min;
        return (this.get_random() % num) + min;
    }
}

simpleMarsagliaRandom = function() 
{
    var original_w = 1023 >>> 0;
    var m_w = 0, m_z = 0;

    this.init = function(z)
    {
        m_w = original_w;
        m_z = z >>> 0;
    };

    this.init(666);

    var internalRandom = function()
    {
        m_z = (36969 * (m_z & 65535) + (m_z >>> 16)) >>> 0;
        m_w = (18000 * (m_w & 65535) + (m_w >>> 16)) >>> 0;
        return (((m_z << 16) >>> 0) + m_w) >>> 0;  /* 32-bit result */
    };

    this.get_random = function(min, max)
    {
        if (arguments.length < 2)
        {
            return internalRandom();
        }

        var num = ((max >>> 0) - (min >>> 0)) >>> 0;
        return ((internalRandom() % num) + min) >>> 0;
    }    
};

在 Javascript 中,所有 &gt;&gt;&gt; 都将数字强制转换为 uint

完全未经测试

请注意,get_random 中将数字从 x 变为 y 的做法是错误的。低数字会比高数字发生的次数多一点。举个例子:假设你有一个标准的 6 面骰子。你滚动它,你得到1-6。现在假设您在其上打印数字 0-5。你滚动它,你得到0-5。没问题。但是您需要 0-3 范围内的数字。所以你确实滚动了 % 3... 所以我们有:

rolled => rolled % 3
0 => 0, 
1 => 1, 
2 => 2, 
3 => 0, 
4 => 1, 
5 => 2, 
6 => 0. 

0 结果更常见。

Ideone for C# 版本:http://ideone.com/VQudcV
Javascript 版本的 JSFiddle:http://jsfiddle.net/dqayk/

【讨论】:

  • 谢谢!将对此进行更多研究。
【解决方案3】:

您应该能够在 C# 和 JS 中使用 MD5 散列。

在 C# 中:

int Hash(params int[] values)
{
    System.Security.Cryptography.MD5 hasher = MD5.Create();
    string valuesAsString = string.Join(",", values);
    var hash = hasher.ComputeHash(Encoding.UTF8.GetBytes(valuesAsString));
    var hashAsInt = BitConverter.ToInt32(hash, 0);
    return Math.Abs(hashAsInt % 1000);
}

在 JS 中,使用一些 MD5 算法实现相同的方法(例如jshash

【讨论】:

    猜你喜欢
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多