Battlesnake – Map

Battlesnake N 部曲

  1. Battlesnake – Introduction
  2. Battlesnake – Map
  3. Battlesnake – Dead End
  4. Battlesnake – Hunger

知道遊戲基本規則後,就可以開始 Coding 囉,此系列文章中,會以我最熟悉的語言來做開發,也就是 PHP,並搭配 Lumen Framework 以省去一些繁瑣的事,這就開始吧!

用二維陣列來儲存地圖上的資訊是最簡單的方式,此外還會在地圖外再加上一圈圍牆,方便之後判斷是否走到邊界了,因此在 11×11 的地圖中,實際陣列會是 13×13,那麼開始製造地圖吧。

// 假設 $width 是收到的地圖大小,因還要加上圍牆,因此 for 結束條件須要 + 2
for ($i = 0; $i < $this->width + 2; ++$i) {
// $boundary 用來判斷現在是否是圍牆的上下邊界,圍牆左右邊界會在下面處理
$boundary = ($i === 0 || $i === ($this->width + 1));

// 實際對地圖填入數值
$this->data[$i] = array_fill(
0,
$this->width + 2, // +2 是為了圍牆
// 透過 helper method,以文字方式來代表此位置的值,藉此,就不需要特別去記 0 代表 wall,1 代表 space,2 代表 xxx
$boundary ? $this->mapping('wall') : $this->mapping('space')
);

// 因為 $boundary 只代表上下邊的圍牆,因此左右兩邊的圍牆就須另外在這處理
if (!$boundary) {
// 在上方 array_fill 中,已將一整列填滿 space,這會導致左右邊界也被當作空地,這會讓蛇離開地圖,因此在左右兩邊必須把 space 改成 wall
// 而這裡的 setMapContent 和上方 mapping 一樣是個 helper method,因此可以透過有意義的文字來設定地圖上各點所代表的含義
$this->setMapContent($i, 0, 'wall');
$this->setMapContent($i, $this->width + 1, 'wall');
}
}

// array_fill:https://secure.php.net/manual/en/function.array-fill.php

到此,已經製作出一張含有圍牆的將地圖囉,如果把地圖視覺話,目前的樣子如下:

圖中的 · 代表 space

接下來,在地圖上還有可能出現的就只有蛇和食物,而食物就是把一個點標記為食物,不需特別處理,因此接下來就說明蛇吧。

// $body 代表是蛇的身體資訊,這邊從尾巴開始處理而不是頭有特別含意,待會說明
for ($i = count($body) - 1; $i >= 0; --$i) {
// 因為地圖有一圈圍牆,因此這邊的 x 和 y 須加 1 才能對應到實際地圖上的位置
$x = $body[$i]['x'] + 1;
$y = $body[$i]['y'] + 1;

if ($i === 0) { // 蛇的頭
// 將此點標記為蛇頭
$this->setMapContent($x, $y, 'head');

// 此處會將敵人蛇頭的周圍三點設為危險區域,用於後續移動時的判斷,後續系列中將再提到
if ($enemy) {
$this->findAndSetDanger($x, $y, count($body));
}
} else if ($i === count($body) - 1) { // 蛇的尾巴
// 這邊就要提到為什麼是從尾巴開始,因為當吃到食物時,尾巴會停留一回合以用作延長身體,並且在 $body 中最後兩個的值會是一樣的,例如:[..., {x: 1, y: 2}, {x: 1, y: 2}]
// 如果我們是從蛇頭開始設點,那麼即會造成判斷錯誤,在延長的那回合,誤把蛇的身體當作蛇尾,進而造成追尾時的誤判
// 註:會不會發生這問題和寫法有關,因此如果你的寫法不一樣,可能不會有這問題
$this->setMapContent($x, $y, 'tail');
} else { // 蛇的身體
// 身體沒有特別要處理的地方,直接標記即可
$this->setMapContent($x, $y, 'body');
}
}

到此,地圖上所有資訊都已標記完,視覺化後如下:

  • :食物
  • ✦:蛇頭
  • :身體
  • :蛇尾
  • ▵:danger 區域

目前,地圖的已有初步資訊,雖然可以改善的地方很多,例如:區分蛇的身體,但已可以開始進行移動,因此下一章就會開始介紹簡單的移動策略啦!