根据正态分布给出的概率,在二维阵列中找到邻居

时间:2015-04-15 11:57:27

标签: arrays

我有一个代表我的世界的二次2D数组。每个单元格可以是空的或由玩家填充。 我想随机挑选一名球员让他与另一位球员互动。 第二个玩家应该根据2d正态分布概率来挑选,这意味着单元越接近应该选择它,阵列边界应该被包裹。

所以我正在搜索一个函数,该函数将播放器1的数组,x和y坐标以及正态分布的标准偏差(σx=σy)作为参数。它应该返回玩家2的x和y坐标。

另外,玩家可以产生新玩家,新玩家的位置应该通过上述相同的方法找到,但这次该函数应该返回空单元格的x和y。

感谢您的想法。

2 个答案:

答案 0 :(得分:1)

您可以创建一个辅助数组的玩家坐标,按照他们与玩家1的距离大小排序。根据您的分布函数生成一个随机数,该函数是辅助数组的索引。如果它是Player 1,则忽略结果,或者在生成它时从辅助数组中排除Player 1。

1) Create secondary array of x & y co-ordinate tuples.
2) For each element in primary array
    If element is not empty and element does not contain player 1
        add co-ordinates of the element to the secondary array
3) Sort secondary array by distance from player 1
    Where distance is the square root of 
    ((difference between player 1 x-coord and element x-coord) squared +
     (difference between player 1 y-coord and element y-coord) squared)
    And the difference is the greater minus the lesser 
        (since sign does not matter as it is being squared anyway).
4) Generate index into secondary array according to the distribution function.
5) Return the x and y coordinates from the element in the secondary array.

您可以使用Box-Muller Transform根据标准分布生成索引。

新玩家将被插入到辅助数组中(假设它在排序位置被实现为动态大小的列表或类似名称)。

答案 1 :(得分:0)

SST的迈克帮助了我的想法,Box-Muller变换让我走上寻找极地方法的正确轨道。

以下算法可以解决这个问题:

class Program
{
    static Random rnd = new Random();

    static void Neighbour(uint sx, uint sy, uint x, uint y, double std, out uint nx, out uint ny)
    {
        double u, v, q, p;
        do
        {
            u = rnd.NextDouble() * 2 - 1;
            v = rnd.NextDouble() * 2 - 1;
            q = u * u + v * v;
        } while (q == 0.0 || q >= 1.0);

        p = Math.Sqrt(-2 * Math.Log(q) / q) * std;

        nx = (uint)((Math.Round(u * p) % sx) + sx + x) % sx;
        ny = (uint)((Math.Round(v * p) % sy) + sy + y) % sy;
    }

    static void Main(string[] args)
    {
        const uint SX = 25;
        const uint SY = 35;

        const uint X = 7;
        const uint Y = 5;

        const double std = 4;

        uint nx, ny;

        const uint N = 100000;

        uint[,] arr = new uint[SY, SX];

        for (uint i = 0; i < N; i++)
        {
            Neighbour(SX, SY, X, Y, std, out nx, out ny);
            arr[ny, nx]++;
        }

        for (uint iy = 0; iy < SY; iy++)
        {
            for (uint ix = 0; ix < SX; ix++)
                Console.Write(arr[iy, ix].ToString().PadLeft(4));
            Console.WriteLine("");
        }

    }
}

我可以循环调用Neighbor,直到找到与玩家1坐标不同的坐标,并根据目的设置居住/无人居住。

# of times cell beeing chosen