2015-01-03 17 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