2015-01-03 68 views
2

我目前有一个1600 x 1600的地图存储在MySQL(2,560,000条记录)中。我正在渲染一个简单的25x25地图给用户进行交互。用户可以在此地图上“声明”图块。我希望能够计算给定用户拥有的瓷砖的开放面数。我可以将其划分为所有瓷砖以确定任意有效性评级。PHP像素映射组效率

所有地图坐标都存储为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点,这是一个很大的负担。

任何帮助,非常感谢。

+0

我本来期望你的第三个例子是6个再次开放面,因为那些面孔2“共享” –

+0

这是什么使这一个独特的问题。这与你通常想象的不同。 – GameCharmer

回答

0

下面是我想出的确定地理效率的简单代码的最后一块。一些事物名称已经改变。 :P

我正在运行通知,所有的ajax,所以我决定去与单一的isset检查在多维而不是其他东西。

$sql = 'SELECT map_x, map_y FROM Map WHERE person_id = :person_id'; 
$query = $DB->prepare($sql); 
$query->execute(array(':nation_id' => $this->person_id)); 
$counter = 0; 
$coords = array(); 
while($row = $query->fetch()) 
{ 
    ++$counter; 
    $coords[$row['map_x']][$row['map_y']] = 1; 
} 
$faces = 0; 
foreach($coords as $x => $batch) 
{ 
    foreach($batch as $y => $junk) 
    { 
     $hits = 4; 
     if(isset($coords[$x + 1][$y])) 
     { 
      --$hits; 
     } 
     if(isset($coords[$x - 1][$y])) 
     { 
      --$hits; 
     } 
     if(isset($coords[$x][$y - 1])) 
     { 
      --$hits; 
     } 
     if(isset($coords[$x][$y + 1])) 
     { 
      --$hits; 
     } 
     $faces += $hits; 
    } 
} 
+0

我知道,而不是使用命中变量,我可以很容易地增加faces变量,但是还有一些额外的功能是在ifs之后添加的。 – GameCharmer

1

一种方法将涉及创建一个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 

然后,最后,提交一个COUNT查询“邻居”点来确定有多少人被其他用户占用并将其从总数中删除。

(注:我添加TODOS其中更多的工作是必须要做的)


这种方法的固有问题是,作为一个群体的增长,这将需要更长的时间才能算出来。

您应该考虑使用内存中的键值存储区,如Redis。但是,对于时间复杂度,查找时间(对于占用的块)在条目数方面看起来是线性的。

+0

当敲出点时,我将如何确定2个图块是否共享相同的开放图块以将其计为多个面?我会投入一些东西来看看我能否加快速度。我明天会发布我现在的解决方案。感谢Jacob的想法! – GameCharmer