我现在有一个1600 x 1600的地图存储在MySQL中(2560000条记录)。我正在向用户呈现一个简单的25x25地图以进行交互。用户可以在此地图上“认领”分幅。我希望能够计算给定用户拥有的瓷砖的开放面数。我可以把这个除以拥有的瓷砖总数来决定一个任意的效率等级。
所有地图坐标都简单地存储为X/Y值。
我正在寻找一种可能处理X/Y值数组并确定每个拥有的组可以访问多少个开放面的方法。例如。。。

0 = player
x x x x x
x x 0 x x
x x x x x
4 open faces

x x x x x
x x 0 x x
x x 0 x x
x x x x x
6 open faces

x x x x x
x x x 0 x
x x 0 x x
x x x x x
8 open faces

现在我正在做一些低效的数组循环来计算这个。我有一个简单的计数器,然后循环遍历所有值的数组,在X和Y的每个方向上寻找值+1来减少计数。每个循环根据查找的数目向总计数器添加0-4。这种方法的固有问题是,随着一个群体的成长,计算出来的时间会越来越长。因为一个团体有可能消耗20000点,这是一个相当大的负担。
任何帮助都非常感谢。

最佳答案

一种方法是创建一个Point类。例如:

class Point {
    public $x;
    public $y;

    public function __construct($x, $y){
        $this->x = $x;
        $this->y = $y;
    }

    public function getNeighbors(){
        // TODO: What if we are at the edge of the board?

        return array(
            new Point($x+1, $y+1),
            new Point($x+1, $y-1),
            new Point($x-1, $y+1),
            new Point($x-1, $y-1),
        );
    }
}

从该类为用户占用的每个点创建实例:
// Generate array of Points from database
$user_points = array(new Point(134, 245), new Point(146, 456));

遍历以生成所有邻居:
// Get a flat array of neighbor Points
$neighbors = array_merge(array_map(function($point){
    return $point->getNeighbors();
}, $user_points));

// TOOD: Remove Points that are equal to values in $user_points

然后,最后,提交一个“邻居”点的查询,以确定有多少用户被其他用户占用,并从总数中删除这些用户。
(注意:我添加了要做更多工作的todo。)
这种方法的固有问题是,随着一个群体的成长,计算出来的时间会越来越长。
您应该考虑使用内存中的键值存储,如Redis。但是,是的,查找时间(对于占用的块),在时间复杂度上,对于条目的数目而言是线性的。

10-05 22:19