if (PHP 是一種易於使用、易於學習且可以廣泛獲取的編程語言。它非常適合開發在各種遊戲中可以使用的簡單腳本。無論是一個人玩簡單的使用紙和筆的遊戲,還是同一群人玩複雜的桌面角色扮演遊戲,或者任意類型的聯機遊戲,本系列都提供了適合您的內容。本文將在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 基礎上,探究可以在各種類型的遊戲中使用的 10 個中級腳本。這些腳本適用於三種遊戲:角色扮演遊戲、機率遊戲和文字遊戲。 在本系列的 第 1 部分 中,您創建了一些初學者級別的 PHP 腳本。現在是時候提高要求來增加一些複雜度,進一步拓展您的 PHP 編程技能並提高您作為遊戲專家的地位。 對於角色扮演遊戲腳本,您將了解如何整合武器的破壞力計算器、特徵表統計跟蹤器及非玩家角色(Non-Player Character,NPC)生成器,同時教您如何將信息保存到文件中以及如何與 PHP 中的數組結合使用。與機率遊戲相關的腳本將幫助您練習 Blackjack,學習如何算牌,並且快速了解 Bingo(一種賭博遊戲)的基本規則,同時教您如何將機率元素插入到 PHP 腳本中。最後,文字遊戲腳本將幫助您解決 Jumble 遊戲,創建簡單的置換計算程序,並生成文字搜索圖,同時讓您的 PHP 數組處理技能更上一層樓。 我們將快速地介紹這些腳本,而不會討論如何查找主機或設置伺服器。有很多 Web 託管公司提供 PHP,並且如果需要安裝自己的 PHP,XAMPP 安裝程序使用起來也十分簡單。我們將不會花費大量時間談論 PHP 最佳實踐或遊戲設計技術。本文介紹的腳本易於理解、使用簡單並可以快速掌握。 本文的 代碼歸檔 包含所討論的每個腳本的完整源代碼,並且可以訪問 Chaoticneutral.net 查看腳本實際運行情況。 破壞力計算器 在 第 1 部分中,我們構建了一個基本的擲骰器。讓我們查看一下如何使用該擲骰器幫助整合基本的破壞力計算器。 如果您曾經運行或者玩過桌面角色扮演遊戲,則可能已經看到過書中附帶的大型武器圖表。通常,這些圖表包括武器名稱及武器的破壞力有多大。它可能類似表 1 中所示的內容。 表 1. 破壞力計算器 武器名稱 | 破壞力 | Little Stick | 1d6 | Big Stick | 1d6+4 | Chainsaw | 2d8 | 您應當能夠得到在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 中創建的簡單 roll 函數,並且使用它計算一套基本武器的破壞力。為此,需要創建一個數組來保存關於武器的信息。 對於本例,一個武器有三個基本特性:名稱(Name)、擲骰(Die Roll)和傷害獎勵(Damage Bonus)。使用這些特性,您可以構建武器數組,如下所示: 清單 1. 武器數組 $weapons = array ( 'littlestick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '0', ), 'bigstick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '4', ), 'chainsaw' => array ( 'name' => 'Little Stick', 'roll' => '2d8', 'bonus' => '0', ), ); | 使用此數組,您可以構建一張顯示武器、武器的破壞力及傷害判定結果表。 清單 2. 構建武器表 foreach ($weapons as $weapon) { list($count, $sides) = explode('d', $weapon['roll']); $result = 0; for ($i = 0; $i < $count;$i++) { $result = $result + roll($sides); } echo "<tr><td>" . $weapon['name'] . "</td><td>" . $weapon['roll']; if ($weapon['bonus'] > 0) { echo "+" . $weapon['bonus']; $result = $result + $weapon['bonus']; } echo "</td><td>" . $result . "</td></tr>"; } | 使用此腳本,您可以用集成的破壞力計算器創建基本武器圖。
統計跟蹤 現在已經可以計算破壞力,讓我們查看如何跟蹤一些基本任務統計信息,這種功能在要運行帶有多個 NPC 的遊戲時可能需要使用。創建一個簡單數組來保存人物信息並將其另存(序列化)為文本文件(將這些信息保存到資料庫中有許多方法,並且在您逐漸熟悉如何使用 PHP 后應當保存到資料庫)。對於本例,您將通過我編寫的名為 Shambles 的遊戲創建一個基本的怪物角色。首先建立一個數組以保存角色信息。 清單 3. 角色信息數組 $character = array( 'name' => 'Fred The Zombie', 'health' => '36', 'gore' => '1', 'clutch' => '5', 'brawn' => '6', 'sense' => '4', 'flail' => '2', 'chuck' => '3', 'lurch' => '4', ); | 需要生成文件名以保存這些信息。實際上不需要在傳入時就使用輸入,但是只可以使用人物姓名中的字母創建文件。 清單 4. 創建用於存儲信息的文件 $filename = substr(preg_replace("/[^a-z0-9]/", "", strtolower($character['name'])), 0, 20); file_put_contents($filename, serialize($character)); | 註:在將該腳本提供給公共使用時,需要過濾用戶輸入以避免有人將錯誤的 JavaScript 代碼或垃圾代碼惡意插入文件中。這只是供您個人使用的示例。最後,需要用表單表示信息以便可以輕鬆更新。這隻需使用輸入欄位中的默認值創建一張表單。 清單 5. 用表單顯示信息 <input name='health' value='<?php echo $character['health'] ?>' /> | 使用此基本腳本(請參閱 代碼歸檔)跟蹤幾個角色和 NPC。
NPC 生成器 在整合一個大型遊戲時,擁有一個一次性的 NPC 池十分有用。如果需要大量暴徒或者士兵,這樣做尤其有幫助。要整合 NPC 生成器,讓我們構建一個包含構造角色規則的數組,然後使用隨機姓名生成器及擲骰器一次性整合一批角色。 使用 Fred the Zombie 作為示例,您可以定義創建角色的規則。某些統計信息是固定的(生命力總是從 36 開始),某些統計信息是派生的(血=生命力/6),而某些統計信息是擲骰的結果(離合器是 1d6 — 一個六面骰子)。規則類似清單 6 中所示的內容。 清單 6. 定義角色創建的規則 $rules = array( 'health' => '36', 'gore' => 'health/6', 'clutch' => '1d6', 'brawn' => '1d6', 'sense' => '1d6', 'flail' => '1d6', 'chuck' => '1d6', 'lurch' => '1d6', ); | 現在您可以編寫少量代碼來評估規則。 清單 7. 評估規則的代碼 foreach ($rules as $stat=>$rule) { if (preg_match("/^[0-9]+$/", $rule)) { // This is only a number, and is therefore a static value $character[$stat] = $rule; } else if (preg_match("/^([0-9]+)d([0-9]+)/", $rule, $matches)) { // This is a die roll $val = 0; for ($n = 0;$n<$matches[1];$n++) { $val = $val + roll($matches[2]); } $character[$stat] = $val; } else if (preg_match("/^([a-z]+)\/([0-9]+)$/", $rule, $matches)) { // This is a derived value of some kind. $character[$stat] = $character[$matches[1]] / $matches[2]; } echo $stat . ' : ' . $character[$stat] . "<br />\n"; } | 在正確評估規則時,您可以引入使用隨機姓名生成器生成的隨機姓名並且一連幾天製作 NPC。請查看 代碼歸檔 中的腳本了解如何整合該任務。
機率計算器:擲骰 在 第 1 部分 中,您整合了一個簡單的機率計算器以確定從給定的一副牌中抽到指定牌面或花色的機率。現在讓我們構建一個擲骰機率計算器。對於本例,您將構建一個在擲兩個六面骰子(2d6)時確定可能結果的計算器。如果使用的是基於 d6 的任何 RPG 系統,玩大富豪或雙陸棋之類的棋盤類遊戲,或者要嘗試在諸如 Craps 之類的骰子遊戲中計算出機率,這將十分有用。 首先,建立在擲兩個骰子時確定可能結果的方法。可以考慮擲兩個不同顏色的骰子(如一個紅色骰子和一個藍色骰子)。如果擲紅色骰子的結果為 1,則有六個可能的結果,每個結果取決於藍色骰子的一面。這意味著可能的擲骰結果總數為 6^2 即 36 個結果。這可能看似有些奇怪,因為您實際上可以得到的最高值為 12(紅色六點加藍色六點),但是如果您認識到可以通過兩個不同的結果得到 11(紅色六點加藍色五點,或者紅色五點加藍色六點)應當更有意義。 讓我們假定,在本例中,您需要同時獲得總和(擲出 10)和骰面(擲出 6 和 4)結果,並且紅色骰子的 6 點與藍色骰子的 6 點沒有差別。重要的數字為 S(骰子面數)和 N(骰子個數)— 假定有 N 個相同的骰子,最大結果數為 S^N — 可是這其中的一些結果可能相同(一個 6 和一個 4,以及一個 4 和一個 6)。 清單 8. 構建擲骰機率計算器 $s = 6; $n = 2; $results = array(array()); for ($i = 0; $i < $n; $i ++) { $newresults = array(); foreach ($results as $result) { for ($x = 0; $x < $s; $x++) { $newresults[] = array_merge($result, array($x+1)); } } $results = $newresults; } | 這可能看似有些沉悶。您可以適當地簡化這段代碼,但是我已經在這裡完成了一些更明顯的操作,因此您可以了解數組是如何處理的。在構建完最終數組后,您可以迭代數組並生成骰子數總和的列表及其各自的機率。這段代碼包含在 代碼歸檔 中。
簡單的 Blackjack 撲克發牌器 在 第 1 部分 中,您構建了一個簡單的撲克發牌器。該發牌器不是真正地在與您玩牌;它只是發出牌盒中的牌,從而允許您開始各種牌局。現在讓我們構建一個真正與您玩牌的 Blackjack 發牌器。使用發牌器必須至少抽到 17 的簡單內部規則構建此發牌器。 這部分代碼將類似先前構建的簡單的撲克發牌器。對於 Blackjack,您需要以迭代抽取及牌局評估的形式構建。您將需要一個把牌面值指定為數字描述的數組。如果更改構建牌組的方法,您可以在原始的 $faces 數組中完成此操作。 清單 9. 修改 Blackjack 的 $faces 數組 $faces = array('Two' => 2, ... ... ... 'King' => 10, 'Ace' => 11); | 然後您需要一個基本函數來評估給定的牌局。該函數將查看手中的牌並返回手上的牌面總值。 清單 10. 評估給定牌局的函數 function evaluateHand($hand) { global $faces; $value = 0; foreach ($hand as $card) { if ($value > 11 && $card['face'] == 'Ace') { $value = $value + 1; // An ace can be 11 or 1 } else { $value = intval($value) + intval($faces[$card['face']]); } } return $value; } | 在評估手上牌局的函數就緒后,應當很容易確定您手上的牌是否超過 21 點,或者發牌器是否應當要牌。有關如何整合所有這些內容的詳細信息,請參閱 代碼歸檔。
牌面計算器 在玩 Blackjack 或者諸如紅心大戰之類基於王牌的遊戲時,知道如何算牌會十分有用。在玩 Blackjack 時,至少需要知道已經看到多少張 A 和花牌。對於紅心大戰,您可能需要知道遊戲中還有多少王牌。您將構建一個 Blackjack 基本計算器。您可以採用相同原理構建王牌遊戲的牌面計算器。 您將構建以略微不同的方式進行計算的牌組。您不必知道所有牌 — 只關注自己感興趣的牌。對於單牌組牌盒,則類似如下所示: 清單 11. 構建單牌組牌盒的牌面計算器 $deck = array ( 'faces' => 16, // 10,J,Q,K * 4 suits 'aces' => 4, // One per suit 'other' => 32, // 52 - (16 + 4) ); | 接下來,構建一張帶有三個按鈕的表單 — 一個用於花牌,一個用於 A,而另一個用於其他牌。通過在每次看到特定類型的牌時單擊相應按鈕,您可以調整留在牌組中的牌。 清單 12. 帶有三個按鈕的簡單表單 然後通過查看修改後的牌組,可以計算抽到花牌、A 或其他牌的機率。 清單 13. 計算抽到花牌、A 或其他牌的機率 echo "Odds of pulling a face: " . $deck['faces'] . " out of " . $deck['faces'] + $deck['aces'] + $deck['other']; | 使用這個基本牌面計算器作為起點,您可以構建一些更健壯的程序。
Bingo 引擎 基於我們在本文中已經完成的內容,您可以輕鬆地整合一個 Bingo 引擎以生成牌並從池中抽出編號。 Bingo 編號範圍從 1 到 75,以 15 個編號為一組(1-15 分配給 B,16-30 分配給 I 等等)。按照構建並洗一副虛擬牌的相同方法,您可以構建並洗一套虛擬的 Bingo 球。但是您無需以相同方法跟蹤牌面和花色。首先,構建基本編號集。 清單 14. 構建 Bingo 的基本編號集 for ($i = 1; $i < 16; $i++) { $numbers['B'][] = $i; $numbers['I'][] = $i+15; $numbers['N'][] = $i+30; $numbers['G'][] = $i+45; $numbers['O'][] = $i+60; } | 接下來,您可以置換每個子數組並且同時製作牌(不要忘記:中間的部分通常是一張任意的牌)。完成後,創建一個可用作牌組的主數組。 清單 15. 創建主數組 $letters = array ('B','I','N','G','O'); foreach ($letters as $letter) { shuffle($numbers[$letter]); $chunks = array_chunk($numbers[$letter], 5); $cards[$i][$letter] = $chunks[0]; if ($letter == 'N') { $cards[$i][$letter][2] = ' '; // Free Space } shuffle($balls); } | 現在已經全部完成!分發牌,並開始從主集合中抽取虛擬 Bingo 球,就像先前抽牌所做的那樣。在 代碼歸檔 中可以找到此腳本的完整運行版本。
Jumble 助手 Jumble 是在大多數報紙中可以找到的字謎,您有一些已經完全混合在一起的單詞。您必須從廢話中提取出實際單詞來,然後使用某些字母來創造新短語。從在 第 1 部分 中創建的縱橫字謎助手開始,讓我們整合一個快速腳本以幫助您構建 Jumble。 首先,打開單詞列表。需要遍歷該列表,將每個單詞拆分為經過排序的字母數組,然後再次合併數組。例如,這樣做將把單詞 “COLOR” 改為字元串 “CLOOR”;該字元串表示單詞 “COLOR” 中的所有字母,但是按照可預測的(而且更重要的是相配的)順序。該字元串隨後將被用作匹配單詞的數組的關鍵字。它必須為數組,因為 “sword” 和 “words” 擁有完全相同的字母,但是順序不同。最後,它將類似如下所示的內容: 清單 16. Jumble 的腳本 foreach ($words as $word) { $arr = str_split($word); sort($arr); $key = implode('', $arr); if (isset($lookup[$key])) { array_push($lookup[$key], $word); } else { $lookup[$key] = array($word); } } | 完成到此為止的程序后,只需將 Jumble 像任何其他單詞一樣處理,查找相應關鍵字的值並輸出所有結果。 清單 17. 完成 Jumble 腳本 $arr = str_split(PHP 是一種易於使用、易於學習且可以廣泛獲取的編程語言。它非常適合開發在各種遊戲中可以使用的簡單腳本。無論是一個人玩簡單的使用紙和筆的遊戲,還是同一群人玩複雜的桌面角色扮演遊戲,或者任意類型的聯機遊戲,本系列都提供了適合您的內容。本文將在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 基礎上,探究可以在各種類型的遊戲中使用的 10 個中級腳本。這些腳本適用於三種遊戲:角色扮演遊戲、機率遊戲和文字遊戲。 在本系列的 第 1 部分 中,您創建了一些初學者級別的 PHP 腳本。現在是時候提高要求來增加一些複雜度,進一步拓展您的 PHP 編程技能並提高您作為遊戲專家的地位。 對於角色扮演遊戲腳本,您將了解如何整合武器的破壞力計算器、特徵表統計跟蹤器及非玩家角色(Non-Player Character,NPC)生成器,同時教您如何將信息保存到文件中以及如何與 PHP 中的數組結合使用。與機率遊戲相關的腳本將幫助您練習 Blackjack,學習如何算牌,並且快速了解 Bingo(一種賭博遊戲)的基本規則,同時教您如何將機率元素插入到 PHP 腳本中。最後,文字遊戲腳本將幫助您解決 Jumble 遊戲,創建簡單的置換計算程序,並生成文字搜索圖,同時讓您的 PHP 數組處理技能更上一層樓。 我們將快速地介紹這些腳本,而不會討論如何查找主機或設置伺服器。有很多 Web 託管公司提供 PHP,並且如果需要安裝自己的 PHP,XAMPP 安裝程序使用起來也十分簡單。我們將不會花費大量時間談論 PHP 最佳實踐或遊戲設計技術。本文介紹的腳本易於理解、使用簡單並可以快速掌握。 本文的 代碼歸檔 包含所討論的每個腳本的完整源代碼,並且可以訪問 Chaoticneutral.net 查看腳本實際運行情況。 破壞力計算器 在 第 1 部分中,我們構建了一個基本的擲骰器。讓我們查看一下如何使用該擲骰器幫助整合基本的破壞力計算器。 如果您曾經運行或者玩過桌面角色扮演遊戲,則可能已經看到過書中附帶的大型武器圖表。通常,這些圖表包括武器名稱及武器的破壞力有多大。它可能類似表 1 中所示的內容。 表 1. 破壞力計算器 武器名稱 | 破壞力 | Little Stick | 1d6 | Big Stick | 1d6+4 | Chainsaw | 2d8 | 您應當能夠得到在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 中創建的簡單 roll 函數,並且使用它計算一套基本武器的破壞力。為此,需要創建一個數組來保存關於武器的信息。 對於本例,一個武器有三個基本特性:名稱(Name)、擲骰(Die Roll)和傷害獎勵(Damage Bonus)。使用這些特性,您可以構建武器數組,如下所示: 清單 1. 武器數組 $weapons = array ( 'littlestick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '0', ), 'bigstick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '4', ), 'chainsaw' => array ( 'name' => 'Little Stick', 'roll' => '2d8', 'bonus' => '0', ), ); | 使用此數組,您可以構建一張顯示武器、武器的破壞力及傷害判定結果表。 清單 2. 構建武器表 foreach ($weapons as $weapon) { list($count, $sides) = explode('d', $weapon['roll']); $result = 0; for ($i = 0; $i < $count;$i++) { $result = $result + roll($sides); } echo "<tr><td>" . $weapon['name'] . "</td><td>" . $weapon['roll']; if ($weapon['bonus'] > 0) { echo "+" . $weapon['bonus']; $result = $result + $weapon['bonus']; } echo "</td><td>" . $result . "</td></tr>"; } | 使用此腳本,您可以用集成的破壞力計算器創建基本武器圖。
統計跟蹤 現在已經可以計算破壞力,讓我們查看如何跟蹤一些基本任務統計信息,這種功能在要運行帶有多個 NPC 的遊戲時可能需要使用。創建一個簡單數組來保存人物信息並將其另存(序列化)為文本文件(將這些信息保存到資料庫中有許多方法,並且在您逐漸熟悉如何使用 PHP 后應當保存到資料庫)。對於本例,您將通過我編寫的名為 Shambles 的遊戲創建一個基本的怪物角色。首先建立一個數組以保存角色信息。 清單 3. 角色信息數組 $character = array( 'name' => 'Fred The Zombie', 'health' => '36', 'gore' => '1', 'clutch' => '5', 'brawn' => '6', 'sense' => '4', 'flail' => '2', 'chuck' => '3', 'lurch' => '4', ); | 需要生成文件名以保存這些信息。實際上不需要在傳入時就使用輸入,但是只可以使用人物姓名中的字母創建文件。 清單 4. 創建用於存儲信息的文件 $filename = substr(preg_replace("/[^a-z0-9]/", "", strtolower($character['name'])), 0, 20); file_put_contents($filename, serialize($character)); | 註:在將該腳本提供給公共使用時,需要過濾用戶輸入以避免有人將錯誤的 JavaScript 代碼或垃圾代碼惡意插入文件中。這只是供您個人使用的示例。最後,需要用表單表示信息以便可以輕鬆更新。這隻需使用輸入欄位中的默認值創建一張表單。 清單 5. 用表單顯示信息 <input name='health' value='<?php echo $character['health'] ?>' /> | 使用此基本腳本(請參閱 代碼歸檔)跟蹤幾個角色和 NPC。
NPC 生成器 在整合一個大型遊戲時,擁有一個一次性的 NPC 池十分有用。如果需要大量暴徒或者士兵,這樣做尤其有幫助。要整合 NPC 生成器,讓我們構建一個包含構造角色規則的數組,然後使用隨機姓名生成器及擲骰器一次性整合一批角色。 使用 Fred the Zombie 作為示例,您可以定義創建角色的規則。某些統計信息是固定的(生命力總是從 36 開始),某些統計信息是派生的(血=生命力/6),而某些統計信息是擲骰的結果(離合器是 1d6 — 一個六面骰子)。規則類似清單 6 中所示的內容。 清單 6. 定義角色創建的規則 $rules = array( 'health' => '36', 'gore' => 'health/6', 'clutch' => '1d6', 'brawn' => '1d6', 'sense' => '1d6', 'flail' => '1d6', 'chuck' => '1d6', 'lurch' => '1d6', ); | 現在您可以編寫少量代碼來評估規則。 清單 7. 評估規則的代碼 foreach ($rules as $stat=>$rule) { if (preg_match("/^[0-9]+$/", $rule)) { // This is only a number, and is therefore a static value $character[$stat] = $rule; } else if (preg_match("/^([0-9]+)d([0-9]+)/", $rule, $matches)) { // This is a die roll $val = 0; for ($n = 0;$n<$matches[1];$n++) { $val = $val + roll($matches[2]); } $character[$stat] = $val; } else if (preg_match("/^([a-z]+)\/([0-9]+)$/", $rule, $matches)) { // This is a derived value of some kind. $character[$stat] = $character[$matches[1]] / $matches[2]; } echo $stat . ' : ' . $character[$stat] . "<br />\n"; } | 在正確評估規則時,您可以引入使用隨機姓名生成器生成的隨機姓名並且一連幾天製作 NPC。請查看 代碼歸檔 中的腳本了解如何整合該任務。
機率計算器:擲骰 在 第 1 部分 中,您整合了一個簡單的機率計算器以確定從給定的一副牌中抽到指定牌面或花色的機率。現在讓我們構建一個擲骰機率計算器。對於本例,您將構建一個在擲兩個六面骰子(2d6)時確定可能結果的計算器。如果使用的是基於 d6 的任何 RPG 系統,玩大富豪或雙陸棋之類的棋盤類遊戲,或者要嘗試在諸如 Craps 之類的骰子遊戲中計算出機率,這將十分有用。 首先,建立在擲兩個骰子時確定可能結果的方法。可以考慮擲兩個不同顏色的骰子(如一個紅色骰子和一個藍色骰子)。如果擲紅色骰子的結果為 1,則有六個可能的結果,每個結果取決於藍色骰子的一面。這意味著可能的擲骰結果總數為 6^2 即 36 個結果。這可能看似有些奇怪,因為您實際上可以得到的最高值為 12(紅色六點加藍色六點),但是如果您認識到可以通過兩個不同的結果得到 11(紅色六點加藍色五點,或者紅色五點加藍色六點)應當更有意義。 讓我們假定,在本例中,您需要同時獲得總和(擲出 10)和骰面(擲出 6 和 4)結果,並且紅色骰子的 6 點與藍色骰子的 6 點沒有差別。重要的數字為 S(骰子面數)和 N(骰子個數)— 假定有 N 個相同的骰子,最大結果數為 S^N — 可是這其中的一些結果可能相同(一個 6 和一個 4,以及一個 4 和一個 6)。 清單 8. 構建擲骰機率計算器 $s = 6; $n = 2; $results = array(array()); for ($i = 0; $i < $n; $i ++) { $newresults = array(); foreach ($results as $result) { for ($x = 0; $x < $s; $x++) { $newresults[] = array_merge($result, array($x+1)); } } $results = $newresults; } | 這可能看似有些沉悶。您可以適當地簡化這段代碼,但是我已經在這裡完成了一些更明顯的操作,因此您可以了解數組是如何處理的。在構建完最終數組后,您可以迭代數組並生成骰子數總和的列表及其各自的機率。這段代碼包含在 代碼歸檔 中。
簡單的 Blackjack 撲克發牌器 在 第 1 部分 中,您構建了一個簡單的撲克發牌器。該發牌器不是真正地在與您玩牌;它只是發出牌盒中的牌,從而允許您開始各種牌局。現在讓我們構建一個真正與您玩牌的 Blackjack 發牌器。使用發牌器必須至少抽到 17 的簡單內部規則構建此發牌器。 這部分代碼將類似先前構建的簡單的撲克發牌器。對於 Blackjack,您需要以迭代抽取及牌局評估的形式構建。您將需要一個把牌面值指定為數字描述的數組。如果更改構建牌組的方法,您可以在原始的 $faces 數組中完成此操作。 清單 9. 修改 Blackjack 的 $faces 數組 $faces = array('Two' => 2, ... ... ... 'King' => 10, 'Ace' => 11); | 然後您需要一個基本函數來評估給定的牌局。該函數將查看手中的牌並返回手上的牌面總值。 清單 10. 評估給定牌局的函數 function evaluateHand($hand) { global $faces; $value = 0; foreach ($hand as $card) { if ($value > 11 && $card['face'] == 'Ace') { $value = $value + 1; // An ace can be 11 or 1 } else { $value = intval($value) + intval($faces[$card['face']]); } } return $value; } | 在評估手上牌局的函數就緒后,應當很容易確定您手上的牌是否超過 21 點,或者發牌器是否應當要牌。有關如何整合所有這些內容的詳細信息,請參閱 代碼歸檔。
牌面計算器 在玩 Blackjack 或者諸如紅心大戰之類基於王牌的遊戲時,知道如何算牌會十分有用。在玩 Blackjack 時,至少需要知道已經看到多少張 A 和花牌。對於紅心大戰,您可能需要知道遊戲中還有多少王牌。您將構建一個 Blackjack 基本計算器。您可以採用相同原理構建王牌遊戲的牌面計算器。 您將構建以略微不同的方式進行計算的牌組。您不必知道所有牌 — 只關注自己感興趣的牌。對於單牌組牌盒,則類似如下所示: 清單 11. 構建單牌組牌盒的牌面計算器 $deck = array ( 'faces' => 16, // 10,J,Q,K * 4 suits 'aces' => 4, // One per suit 'other' => 32, // 52 - (16 + 4) ); | 接下來,構建一張帶有三個按鈕的表單 — 一個用於花牌,一個用於 A,而另一個用於其他牌。通過在每次看到特定類型的牌時單擊相應按鈕,您可以調整留在牌組中的牌。 清單 12. 帶有三個按鈕的簡單表單 if (PHP 是一種易於使用、易於學習且可以廣泛獲取的編程語言。它非常適合開發在各種遊戲中可以使用的簡單腳本。無論是一個人玩簡單的使用紙和筆的遊戲,還是同一群人玩複雜的桌面角色扮演遊戲,或者任意類型的聯機遊戲,本系列都提供了適合您的內容。本文將在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 基礎上,探究可以在各種類型的遊戲中使用的 10 個中級腳本。這些腳本適用於三種遊戲:角色扮演遊戲、機率遊戲和文字遊戲。 在本系列的 第 1 部分 中,您創建了一些初學者級別的 PHP 腳本。現在是時候提高要求來增加一些複雜度,進一步拓展您的 PHP 編程技能並提高您作為遊戲專家的地位。 對於角色扮演遊戲腳本,您將了解如何整合武器的破壞力計算器、特徵表統計跟蹤器及非玩家角色(Non-Player Character,NPC)生成器,同時教您如何將信息保存到文件中以及如何與 PHP 中的數組結合使用。與機率遊戲相關的腳本將幫助您練習 Blackjack,學習如何算牌,並且快速了解 Bingo(一種賭博遊戲)的基本規則,同時教您如何將機率元素插入到 PHP 腳本中。最後,文字遊戲腳本將幫助您解決 Jumble 遊戲,創建簡單的置換計算程序,並生成文字搜索圖,同時讓您的 PHP 數組處理技能更上一層樓。 我們將快速地介紹這些腳本,而不會討論如何查找主機或設置伺服器。有很多 Web 託管公司提供 PHP,並且如果需要安裝自己的 PHP,XAMPP 安裝程序使用起來也十分簡單。我們將不會花費大量時間談論 PHP 最佳實踐或遊戲設計技術。本文介紹的腳本易於理解、使用簡單並可以快速掌握。 本文的 代碼歸檔 包含所討論的每個腳本的完整源代碼,並且可以訪問 Chaoticneutral.net 查看腳本實際運行情況。 破壞力計算器 在 第 1 部分中,我們構建了一個基本的擲骰器。讓我們查看一下如何使用該擲骰器幫助整合基本的破壞力計算器。 如果您曾經運行或者玩過桌面角色扮演遊戲,則可能已經看到過書中附帶的大型武器圖表。通常,這些圖表包括武器名稱及武器的破壞力有多大。它可能類似表 1 中所示的內容。 表 1. 破壞力計算器 武器名稱 | 破壞力 | Little Stick | 1d6 | Big Stick | 1d6+4 | Chainsaw | 2d8 | 您應當能夠得到在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 中創建的簡單 roll 函數,並且使用它計算一套基本武器的破壞力。為此,需要創建一個數組來保存關於武器的信息。 對於本例,一個武器有三個基本特性:名稱(Name)、擲骰(Die Roll)和傷害獎勵(Damage Bonus)。使用這些特性,您可以構建武器數組,如下所示: 清單 1. 武器數組 $weapons = array ( 'littlestick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '0', ), 'bigstick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '4', ), 'chainsaw' => array ( 'name' => 'Little Stick', 'roll' => '2d8', 'bonus' => '0', ), ); | 使用此數組,您可以構建一張顯示武器、武器的破壞力及傷害判定結果表。 清單 2. 構建武器表 foreach ($weapons as $weapon) { list($count, $sides) = explode('d', $weapon['roll']); $result = 0; for ($i = 0; $i < $count;$i++) { $result = $result + roll($sides); } echo "<tr><td>" . $weapon['name'] . "</td><td>" . $weapon['roll']; if ($weapon['bonus'] > 0) { echo "+" . $weapon['bonus']; $result = $result + $weapon['bonus']; } echo "</td><td>" . $result . "</td></tr>"; } | 使用此腳本,您可以用集成的破壞力計算器創建基本武器圖。
統計跟蹤 現在已經可以計算破壞力,讓我們查看如何跟蹤一些基本任務統計信息,這種功能在要運行帶有多個 NPC 的遊戲時可能需要使用。創建一個簡單數組來保存人物信息並將其另存(序列化)為文本文件(將這些信息保存到資料庫中有許多方法,並且在您逐漸熟悉如何使用 PHP 后應當保存到資料庫)。對於本例,您將通過我編寫的名為 Shambles 的遊戲創建一個基本的怪物角色。首先建立一個數組以保存角色信息。 清單 3. 角色信息數組 $character = array( 'name' => 'Fred The Zombie', 'health' => '36', 'gore' => '1', 'clutch' => '5', 'brawn' => '6', 'sense' => '4', 'flail' => '2', 'chuck' => '3', 'lurch' => '4', ); | 需要生成文件名以保存這些信息。實際上不需要在傳入時就使用輸入,但是只可以使用人物姓名中的字母創建文件。 清單 4. 創建用於存儲信息的文件 $filename = substr(preg_replace("/[^a-z0-9]/", "", strtolower($character['name'])), 0, 20); file_put_contents($filename, serialize($character)); | 註:在將該腳本提供給公共使用時,需要過濾用戶輸入以避免有人將錯誤的 JavaScript 代碼或垃圾代碼惡意插入文件中。這只是供您個人使用的示例。最後,需要用表單表示信息以便可以輕鬆更新。這隻需使用輸入欄位中的默認值創建一張表單。 清單 5. 用表單顯示信息 <input name='health' value='<?php echo $character['health'] ?>' /> | 使用此基本腳本(請參閱 代碼歸檔)跟蹤幾個角色和 NPC。
NPC 生成器 在整合一個大型遊戲時,擁有一個一次性的 NPC 池十分有用。如果需要大量暴徒或者士兵,這樣做尤其有幫助。要整合 NPC 生成器,讓我們構建一個包含構造角色規則的數組,然後使用隨機姓名生成器及擲骰器一次性整合一批角色。 使用 Fred the Zombie 作為示例,您可以定義創建角色的規則。某些統計信息是固定的(生命力總是從 36 開始),某些統計信息是派生的(血=生命力/6),而某些統計信息是擲骰的結果(離合器是 1d6 — 一個六面骰子)。規則類似清單 6 中所示的內容。 清單 6. 定義角色創建的規則 $rules = array( 'health' => '36', 'gore' => 'health/6', 'clutch' => '1d6', 'brawn' => '1d6', 'sense' => '1d6', 'flail' => '1d6', 'chuck' => '1d6', 'lurch' => '1d6', ); | 現在您可以編寫少量代碼來評估規則。 清單 7. 評估規則的代碼 foreach ($rules as $stat=>$rule) { if (preg_match("/^[0-9]+$/", $rule)) { // This is only a number, and is therefore a static value $character[$stat] = $rule; } else if (preg_match("/^([0-9]+)d([0-9]+)/", $rule, $matches)) { // This is a die roll $val = 0; for ($n = 0;$n<$matches[1];$n++) { $val = $val + roll($matches[2]); } $character[$stat] = $val; } else if (preg_match("/^([a-z]+)\/([0-9]+)$/", $rule, $matches)) { // This is a derived value of some kind. $character[$stat] = $character[$matches[1]] / $matches[2]; } echo $stat . ' : ' . $character[$stat] . "<br />\n"; } | 在正確評估規則時,您可以引入使用隨機姓名生成器生成的隨機姓名並且一連幾天製作 NPC。請查看 代碼歸檔 中的腳本了解如何整合該任務。
機率計算器:擲骰 在 第 1 部分 中,您整合了一個簡單的機率計算器以確定從給定的一副牌中抽到指定牌面或花色的機率。現在讓我們構建一個擲骰機率計算器。對於本例,您將構建一個在擲兩個六面骰子(2d6)時確定可能結果的計算器。如果使用的是基於 d6 的任何 RPG 系統,玩大富豪或雙陸棋之類的棋盤類遊戲,或者要嘗試在諸如 Craps 之類的骰子遊戲中計算出機率,這將十分有用。 首先,建立在擲兩個骰子時確定可能結果的方法。可以考慮擲兩個不同顏色的骰子(如一個紅色骰子和一個藍色骰子)。如果擲紅色骰子的結果為 1,則有六個可能的結果,每個結果取決於藍色骰子的一面。這意味著可能的擲骰結果總數為 6^2 即 36 個結果。這可能看似有些奇怪,因為您實際上可以得到的最高值為 12(紅色六點加藍色六點),但是如果您認識到可以通過兩個不同的結果得到 11(紅色六點加藍色五點,或者紅色五點加藍色六點)應當更有意義。 讓我們假定,在本例中,您需要同時獲得總和(擲出 10)和骰面(擲出 6 和 4)結果,並且紅色骰子的 6 點與藍色骰子的 6 點沒有差別。重要的數字為 S(骰子面數)和 N(骰子個數)— 假定有 N 個相同的骰子,最大結果數為 S^N — 可是這其中的一些結果可能相同(一個 6 和一個 4,以及一個 4 和一個 6)。 清單 8. 構建擲骰機率計算器 $s = 6; $n = 2; $results = array(array()); for ($i = 0; $i < $n; $i ++) { $newresults = array(); foreach ($results as $result) { for ($x = 0; $x < $s; $x++) { $newresults[] = array_merge($result, array($x+1)); } } $results = $newresults; } | 這可能看似有些沉悶。您可以適當地簡化這段代碼,但是我已經在這裡完成了一些更明顯的操作,因此您可以了解數組是如何處理的。在構建完最終數組后,您可以迭代數組並生成骰子數總和的列表及其各自的機率。這段代碼包含在 代碼歸檔 中。
簡單的 Blackjack 撲克發牌器 在 第 1 部分 中,您構建了一個簡單的撲克發牌器。該發牌器不是真正地在與您玩牌;它只是發出牌盒中的牌,從而允許您開始各種牌局。現在讓我們構建一個真正與您玩牌的 Blackjack 發牌器。使用發牌器必須至少抽到 17 的簡單內部規則構建此發牌器。 這部分代碼將類似先前構建的簡單的撲克發牌器。對於 Blackjack,您需要以迭代抽取及牌局評估的形式構建。您將需要一個把牌面值指定為數字描述的數組。如果更改構建牌組的方法,您可以在原始的 $faces 數組中完成此操作。 清單 9. 修改 Blackjack 的 $faces 數組 $faces = array('Two' => 2, ... ... ... 'King' => 10, 'Ace' => 11); | 然後您需要一個基本函數來評估給定的牌局。該函數將查看手中的牌並返回手上的牌面總值。 清單 10. 評估給定牌局的函數 function evaluateHand($hand) { global $faces; $value = 0; foreach ($hand as $card) { if ($value > 11 && $card['face'] == 'Ace') { $value = $value + 1; // An ace can be 11 or 1 } else { $value = intval($value) + intval($faces[$card['face']]); } } return $value; } | 在評估手上牌局的函數就緒后,應當很容易確定您手上的牌是否超過 21 點,或者發牌器是否應當要牌。有關如何整合所有這些內容的詳細信息,請參閱 代碼歸檔。
牌面計算器 在玩 Blackjack 或者諸如紅心大戰之類基於王牌的遊戲時,知道如何算牌會十分有用。在玩 Blackjack 時,至少需要知道已經看到多少張 A 和花牌。對於紅心大戰,您可能需要知道遊戲中還有多少王牌。您將構建一個 Blackjack 基本計算器。您可以採用相同原理構建王牌遊戲的牌面計算器。 您將構建以略微不同的方式進行計算的牌組。您不必知道所有牌 — 只關注自己感興趣的牌。對於單牌組牌盒,則類似如下所示: 清單 11. 構建單牌組牌盒的牌面計算器 $deck = array ( 'faces' => 16, // 10,J,Q,K * 4 suits 'aces' => 4, // One per suit 'other' => 32, // 52 - (16 + 4) ); | 接下來,構建一張帶有三個按鈕的表單 — 一個用於花牌,一個用於 A,而另一個用於其他牌。通過在每次看到特定類型的牌時單擊相應按鈕,您可以調整留在牌組中的牌。 清單 12. 帶有三個按鈕的簡單表單 然後通過查看修改後的牌組,可以計算抽到花牌、A 或其他牌的機率。 清單 13. 計算抽到花牌、A 或其他牌的機率 echo "Odds of pulling a face: " . $deck['faces'] . " out of " . $deck['faces'] + $deck['aces'] + $deck['other']; | 使用這個基本牌面計算器作為起點,您可以構建一些更健壯的程序。
Bingo 引擎 基於我們在本文中已經完成的內容,您可以輕鬆地整合一個 Bingo 引擎以生成牌並從池中抽出編號。 Bingo 編號範圍從 1 到 75,以 15 個編號為一組(1-15 分配給 B,16-30 分配給 I 等等)。按照構建並洗一副虛擬牌的相同方法,您可以構建並洗一套虛擬的 Bingo 球。但是您無需以相同方法跟蹤牌面和花色。首先,構建基本編號集。 清單 14. 構建 Bingo 的基本編號集 for ($i = 1; $i < 16; $i++) { $numbers['B'][] = $i; $numbers['I'][] = $i+15; $numbers['N'][] = $i+30; $numbers['G'][] = $i+45; $numbers['O'][] = $i+60; } | 接下來,您可以置換每個子數組並且同時製作牌(不要忘記:中間的部分通常是一張任意的牌)。完成後,創建一個可用作牌組的主數組。 清單 15. 創建主數組 $letters = array ('B','I','N','G','O'); foreach ($letters as $letter) { shuffle($numbers[$letter]); $chunks = array_chunk($numbers[$letter], 5); $cards[$i][$letter] = $chunks[0]; if ($letter == 'N') { $cards[$i][$letter][2] = ' '; // Free Space } shuffle($balls); } | 現在已經全部完成!分發牌,並開始從主集合中抽取虛擬 Bingo 球,就像先前抽牌所做的那樣。在 代碼歸檔 中可以找到此腳本的完整運行版本。
Jumble 助手 Jumble 是在大多數報紙中可以找到的字謎,您有一些已經完全混合在一起的單詞。您必須從廢話中提取出實際單詞來,然後使用某些字母來創造新短語。從在 第 1 部分 中創建的縱橫字謎助手開始,讓我們整合一個快速腳本以幫助您構建 Jumble。 首先,打開單詞列表。需要遍歷該列表,將每個單詞拆分為經過排序的字母數組,然後再次合併數組。例如,這樣做將把單詞 “COLOR” 改為字元串 “CLOOR”;該字元串表示單詞 “COLOR” 中的所有字母,但是按照可預測的(而且更重要的是相配的)順序。該字元串隨後將被用作匹配單詞的數組的關鍵字。它必須為數組,因為 “sword” 和 “words” 擁有完全相同的字母,但是順序不同。最後,它將類似如下所示的內容: 清單 16. Jumble 的腳本 foreach ($words as $word) { $arr = str_split($word); sort($arr); $key = implode('', $arr); if (isset($lookup[$key])) { array_push($lookup[$key], $word); } else { $lookup[$key] = array($word); } } | 完成到此為止的程序后,只需將 Jumble 像任何其他單詞一樣處理,查找相應關鍵字的值並輸出所有結果。 清單 17. 完成 Jumble 腳本 您可以在 代碼歸檔 中看到如何將這些內容整合在一起。
置換密碼 置換密碼 是一種簡單的加密技術,採用這項技術將把字母表中的每個字母替換為字母表中的其他字母。按照現代加密技術的標準,置換密碼簡直就是小兒科。但是簡單的置換密碼玩起來很有趣,尤其是在 RPG 環境中給某個人傳遞一條可以在玩遊戲的過程中破解出來的編碼信息。 首先從 第 1 部分 的 Hangman 生成器中偷一些代碼 — 也就是,字母數組。製作另外一份數組副本,攪亂該副本,並構建一個聯合數組,其中原來的字母將獲得重組后的值。 清單 18. 修改字母數組 $letters = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p', 'q','r','s','t','u','v','w','x','y','z'); $code = $letters; shuffle($code); $key = array_combine($letters, $code); | 接下來,獲取 $_POST 中的輸入,將消息拆分為字母,然後將每個字母的值輸出到密鑰中。 清單 19. 分隔並輸出字母 if (!empty(PHP 是一種易於使用、易於學習且可以廣泛獲取的編程語言。它非常適合開發在各種遊戲中可以使用的簡單腳本。無論是一個人玩簡單的使用紙和筆的遊戲,還是同一群人玩複雜的桌面角色扮演遊戲,或者任意類型的聯機遊戲,本系列都提供了適合您的內容。本文將在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 基礎上,探究可以在各種類型的遊戲中使用的 10 個中級腳本。這些腳本適用於三種遊戲:角色扮演遊戲、機率遊戲和文字遊戲。 在本系列的 第 1 部分 中,您創建了一些初學者級別的 PHP 腳本。現在是時候提高要求來增加一些複雜度,進一步拓展您的 PHP 編程技能並提高您作為遊戲專家的地位。 對於角色扮演遊戲腳本,您將了解如何整合武器的破壞力計算器、特徵表統計跟蹤器及非玩家角色(Non-Player Character,NPC)生成器,同時教您如何將信息保存到文件中以及如何與 PHP 中的數組結合使用。與機率遊戲相關的腳本將幫助您練習 Blackjack,學習如何算牌,並且快速了解 Bingo(一種賭博遊戲)的基本規則,同時教您如何將機率元素插入到 PHP 腳本中。最後,文字遊戲腳本將幫助您解決 Jumble 遊戲,創建簡單的置換計算程序,並生成文字搜索圖,同時讓您的 PHP 數組處理技能更上一層樓。 我們將快速地介紹這些腳本,而不會討論如何查找主機或設置伺服器。有很多 Web 託管公司提供 PHP,並且如果需要安裝自己的 PHP,XAMPP 安裝程序使用起來也十分簡單。我們將不會花費大量時間談論 PHP 最佳實踐或遊戲設計技術。本文介紹的腳本易於理解、使用簡單並可以快速掌握。 本文的 代碼歸檔 包含所討論的每個腳本的完整源代碼,並且可以訪問 Chaoticneutral.net 查看腳本實際運行情況。 破壞力計算器 在 第 1 部分中,我們構建了一個基本的擲骰器。讓我們查看一下如何使用該擲骰器幫助整合基本的破壞力計算器。 如果您曾經運行或者玩過桌面角色扮演遊戲,則可能已經看到過書中附帶的大型武器圖表。通常,這些圖表包括武器名稱及武器的破壞力有多大。它可能類似表 1 中所示的內容。 表 1. 破壞力計算器 武器名稱 | 破壞力 | Little Stick | 1d6 | Big Stick | 1d6+4 | Chainsaw | 2d8 | 您應當能夠得到在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 中創建的簡單 roll 函數,並且使用它計算一套基本武器的破壞力。為此,需要創建一個數組來保存關於武器的信息。 對於本例,一個武器有三個基本特性:名稱(Name)、擲骰(Die Roll)和傷害獎勵(Damage Bonus)。使用這些特性,您可以構建武器數組,如下所示: 清單 1. 武器數組 $weapons = array ( 'littlestick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '0', ), 'bigstick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '4', ), 'chainsaw' => array ( 'name' => 'Little Stick', 'roll' => '2d8', 'bonus' => '0', ), ); | 使用此數組,您可以構建一張顯示武器、武器的破壞力及傷害判定結果表。 清單 2. 構建武器表 foreach ($weapons as $weapon) { list($count, $sides) = explode('d', $weapon['roll']); $result = 0; for ($i = 0; $i < $count;$i++) { $result = $result + roll($sides); } echo "<tr><td>" . $weapon['name'] . "</td><td>" . $weapon['roll']; if ($weapon['bonus'] > 0) { echo "+" . $weapon['bonus']; $result = $result + $weapon['bonus']; } echo "</td><td>" . $result . "</td></tr>"; } | 使用此腳本,您可以用集成的破壞力計算器創建基本武器圖。
統計跟蹤 現在已經可以計算破壞力,讓我們查看如何跟蹤一些基本任務統計信息,這種功能在要運行帶有多個 NPC 的遊戲時可能需要使用。創建一個簡單數組來保存人物信息並將其另存(序列化)為文本文件(將這些信息保存到資料庫中有許多方法,並且在您逐漸熟悉如何使用 PHP 后應當保存到資料庫)。對於本例,您將通過我編寫的名為 Shambles 的遊戲創建一個基本的怪物角色。首先建立一個數組以保存角色信息。 清單 3. 角色信息數組 $character = array( 'name' => 'Fred The Zombie', 'health' => '36', 'gore' => '1', 'clutch' => '5', 'brawn' => '6', 'sense' => '4', 'flail' => '2', 'chuck' => '3', 'lurch' => '4', ); | 需要生成文件名以保存這些信息。實際上不需要在傳入時就使用輸入,但是只可以使用人物姓名中的字母創建文件。 清單 4. 創建用於存儲信息的文件 $filename = substr(preg_replace("/[^a-z0-9]/", "", strtolower($character['name'])), 0, 20); file_put_contents($filename, serialize($character)); | 註:在將該腳本提供給公共使用時,需要過濾用戶輸入以避免有人將錯誤的 JavaScript 代碼或垃圾代碼惡意插入文件中。這只是供您個人使用的示例。最後,需要用表單表示信息以便可以輕鬆更新。這隻需使用輸入欄位中的默認值創建一張表單。 清單 5. 用表單顯示信息 <input name='health' value='<?php echo $character['health'] ?>' /> | 使用此基本腳本(請參閱 代碼歸檔)跟蹤幾個角色和 NPC。
NPC 生成器 在整合一個大型遊戲時,擁有一個一次性的 NPC 池十分有用。如果需要大量暴徒或者士兵,這樣做尤其有幫助。要整合 NPC 生成器,讓我們構建一個包含構造角色規則的數組,然後使用隨機姓名生成器及擲骰器一次性整合一批角色。 使用 Fred the Zombie 作為示例,您可以定義創建角色的規則。某些統計信息是固定的(生命力總是從 36 開始),某些統計信息是派生的(血=生命力/6),而某些統計信息是擲骰的結果(離合器是 1d6 — 一個六面骰子)。規則類似清單 6 中所示的內容。 清單 6. 定義角色創建的規則 $rules = array( 'health' => '36', 'gore' => 'health/6', 'clutch' => '1d6', 'brawn' => '1d6', 'sense' => '1d6', 'flail' => '1d6', 'chuck' => '1d6', 'lurch' => '1d6', ); | 現在您可以編寫少量代碼來評估規則。 清單 7. 評估規則的代碼 foreach ($rules as $stat=>$rule) { if (preg_match("/^[0-9]+$/", $rule)) { // This is only a number, and is therefore a static value $character[$stat] = $rule; } else if (preg_match("/^([0-9]+)d([0-9]+)/", $rule, $matches)) { // This is a die roll $val = 0; for ($n = 0;$n<$matches[1];$n++) { $val = $val + roll($matches[2]); } $character[$stat] = $val; } else if (preg_match("/^([a-z]+)\/([0-9]+)$/", $rule, $matches)) { // This is a derived value of some kind. $character[$stat] = $character[$matches[1]] / $matches[2]; } echo $stat . ' : ' . $character[$stat] . "<br />\n"; } | 在正確評估規則時,您可以引入使用隨機姓名生成器生成的隨機姓名並且一連幾天製作 NPC。請查看 代碼歸檔 中的腳本了解如何整合該任務。
機率計算器:擲骰 在 第 1 部分 中,您整合了一個簡單的機率計算器以確定從給定的一副牌中抽到指定牌面或花色的機率。現在讓我們構建一個擲骰機率計算器。對於本例,您將構建一個在擲兩個六面骰子(2d6)時確定可能結果的計算器。如果使用的是基於 d6 的任何 RPG 系統,玩大富豪或雙陸棋之類的棋盤類遊戲,或者要嘗試在諸如 Craps 之類的骰子遊戲中計算出機率,這將十分有用。 首先,建立在擲兩個骰子時確定可能結果的方法。可以考慮擲兩個不同顏色的骰子(如一個紅色骰子和一個藍色骰子)。如果擲紅色骰子的結果為 1,則有六個可能的結果,每個結果取決於藍色骰子的一面。這意味著可能的擲骰結果總數為 6^2 即 36 個結果。這可能看似有些奇怪,因為您實際上可以得到的最高值為 12(紅色六點加藍色六點),但是如果您認識到可以通過兩個不同的結果得到 11(紅色六點加藍色五點,或者紅色五點加藍色六點)應當更有意義。 讓我們假定,在本例中,您需要同時獲得總和(擲出 10)和骰面(擲出 6 和 4)結果,並且紅色骰子的 6 點與藍色骰子的 6 點沒有差別。重要的數字為 S(骰子面數)和 N(骰子個數)— 假定有 N 個相同的骰子,最大結果數為 S^N — 可是這其中的一些結果可能相同(一個 6 和一個 4,以及一個 4 和一個 6)。 清單 8. 構建擲骰機率計算器 $s = 6; $n = 2; $results = array(array()); for ($i = 0; $i < $n; $i ++) { $newresults = array(); foreach ($results as $result) { for ($x = 0; $x < $s; $x++) { $newresults[] = array_merge($result, array($x+1)); } } $results = $newresults; } | 這可能看似有些沉悶。您可以適當地簡化這段代碼,但是我已經在這裡完成了一些更明顯的操作,因此您可以了解數組是如何處理的。在構建完最終數組后,您可以迭代數組並生成骰子數總和的列表及其各自的機率。這段代碼包含在 代碼歸檔 中。
簡單的 Blackjack 撲克發牌器 在 第 1 部分 中,您構建了一個簡單的撲克發牌器。該發牌器不是真正地在與您玩牌;它只是發出牌盒中的牌,從而允許您開始各種牌局。現在讓我們構建一個真正與您玩牌的 Blackjack 發牌器。使用發牌器必須至少抽到 17 的簡單內部規則構建此發牌器。 這部分代碼將類似先前構建的簡單的撲克發牌器。對於 Blackjack,您需要以迭代抽取及牌局評估的形式構建。您將需要一個把牌面值指定為數字描述的數組。如果更改構建牌組的方法,您可以在原始的 $faces 數組中完成此操作。 清單 9. 修改 Blackjack 的 $faces 數組 $faces = array('Two' => 2, ... ... ... 'King' => 10, 'Ace' => 11); | 然後您需要一個基本函數來評估給定的牌局。該函數將查看手中的牌並返回手上的牌面總值。 清單 10. 評估給定牌局的函數 function evaluateHand($hand) { global $faces; $value = 0; foreach ($hand as $card) { if ($value > 11 && $card['face'] == 'Ace') { $value = $value + 1; // An ace can be 11 or 1 } else { $value = intval($value) + intval($faces[$card['face']]); } } return $value; } | 在評估手上牌局的函數就緒后,應當很容易確定您手上的牌是否超過 21 點,或者發牌器是否應當要牌。有關如何整合所有這些內容的詳細信息,請參閱 代碼歸檔。
牌面計算器 在玩 Blackjack 或者諸如紅心大戰之類基於王牌的遊戲時,知道如何算牌會十分有用。在玩 Blackjack 時,至少需要知道已經看到多少張 A 和花牌。對於紅心大戰,您可能需要知道遊戲中還有多少王牌。您將構建一個 Blackjack 基本計算器。您可以採用相同原理構建王牌遊戲的牌面計算器。 您將構建以略微不同的方式進行計算的牌組。您不必知道所有牌 — 只關注自己感興趣的牌。對於單牌組牌盒,則類似如下所示: 清單 11. 構建單牌組牌盒的牌面計算器 $deck = array ( 'faces' => 16, // 10,J,Q,K * 4 suits 'aces' => 4, // One per suit 'other' => 32, // 52 - (16 + 4) ); | 接下來,構建一張帶有三個按鈕的表單 — 一個用於花牌,一個用於 A,而另一個用於其他牌。通過在每次看到特定類型的牌時單擊相應按鈕,您可以調整留在牌組中的牌。 清單 12. 帶有三個按鈕的簡單表單 if (PHP 是一種易於使用、易於學習且可以廣泛獲取的編程語言。它非常適合開發在各種遊戲中可以使用的簡單腳本。無論是一個人玩簡單的使用紙和筆的遊戲,還是同一群人玩複雜的桌面角色扮演遊戲,或者任意類型的聯機遊戲,本系列都提供了適合您的內容。本文將在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 基礎上,探究可以在各種類型的遊戲中使用的 10 個中級腳本。這些腳本適用於三種遊戲:角色扮演遊戲、機率遊戲和文字遊戲。 在本系列的 第 1 部分 中,您創建了一些初學者級別的 PHP 腳本。現在是時候提高要求來增加一些複雜度,進一步拓展您的 PHP 編程技能並提高您作為遊戲專家的地位。 對於角色扮演遊戲腳本,您將了解如何整合武器的破壞力計算器、特徵表統計跟蹤器及非玩家角色(Non-Player Character,NPC)生成器,同時教您如何將信息保存到文件中以及如何與 PHP 中的數組結合使用。與機率遊戲相關的腳本將幫助您練習 Blackjack,學習如何算牌,並且快速了解 Bingo(一種賭博遊戲)的基本規則,同時教您如何將機率元素插入到 PHP 腳本中。最後,文字遊戲腳本將幫助您解決 Jumble 遊戲,創建簡單的置換計算程序,並生成文字搜索圖,同時讓您的 PHP 數組處理技能更上一層樓。 我們將快速地介紹這些腳本,而不會討論如何查找主機或設置伺服器。有很多 Web 託管公司提供 PHP,並且如果需要安裝自己的 PHP,XAMPP 安裝程序使用起來也十分簡單。我們將不會花費大量時間談論 PHP 最佳實踐或遊戲設計技術。本文介紹的腳本易於理解、使用簡單並可以快速掌握。 本文的 代碼歸檔 包含所討論的每個腳本的完整源代碼,並且可以訪問 Chaoticneutral.net 查看腳本實際運行情況。 破壞力計算器 在 第 1 部分中,我們構建了一個基本的擲骰器。讓我們查看一下如何使用該擲骰器幫助整合基本的破壞力計算器。 如果您曾經運行或者玩過桌面角色扮演遊戲,則可能已經看到過書中附帶的大型武器圖表。通常,這些圖表包括武器名稱及武器的破壞力有多大。它可能類似表 1 中所示的內容。 表 1. 破壞力計算器 武器名稱 | 破壞力 | Little Stick | 1d6 | Big Stick | 1d6+4 | Chainsaw | 2d8 | 您應當能夠得到在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 中創建的簡單 roll 函數,並且使用它計算一套基本武器的破壞力。為此,需要創建一個數組來保存關於武器的信息。 對於本例,一個武器有三個基本特性:名稱(Name)、擲骰(Die Roll)和傷害獎勵(Damage Bonus)。使用這些特性,您可以構建武器數組,如下所示: 清單 1. 武器數組 $weapons = array ( 'littlestick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '0', ), 'bigstick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '4', ), 'chainsaw' => array ( 'name' => 'Little Stick', 'roll' => '2d8', 'bonus' => '0', ), ); | 使用此數組,您可以構建一張顯示武器、武器的破壞力及傷害判定結果表。 清單 2. 構建武器表 foreach ($weapons as $weapon) { list($count, $sides) = explode('d', $weapon['roll']); $result = 0; for ($i = 0; $i < $count;$i++) { $result = $result + roll($sides); } echo "<tr><td>" . $weapon['name'] . "</td><td>" . $weapon['roll']; if ($weapon['bonus'] > 0) { echo "+" . $weapon['bonus']; $result = $result + $weapon['bonus']; } echo "</td><td>" . $result . "</td></tr>"; } | 使用此腳本,您可以用集成的破壞力計算器創建基本武器圖。
統計跟蹤 現在已經可以計算破壞力,讓我們查看如何跟蹤一些基本任務統計信息,這種功能在要運行帶有多個 NPC 的遊戲時可能需要使用。創建一個簡單數組來保存人物信息並將其另存(序列化)為文本文件(將這些信息保存到資料庫中有許多方法,並且在您逐漸熟悉如何使用 PHP 后應當保存到資料庫)。對於本例,您將通過我編寫的名為 Shambles 的遊戲創建一個基本的怪物角色。首先建立一個數組以保存角色信息。 清單 3. 角色信息數組 $character = array( 'name' => 'Fred The Zombie', 'health' => '36', 'gore' => '1', 'clutch' => '5', 'brawn' => '6', 'sense' => '4', 'flail' => '2', 'chuck' => '3', 'lurch' => '4', ); | 需要生成文件名以保存這些信息。實際上不需要在傳入時就使用輸入,但是只可以使用人物姓名中的字母創建文件。 清單 4. 創建用於存儲信息的文件 $filename = substr(preg_replace("/[^a-z0-9]/", "", strtolower($character['name'])), 0, 20); file_put_contents($filename, serialize($character)); | 註:在將該腳本提供給公共使用時,需要過濾用戶輸入以避免有人將錯誤的 JavaScript 代碼或垃圾代碼惡意插入文件中。這只是供您個人使用的示例。最後,需要用表單表示信息以便可以輕鬆更新。這隻需使用輸入欄位中的默認值創建一張表單。 清單 5. 用表單顯示信息 <input name='health' value='<?php echo $character['health'] ?>' /> | 使用此基本腳本(請參閱 代碼歸檔)跟蹤幾個角色和 NPC。
NPC 生成器 在整合一個大型遊戲時,擁有一個一次性的 NPC 池十分有用。如果需要大量暴徒或者士兵,這樣做尤其有幫助。要整合 NPC 生成器,讓我們構建一個包含構造角色規則的數組,然後使用隨機姓名生成器及擲骰器一次性整合一批角色。 使用 Fred the Zombie 作為示例,您可以定義創建角色的規則。某些統計信息是固定的(生命力總是從 36 開始),某些統計信息是派生的(血=生命力/6),而某些統計信息是擲骰的結果(離合器是 1d6 — 一個六面骰子)。規則類似清單 6 中所示的內容。 清單 6. 定義角色創建的規則 $rules = array( 'health' => '36', 'gore' => 'health/6', 'clutch' => '1d6', 'brawn' => '1d6', 'sense' => '1d6', 'flail' => '1d6', 'chuck' => '1d6', 'lurch' => '1d6', ); | 現在您可以編寫少量代碼來評估規則。 清單 7. 評估規則的代碼 foreach ($rules as $stat=>$rule) { if (preg_match("/^[0-9]+$/", $rule)) { // This is only a number, and is therefore a static value $character[$stat] = $rule; } else if (preg_match("/^([0-9]+)d([0-9]+)/", $rule, $matches)) { // This is a die roll $val = 0; for ($n = 0;$n<$matches[1];$n++) { $val = $val + roll($matches[2]); } $character[$stat] = $val; } else if (preg_match("/^([a-z]+)\/([0-9]+)$/", $rule, $matches)) { // This is a derived value of some kind. $character[$stat] = $character[$matches[1]] / $matches[2]; } echo $stat . ' : ' . $character[$stat] . "<br />\n"; } | 在正確評估規則時,您可以引入使用隨機姓名生成器生成的隨機姓名並且一連幾天製作 NPC。請查看 代碼歸檔 中的腳本了解如何整合該任務。
機率計算器:擲骰 在 第 1 部分 中,您整合了一個簡單的機率計算器以確定從給定的一副牌中抽到指定牌面或花色的機率。現在讓我們構建一個擲骰機率計算器。對於本例,您將構建一個在擲兩個六面骰子(2d6)時確定可能結果的計算器。如果使用的是基於 d6 的任何 RPG 系統,玩大富豪或雙陸棋之類的棋盤類遊戲,或者要嘗試在諸如 Craps 之類的骰子遊戲中計算出機率,這將十分有用。 首先,建立在擲兩個骰子時確定可能結果的方法。可以考慮擲兩個不同顏色的骰子(如一個紅色骰子和一個藍色骰子)。如果擲紅色骰子的結果為 1,則有六個可能的結果,每個結果取決於藍色骰子的一面。這意味著可能的擲骰結果總數為 6^2 即 36 個結果。這可能看似有些奇怪,因為您實際上可以得到的最高值為 12(紅色六點加藍色六點),但是如果您認識到可以通過兩個不同的結果得到 11(紅色六點加藍色五點,或者紅色五點加藍色六點)應當更有意義。 讓我們假定,在本例中,您需要同時獲得總和(擲出 10)和骰面(擲出 6 和 4)結果,並且紅色骰子的 6 點與藍色骰子的 6 點沒有差別。重要的數字為 S(骰子面數)和 N(骰子個數)— 假定有 N 個相同的骰子,最大結果數為 S^N — 可是這其中的一些結果可能相同(一個 6 和一個 4,以及一個 4 和一個 6)。 清單 8. 構建擲骰機率計算器 $s = 6; $n = 2; $results = array(array()); for ($i = 0; $i < $n; $i ++) { $newresults = array(); foreach ($results as $result) { for ($x = 0; $x < $s; $x++) { $newresults[] = array_merge($result, array($x+1)); } } $results = $newresults; } | 這可能看似有些沉悶。您可以適當地簡化這段代碼,但是我已經在這裡完成了一些更明顯的操作,因此您可以了解數組是如何處理的。在構建完最終數組后,您可以迭代數組並生成骰子數總和的列表及其各自的機率。這段代碼包含在 代碼歸檔 中。
簡單的 Blackjack 撲克發牌器 在 第 1 部分 中,您構建了一個簡單的撲克發牌器。該發牌器不是真正地在與您玩牌;它只是發出牌盒中的牌,從而允許您開始各種牌局。現在讓我們構建一個真正與您玩牌的 Blackjack 發牌器。使用發牌器必須至少抽到 17 的簡單內部規則構建此發牌器。 這部分代碼將類似先前構建的簡單的撲克發牌器。對於 Blackjack,您需要以迭代抽取及牌局評估的形式構建。您將需要一個把牌面值指定為數字描述的數組。如果更改構建牌組的方法,您可以在原始的 $faces 數組中完成此操作。 清單 9. 修改 Blackjack 的 $faces 數組 $faces = array('Two' => 2, ... ... ... 'King' => 10, 'Ace' => 11); | 然後您需要一個基本函數來評估給定的牌局。該函數將查看手中的牌並返回手上的牌面總值。 清單 10. 評估給定牌局的函數 function evaluateHand($hand) { global $faces; $value = 0; foreach ($hand as $card) { if ($value > 11 && $card['face'] == 'Ace') { $value = $value + 1; // An ace can be 11 or 1 } else { $value = intval($value) + intval($faces[$card['face']]); } } return $value; } | 在評估手上牌局的函數就緒后,應當很容易確定您手上的牌是否超過 21 點,或者發牌器是否應當要牌。有關如何整合所有這些內容的詳細信息,請參閱 代碼歸檔。
牌面計算器 在玩 Blackjack 或者諸如紅心大戰之類基於王牌的遊戲時,知道如何算牌會十分有用。在玩 Blackjack 時,至少需要知道已經看到多少張 A 和花牌。對於紅心大戰,您可能需要知道遊戲中還有多少王牌。您將構建一個 Blackjack 基本計算器。您可以採用相同原理構建王牌遊戲的牌面計算器。 您將構建以略微不同的方式進行計算的牌組。您不必知道所有牌 — 只關注自己感興趣的牌。對於單牌組牌盒,則類似如下所示: 清單 11. 構建單牌組牌盒的牌面計算器 $deck = array ( 'faces' => 16, // 10,J,Q,K * 4 suits 'aces' => 4, // One per suit 'other' => 32, // 52 - (16 + 4) ); | 接下來,構建一張帶有三個按鈕的表單 — 一個用於花牌,一個用於 A,而另一個用於其他牌。通過在每次看到特定類型的牌時單擊相應按鈕,您可以調整留在牌組中的牌。 清單 12. 帶有三個按鈕的簡單表單 然後通過查看修改後的牌組,可以計算抽到花牌、A 或其他牌的機率。 清單 13. 計算抽到花牌、A 或其他牌的機率 echo "Odds of pulling a face: " . $deck['faces'] . " out of " . $deck['faces'] + $deck['aces'] + $deck['other']; | 使用這個基本牌面計算器作為起點,您可以構建一些更健壯的程序。
Bingo 引擎 基於我們在本文中已經完成的內容,您可以輕鬆地整合一個 Bingo 引擎以生成牌並從池中抽出編號。 Bingo 編號範圍從 1 到 75,以 15 個編號為一組(1-15 分配給 B,16-30 分配給 I 等等)。按照構建並洗一副虛擬牌的相同方法,您可以構建並洗一套虛擬的 Bingo 球。但是您無需以相同方法跟蹤牌面和花色。首先,構建基本編號集。 清單 14. 構建 Bingo 的基本編號集 for ($i = 1; $i < 16; $i++) { $numbers['B'][] = $i; $numbers['I'][] = $i+15; $numbers['N'][] = $i+30; $numbers['G'][] = $i+45; $numbers['O'][] = $i+60; } | 接下來,您可以置換每個子數組並且同時製作牌(不要忘記:中間的部分通常是一張任意的牌)。完成後,創建一個可用作牌組的主數組。 清單 15. 創建主數組 $letters = array ('B','I','N','G','O'); foreach ($letters as $letter) { shuffle($numbers[$letter]); $chunks = array_chunk($numbers[$letter], 5); $cards[$i][$letter] = $chunks[0]; if ($letter == 'N') { $cards[$i][$letter][2] = ' '; // Free Space } shuffle($balls); } | 現在已經全部完成!分發牌,並開始從主集合中抽取虛擬 Bingo 球,就像先前抽牌所做的那樣。在 代碼歸檔 中可以找到此腳本的完整運行版本。
Jumble 助手 Jumble 是在大多數報紙中可以找到的字謎,您有一些已經完全混合在一起的單詞。您必須從廢話中提取出實際單詞來,然後使用某些字母來創造新短語。從在 第 1 部分 中創建的縱橫字謎助手開始,讓我們整合一個快速腳本以幫助您構建 Jumble。 首先,打開單詞列表。需要遍歷該列表,將每個單詞拆分為經過排序的字母數組,然後再次合併數組。例如,這樣做將把單詞 “COLOR” 改為字元串 “CLOOR”;該字元串表示單詞 “COLOR” 中的所有字母,但是按照可預測的(而且更重要的是相配的)順序。該字元串隨後將被用作匹配單詞的數組的關鍵字。它必須為數組,因為 “sword” 和 “words” 擁有完全相同的字母,但是順序不同。最後,它將類似如下所示的內容: 清單 16. Jumble 的腳本 foreach ($words as $word) { $arr = str_split($word); sort($arr); $key = implode('', $arr); if (isset($lookup[$key])) { array_push($lookup[$key], $word); } else { $lookup[$key] = array($word); } } | 完成到此為止的程序后,只需將 Jumble 像任何其他單詞一樣處理,查找相應關鍵字的值並輸出所有結果。 清單 17. 完成 Jumble 腳本 $arr = str_split(PHP 是一種易於使用、易於學習且可以廣泛獲取的編程語言。它非常適合開發在各種遊戲中可以使用的簡單腳本。無論是一個人玩簡單的使用紙和筆的遊戲,還是同一群人玩複雜的桌面角色扮演遊戲,或者任意類型的聯機遊戲,本系列都提供了適合您的內容。本文將在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 基礎上,探究可以在各種類型的遊戲中使用的 10 個中級腳本。這些腳本適用於三種遊戲:角色扮演遊戲、機率遊戲和文字遊戲。 在本系列的 第 1 部分 中,您創建了一些初學者級別的 PHP 腳本。現在是時候提高要求來增加一些複雜度,進一步拓展您的 PHP 編程技能並提高您作為遊戲專家的地位。 對於角色扮演遊戲腳本,您將了解如何整合武器的破壞力計算器、特徵表統計跟蹤器及非玩家角色(Non-Player Character,NPC)生成器,同時教您如何將信息保存到文件中以及如何與 PHP 中的數組結合使用。與機率遊戲相關的腳本將幫助您練習 Blackjack,學習如何算牌,並且快速了解 Bingo(一種賭博遊戲)的基本規則,同時教您如何將機率元素插入到 PHP 腳本中。最後,文字遊戲腳本將幫助您解決 Jumble 遊戲,創建簡單的置換計算程序,並生成文字搜索圖,同時讓您的 PHP 數組處理技能更上一層樓。 我們將快速地介紹這些腳本,而不會討論如何查找主機或設置伺服器。有很多 Web 託管公司提供 PHP,並且如果需要安裝自己的 PHP,XAMPP 安裝程序使用起來也十分簡單。我們將不會花費大量時間談論 PHP 最佳實踐或遊戲設計技術。本文介紹的腳本易於理解、使用簡單並可以快速掌握。 本文的 代碼歸檔 包含所討論的每個腳本的完整源代碼,並且可以訪問 Chaoticneutral.net 查看腳本實際運行情況。 破壞力計算器 在 第 1 部分中,我們構建了一個基本的擲骰器。讓我們查看一下如何使用該擲骰器幫助整合基本的破壞力計算器。 如果您曾經運行或者玩過桌面角色扮演遊戲,則可能已經看到過書中附帶的大型武器圖表。通常,這些圖表包括武器名稱及武器的破壞力有多大。它可能類似表 1 中所示的內容。 表 1. 破壞力計算器 武器名稱 | 破壞力 | Little Stick | 1d6 | Big Stick | 1d6+4 | Chainsaw | 2d8 | 您應當能夠得到在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 中創建的簡單 roll 函數,並且使用它計算一套基本武器的破壞力。為此,需要創建一個數組來保存關於武器的信息。 對於本例,一個武器有三個基本特性:名稱(Name)、擲骰(Die Roll)和傷害獎勵(Damage Bonus)。使用這些特性,您可以構建武器數組,如下所示: 清單 1. 武器數組 $weapons = array ( 'littlestick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '0', ), 'bigstick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '4', ), 'chainsaw' => array ( 'name' => 'Little Stick', 'roll' => '2d8', 'bonus' => '0', ), ); | 使用此數組,您可以構建一張顯示武器、武器的破壞力及傷害判定結果表。 清單 2. 構建武器表 foreach ($weapons as $weapon) { list($count, $sides) = explode('d', $weapon['roll']); $result = 0; for ($i = 0; $i < $count;$i++) { $result = $result + roll($sides); } echo "<tr><td>" . $weapon['name'] . "</td><td>" . $weapon['roll']; if ($weapon['bonus'] > 0) { echo "+" . $weapon['bonus']; $result = $result + $weapon['bonus']; } echo "</td><td>" . $result . "</td></tr>"; } | 使用此腳本,您可以用集成的破壞力計算器創建基本武器圖。
統計跟蹤 現在已經可以計算破壞力,讓我們查看如何跟蹤一些基本任務統計信息,這種功能在要運行帶有多個 NPC 的遊戲時可能需要使用。創建一個簡單數組來保存人物信息並將其另存(序列化)為文本文件(將這些信息保存到資料庫中有許多方法,並且在您逐漸熟悉如何使用 PHP 后應當保存到資料庫)。對於本例,您將通過我編寫的名為 Shambles 的遊戲創建一個基本的怪物角色。首先建立一個數組以保存角色信息。 清單 3. 角色信息數組 $character = array( 'name' => 'Fred The Zombie', 'health' => '36', 'gore' => '1', 'clutch' => '5', 'brawn' => '6', 'sense' => '4', 'flail' => '2', 'chuck' => '3', 'lurch' => '4', ); | 需要生成文件名以保存這些信息。實際上不需要在傳入時就使用輸入,但是只可以使用人物姓名中的字母創建文件。 清單 4. 創建用於存儲信息的文件 $filename = substr(preg_replace("/[^a-z0-9]/", "", strtolower($character['name'])), 0, 20); file_put_contents($filename, serialize($character)); | 註:在將該腳本提供給公共使用時,需要過濾用戶輸入以避免有人將錯誤的 JavaScript 代碼或垃圾代碼惡意插入文件中。這只是供您個人使用的示例。最後,需要用表單表示信息以便可以輕鬆更新。這隻需使用輸入欄位中的默認值創建一張表單。 清單 5. 用表單顯示信息 <input name='health' value='<?php echo $character['health'] ?>' /> | 使用此基本腳本(請參閱 代碼歸檔)跟蹤幾個角色和 NPC。
NPC 生成器 在整合一個大型遊戲時,擁有一個一次性的 NPC 池十分有用。如果需要大量暴徒或者士兵,這樣做尤其有幫助。要整合 NPC 生成器,讓我們構建一個包含構造角色規則的數組,然後使用隨機姓名生成器及擲骰器一次性整合一批角色。 使用 Fred the Zombie 作為示例,您可以定義創建角色的規則。某些統計信息是固定的(生命力總是從 36 開始),某些統計信息是派生的(血=生命力/6),而某些統計信息是擲骰的結果(離合器是 1d6 — 一個六面骰子)。規則類似清單 6 中所示的內容。 清單 6. 定義角色創建的規則 $rules = array( 'health' => '36', 'gore' => 'health/6', 'clutch' => '1d6', 'brawn' => '1d6', 'sense' => '1d6', 'flail' => '1d6', 'chuck' => '1d6', 'lurch' => '1d6', ); | 現在您可以編寫少量代碼來評估規則。 清單 7. 評估規則的代碼 foreach ($rules as $stat=>$rule) { if (preg_match("/^[0-9]+$/", $rule)) { // This is only a number, and is therefore a static value $character[$stat] = $rule; } else if (preg_match("/^([0-9]+)d([0-9]+)/", $rule, $matches)) { // This is a die roll $val = 0; for ($n = 0;$n<$matches[1];$n++) { $val = $val + roll($matches[2]); } $character[$stat] = $val; } else if (preg_match("/^([a-z]+)\/([0-9]+)$/", $rule, $matches)) { // This is a derived value of some kind. $character[$stat] = $character[$matches[1]] / $matches[2]; } echo $stat . ' : ' . $character[$stat] . "<br />\n"; } | 在正確評估規則時,您可以引入使用隨機姓名生成器生成的隨機姓名並且一連幾天製作 NPC。請查看 代碼歸檔 中的腳本了解如何整合該任務。
機率計算器:擲骰 在 第 1 部分 中,您整合了一個簡單的機率計算器以確定從給定的一副牌中抽到指定牌面或花色的機率。現在讓我們構建一個擲骰機率計算器。對於本例,您將構建一個在擲兩個六面骰子(2d6)時確定可能結果的計算器。如果使用的是基於 d6 的任何 RPG 系統,玩大富豪或雙陸棋之類的棋盤類遊戲,或者要嘗試在諸如 Craps 之類的骰子遊戲中計算出機率,這將十分有用。 首先,建立在擲兩個骰子時確定可能結果的方法。可以考慮擲兩個不同顏色的骰子(如一個紅色骰子和一個藍色骰子)。如果擲紅色骰子的結果為 1,則有六個可能的結果,每個結果取決於藍色骰子的一面。這意味著可能的擲骰結果總數為 6^2 即 36 個結果。這可能看似有些奇怪,因為您實際上可以得到的最高值為 12(紅色六點加藍色六點),但是如果您認識到可以通過兩個不同的結果得到 11(紅色六點加藍色五點,或者紅色五點加藍色六點)應當更有意義。 讓我們假定,在本例中,您需要同時獲得總和(擲出 10)和骰面(擲出 6 和 4)結果,並且紅色骰子的 6 點與藍色骰子的 6 點沒有差別。重要的數字為 S(骰子面數)和 N(骰子個數)— 假定有 N 個相同的骰子,最大結果數為 S^N — 可是這其中的一些結果可能相同(一個 6 和一個 4,以及一個 4 和一個 6)。 清單 8. 構建擲骰機率計算器 $s = 6; $n = 2; $results = array(array()); for ($i = 0; $i < $n; $i ++) { $newresults = array(); foreach ($results as $result) { for ($x = 0; $x < $s; $x++) { $newresults[] = array_merge($result, array($x+1)); } } $results = $newresults; } | 這可能看似有些沉悶。您可以適當地簡化這段代碼,但是我已經在這裡完成了一些更明顯的操作,因此您可以了解數組是如何處理的。在構建完最終數組后,您可以迭代數組並生成骰子數總和的列表及其各自的機率。這段代碼包含在 代碼歸檔 中。
簡單的 Blackjack 撲克發牌器 在 第 1 部分 中,您構建了一個簡單的撲克發牌器。該發牌器不是真正地在與您玩牌;它只是發出牌盒中的牌,從而允許您開始各種牌局。現在讓我們構建一個真正與您玩牌的 Blackjack 發牌器。使用發牌器必須至少抽到 17 的簡單內部規則構建此發牌器。 這部分代碼將類似先前構建的簡單的撲克發牌器。對於 Blackjack,您需要以迭代抽取及牌局評估的形式構建。您將需要一個把牌面值指定為數字描述的數組。如果更改構建牌組的方法,您可以在原始的 $faces 數組中完成此操作。 清單 9. 修改 Blackjack 的 $faces 數組 $faces = array('Two' => 2, ... ... ... 'King' => 10, 'Ace' => 11); | 然後您需要一個基本函數來評估給定的牌局。該函數將查看手中的牌並返回手上的牌面總值。 清單 10. 評估給定牌局的函數 function evaluateHand($hand) { global $faces; $value = 0; foreach ($hand as $card) { if ($value > 11 && $card['face'] == 'Ace') { $value = $value + 1; // An ace can be 11 or 1 } else { $value = intval($value) + intval($faces[$card['face']]); } } return $value; } | 在評估手上牌局的函數就緒后,應當很容易確定您手上的牌是否超過 21 點,或者發牌器是否應當要牌。有關如何整合所有這些內容的詳細信息,請參閱 代碼歸檔。
牌面計算器 在玩 Blackjack 或者諸如紅心大戰之類基於王牌的遊戲時,知道如何算牌會十分有用。在玩 Blackjack 時,至少需要知道已經看到多少張 A 和花牌。對於紅心大戰,您可能需要知道遊戲中還有多少王牌。您將構建一個 Blackjack 基本計算器。您可以採用相同原理構建王牌遊戲的牌面計算器。 您將構建以略微不同的方式進行計算的牌組。您不必知道所有牌 — 只關注自己感興趣的牌。對於單牌組牌盒,則類似如下所示: 清單 11. 構建單牌組牌盒的牌面計算器 $deck = array ( 'faces' => 16, // 10,J,Q,K * 4 suits 'aces' => 4, // One per suit 'other' => 32, // 52 - (16 + 4) ); | 接下來,構建一張帶有三個按鈕的表單 — 一個用於花牌,一個用於 A,而另一個用於其他牌。通過在每次看到特定類型的牌時單擊相應按鈕,您可以調整留在牌組中的牌。 清單 12. 帶有三個按鈕的簡單表單 if (PHP 是一種易於使用、易於學習且可以廣泛獲取的編程語言。它非常適合開發在各種遊戲中可以使用的簡單腳本。無論是一個人玩簡單的使用紙和筆的遊戲,還是同一群人玩複雜的桌面角色扮演遊戲,或者任意類型的聯機遊戲,本系列都提供了適合您的內容。本文將在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 基礎上,探究可以在各種類型的遊戲中使用的 10 個中級腳本。這些腳本適用於三種遊戲:角色扮演遊戲、機率遊戲和文字遊戲。 在本系列的 第 1 部分 中,您創建了一些初學者級別的 PHP 腳本。現在是時候提高要求來增加一些複雜度,進一步拓展您的 PHP 編程技能並提高您作為遊戲專家的地位。 對於角色扮演遊戲腳本,您將了解如何整合武器的破壞力計算器、特徵表統計跟蹤器及非玩家角色(Non-Player Character,NPC)生成器,同時教您如何將信息保存到文件中以及如何與 PHP 中的數組結合使用。與機率遊戲相關的腳本將幫助您練習 Blackjack,學習如何算牌,並且快速了解 Bingo(一種賭博遊戲)的基本規則,同時教您如何將機率元素插入到 PHP 腳本中。最後,文字遊戲腳本將幫助您解決 Jumble 遊戲,創建簡單的置換計算程序,並生成文字搜索圖,同時讓您的 PHP 數組處理技能更上一層樓。 我們將快速地介紹這些腳本,而不會討論如何查找主機或設置伺服器。有很多 Web 託管公司提供 PHP,並且如果需要安裝自己的 PHP,XAMPP 安裝程序使用起來也十分簡單。我們將不會花費大量時間談論 PHP 最佳實踐或遊戲設計技術。本文介紹的腳本易於理解、使用簡單並可以快速掌握。 本文的 代碼歸檔 包含所討論的每個腳本的完整源代碼,並且可以訪問 Chaoticneutral.net 查看腳本實際運行情況。 破壞力計算器 在 第 1 部分中,我們構建了一個基本的擲骰器。讓我們查看一下如何使用該擲骰器幫助整合基本的破壞力計算器。 如果您曾經運行或者玩過桌面角色扮演遊戲,則可能已經看到過書中附帶的大型武器圖表。通常,這些圖表包括武器名稱及武器的破壞力有多大。它可能類似表 1 中所示的內容。 表 1. 破壞力計算器 武器名稱 | 破壞力 | Little Stick | 1d6 | Big Stick | 1d6+4 | Chainsaw | 2d8 | 您應當能夠得到在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 中創建的簡單 roll 函數,並且使用它計算一套基本武器的破壞力。為此,需要創建一個數組來保存關於武器的信息。 對於本例,一個武器有三個基本特性:名稱(Name)、擲骰(Die Roll)和傷害獎勵(Damage Bonus)。使用這些特性,您可以構建武器數組,如下所示: 清單 1. 武器數組 $weapons = array ( 'littlestick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '0', ), 'bigstick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '4', ), 'chainsaw' => array ( 'name' => 'Little Stick', 'roll' => '2d8', 'bonus' => '0', ), ); | 使用此數組,您可以構建一張顯示武器、武器的破壞力及傷害判定結果表。 清單 2. 構建武器表 foreach ($weapons as $weapon) { list($count, $sides) = explode('d', $weapon['roll']); $result = 0; for ($i = 0; $i < $count;$i++) { $result = $result + roll($sides); } echo "<tr><td>" . $weapon['name'] . "</td><td>" . $weapon['roll']; if ($weapon['bonus'] > 0) { echo "+" . $weapon['bonus']; $result = $result + $weapon['bonus']; } echo "</td><td>" . $result . "</td></tr>"; } | 使用此腳本,您可以用集成的破壞力計算器創建基本武器圖。
統計跟蹤 現在已經可以計算破壞力,讓我們查看如何跟蹤一些基本任務統計信息,這種功能在要運行帶有多個 NPC 的遊戲時可能需要使用。創建一個簡單數組來保存人物信息並將其另存(序列化)為文本文件(將這些信息保存到資料庫中有許多方法,並且在您逐漸熟悉如何使用 PHP 后應當保存到資料庫)。對於本例,您將通過我編寫的名為 Shambles 的遊戲創建一個基本的怪物角色。首先建立一個數組以保存角色信息。 清單 3. 角色信息數組 $character = array( 'name' => 'Fred The Zombie', 'health' => '36', 'gore' => '1', 'clutch' => '5', 'brawn' => '6', 'sense' => '4', 'flail' => '2', 'chuck' => '3', 'lurch' => '4', ); | 需要生成文件名以保存這些信息。實際上不需要在傳入時就使用輸入,但是只可以使用人物姓名中的字母創建文件。 清單 4. 創建用於存儲信息的文件 $filename = substr(preg_replace("/[^a-z0-9]/", "", strtolower($character['name'])), 0, 20); file_put_contents($filename, serialize($character)); | 註:在將該腳本提供給公共使用時,需要過濾用戶輸入以避免有人將錯誤的 JavaScript 代碼或垃圾代碼惡意插入文件中。這只是供您個人使用的示例。最後,需要用表單表示信息以便可以輕鬆更新。這隻需使用輸入欄位中的默認值創建一張表單。 清單 5. 用表單顯示信息 <input name='health' value='<?php echo $character['health'] ?>' /> | 使用此基本腳本(請參閱 代碼歸檔)跟蹤幾個角色和 NPC。
NPC 生成器 在整合一個大型遊戲時,擁有一個一次性的 NPC 池十分有用。如果需要大量暴徒或者士兵,這樣做尤其有幫助。要整合 NPC 生成器,讓我們構建一個包含構造角色規則的數組,然後使用隨機姓名生成器及擲骰器一次性整合一批角色。 使用 Fred the Zombie 作為示例,您可以定義創建角色的規則。某些統計信息是固定的(生命力總是從 36 開始),某些統計信息是派生的(血=生命力/6),而某些統計信息是擲骰的結果(離合器是 1d6 — 一個六面骰子)。規則類似清單 6 中所示的內容。 清單 6. 定義角色創建的規則 $rules = array( 'health' => '36', 'gore' => 'health/6', 'clutch' => '1d6', 'brawn' => '1d6', 'sense' => '1d6', 'flail' => '1d6', 'chuck' => '1d6', 'lurch' => '1d6', ); | 現在您可以編寫少量代碼來評估規則。 清單 7. 評估規則的代碼 foreach ($rules as $stat=>$rule) { if (preg_match("/^[0-9]+$/", $rule)) { // This is only a number, and is therefore a static value $character[$stat] = $rule; } else if (preg_match("/^([0-9]+)d([0-9]+)/", $rule, $matches)) { // This is a die roll $val = 0; for ($n = 0;$n<$matches[1];$n++) { $val = $val + roll($matches[2]); } $character[$stat] = $val; } else if (preg_match("/^([a-z]+)\/([0-9]+)$/", $rule, $matches)) { // This is a derived value of some kind. $character[$stat] = $character[$matches[1]] / $matches[2]; } echo $stat . ' : ' . $character[$stat] . "<br />\n"; } | 在正確評估規則時,您可以引入使用隨機姓名生成器生成的隨機姓名並且一連幾天製作 NPC。請查看 代碼歸檔 中的腳本了解如何整合該任務。
機率計算器:擲骰 在 第 1 部分 中,您整合了一個簡單的機率計算器以確定從給定的一副牌中抽到指定牌面或花色的機率。現在讓我們構建一個擲骰機率計算器。對於本例,您將構建一個在擲兩個六面骰子(2d6)時確定可能結果的計算器。如果使用的是基於 d6 的任何 RPG 系統,玩大富豪或雙陸棋之類的棋盤類遊戲,或者要嘗試在諸如 Craps 之類的骰子遊戲中計算出機率,這將十分有用。 首先,建立在擲兩個骰子時確定可能結果的方法。可以考慮擲兩個不同顏色的骰子(如一個紅色骰子和一個藍色骰子)。如果擲紅色骰子的結果為 1,則有六個可能的結果,每個結果取決於藍色骰子的一面。這意味著可能的擲骰結果總數為 6^2 即 36 個結果。這可能看似有些奇怪,因為您實際上可以得到的最高值為 12(紅色六點加藍色六點),但是如果您認識到可以通過兩個不同的結果得到 11(紅色六點加藍色五點,或者紅色五點加藍色六點)應當更有意義。 讓我們假定,在本例中,您需要同時獲得總和(擲出 10)和骰面(擲出 6 和 4)結果,並且紅色骰子的 6 點與藍色骰子的 6 點沒有差別。重要的數字為 S(骰子面數)和 N(骰子個數)— 假定有 N 個相同的骰子,最大結果數為 S^N — 可是這其中的一些結果可能相同(一個 6 和一個 4,以及一個 4 和一個 6)。 清單 8. 構建擲骰機率計算器 $s = 6; $n = 2; $results = array(array()); for ($i = 0; $i < $n; $i ++) { $newresults = array(); foreach ($results as $result) { for ($x = 0; $x < $s; $x++) { $newresults[] = array_merge($result, array($x+1)); } } $results = $newresults; } | 這可能看似有些沉悶。您可以適當地簡化這段代碼,但是我已經在這裡完成了一些更明顯的操作,因此您可以了解數組是如何處理的。在構建完最終數組后,您可以迭代數組並生成骰子數總和的列表及其各自的機率。這段代碼包含在 代碼歸檔 中。
簡單的 Blackjack 撲克發牌器 在 第 1 部分 中,您構建了一個簡單的撲克發牌器。該發牌器不是真正地在與您玩牌;它只是發出牌盒中的牌,從而允許您開始各種牌局。現在讓我們構建一個真正與您玩牌的 Blackjack 發牌器。使用發牌器必須至少抽到 17 的簡單內部規則構建此發牌器。 這部分代碼將類似先前構建的簡單的撲克發牌器。對於 Blackjack,您需要以迭代抽取及牌局評估的形式構建。您將需要一個把牌面值指定為數字描述的數組。如果更改構建牌組的方法,您可以在原始的 $faces 數組中完成此操作。 清單 9. 修改 Blackjack 的 $faces 數組 $faces = array('Two' => 2, ... ... ... 'King' => 10, 'Ace' => 11); | 然後您需要一個基本函數來評估給定的牌局。該函數將查看手中的牌並返回手上的牌面總值。 清單 10. 評估給定牌局的函數 function evaluateHand($hand) { global $faces; $value = 0; foreach ($hand as $card) { if ($value > 11 && $card['face'] == 'Ace') { $value = $value + 1; // An ace can be 11 or 1 } else { $value = intval($value) + intval($faces[$card['face']]); } } return $value; } | 在評估手上牌局的函數就緒后,應當很容易確定您手上的牌是否超過 21 點,或者發牌器是否應當要牌。有關如何整合所有這些內容的詳細信息,請參閱 代碼歸檔。
牌面計算器 在玩 Blackjack 或者諸如紅心大戰之類基於王牌的遊戲時,知道如何算牌會十分有用。在玩 Blackjack 時,至少需要知道已經看到多少張 A 和花牌。對於紅心大戰,您可能需要知道遊戲中還有多少王牌。您將構建一個 Blackjack 基本計算器。您可以採用相同原理構建王牌遊戲的牌面計算器。 您將構建以略微不同的方式進行計算的牌組。您不必知道所有牌 — 只關注自己感興趣的牌。對於單牌組牌盒,則類似如下所示: 清單 11. 構建單牌組牌盒的牌面計算器 $deck = array ( 'faces' => 16, // 10,J,Q,K * 4 suits 'aces' => 4, // One per suit 'other' => 32, // 52 - (16 + 4) ); | 接下來,構建一張帶有三個按鈕的表單 — 一個用於花牌,一個用於 A,而另一個用於其他牌。通過在每次看到特定類型的牌時單擊相應按鈕,您可以調整留在牌組中的牌。 清單 12. 帶有三個按鈕的簡單表單 然後通過查看修改後的牌組,可以計算抽到花牌、A 或其他牌的機率。 清單 13. 計算抽到花牌、A 或其他牌的機率 echo "Odds of pulling a face: " . $deck['faces'] . " out of " . $deck['faces'] + $deck['aces'] + $deck['other']; | 使用這個基本牌面計算器作為起點,您可以構建一些更健壯的程序。
Bingo 引擎 基於我們在本文中已經完成的內容,您可以輕鬆地整合一個 Bingo 引擎以生成牌並從池中抽出編號。 Bingo 編號範圍從 1 到 75,以 15 個編號為一組(1-15 分配給 B,16-30 分配給 I 等等)。按照構建並洗一副虛擬牌的相同方法,您可以構建並洗一套虛擬的 Bingo 球。但是您無需以相同方法跟蹤牌面和花色。首先,構建基本編號集。 清單 14. 構建 Bingo 的基本編號集 for ($i = 1; $i < 16; $i++) { $numbers['B'][] = $i; $numbers['I'][] = $i+15; $numbers['N'][] = $i+30; $numbers['G'][] = $i+45; $numbers['O'][] = $i+60; } | 接下來,您可以置換每個子數組並且同時製作牌(不要忘記:中間的部分通常是一張任意的牌)。完成後,創建一個可用作牌組的主數組。 清單 15. 創建主數組 $letters = array ('B','I','N','G','O'); foreach ($letters as $letter) { shuffle($numbers[$letter]); $chunks = array_chunk($numbers[$letter], 5); $cards[$i][$letter] = $chunks[0]; if ($letter == 'N') { $cards[$i][$letter][2] = ' '; // Free Space } shuffle($balls); } | 現在已經全部完成!分發牌,並開始從主集合中抽取虛擬 Bingo 球,就像先前抽牌所做的那樣。在 代碼歸檔 中可以找到此腳本的完整運行版本。
Jumble 助手 Jumble 是在大多數報紙中可以找到的字謎,您有一些已經完全混合在一起的單詞。您必須從廢話中提取出實際單詞來,然後使用某些字母來創造新短語。從在 第 1 部分 中創建的縱橫字謎助手開始,讓我們整合一個快速腳本以幫助您構建 Jumble。 首先,打開單詞列表。需要遍歷該列表,將每個單詞拆分為經過排序的字母數組,然後再次合併數組。例如,這樣做將把單詞 “COLOR” 改為字元串 “CLOOR”;該字元串表示單詞 “COLOR” 中的所有字母,但是按照可預測的(而且更重要的是相配的)順序。該字元串隨後將被用作匹配單詞的數組的關鍵字。它必須為數組,因為 “sword” 和 “words” 擁有完全相同的字母,但是順序不同。最後,它將類似如下所示的內容: 清單 16. Jumble 的腳本 foreach ($words as $word) { $arr = str_split($word); sort($arr); $key = implode('', $arr); if (isset($lookup[$key])) { array_push($lookup[$key], $word); } else { $lookup[$key] = array($word); } } | 完成到此為止的程序后,只需將 Jumble 像任何其他單詞一樣處理,查找相應關鍵字的值並輸出所有結果。 清單 17. 完成 Jumble 腳本 您可以在 代碼歸檔 中看到如何將這些內容整合在一起。
置換密碼 置換密碼 是一種簡單的加密技術,採用這項技術將把字母表中的每個字母替換為字母表中的其他字母。按照現代加密技術的標準,置換密碼簡直就是小兒科。但是簡單的置換密碼玩起來很有趣,尤其是在 RPG 環境中給某個人傳遞一條可以在玩遊戲的過程中破解出來的編碼信息。 首先從 第 1 部分 的 Hangman 生成器中偷一些代碼 — 也就是,字母數組。製作另外一份數組副本,攪亂該副本,並構建一個聯合數組,其中原來的字母將獲得重組后的值。 清單 18. 修改字母數組 $letters = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p', 'q','r','s','t','u','v','w','x','y','z'); $code = $letters; shuffle($code); $key = array_combine($letters, $code); | 接下來,獲取 $_POST 中的輸入,將消息拆分為字母,然後將每個字母的值輸出到密鑰中。 清單 19. 分隔並輸出字母 在 $key[$letter] 之前使用 @ 符號將告訴 PHP 忽略在編碼期間發生的所有錯誤。如果消息有標點符號、數字或空格,PHP 將報告 $key 數組中沒有相應值。這沒問題。結果得到的編碼文本將去掉空格、數字和標點符號,從而使它(略微)更加難於解碼。
單詞搜索生成器 單詞搜索可能是我們學到的最早的基於字母的字謎。使用已有技術,再包括一些縱橫字謎助手中的邏輯,您就可以創建一個非常基本的單詞搜索生成器。為了保持簡單,您將創建一個大小為 10x10 個字母,裡面藏有 10 個單詞(垂直方向 5 個,水平方向 5 個)的單詞搜索。 第一部分,在水平方向放入單詞非常簡單 — 構建一個數組的數組,每個數組中有 10 個元素,用句點填充。然後在所有其他數組中,放入各個單詞的字母。要放入垂直方向的單詞,需要同時訪問所有數組,使用縱橫字謎助手代碼查找可能匹配的單詞。最棘手的部分可能是清單 20 中將單詞或者隨機字母填入垂直行(其中單詞短於整行)的部分。 清單 20. 在垂直行中填充單詞或者隨機字母 $wordletters = str_split($word); for ($c = 0; $c < $height; $c++) { if ( $grid[$c][$i] == '.' && ($c < $x || empty($wordletters))) { $grid[$c][$i] = $letters[rand(0,25)]; } else { if ($grid[$c][$i] == '.') { $grid[$c][$i] = array_shift($wordletters); } else if ($c >= $x) { array_shift($wordletters); } } } | 代碼歸檔 包含了許多註釋,可以幫助說明整個過程。該代碼還有很大的性能改進空間,但是這應當已經向您展示了如何動手處理問題的一般概念。嘗試代碼歸檔中的完整腳本以查看結果。
結束語 本文說明了如何獲取在 “用 PHP 可以編寫的 30 個遊戲腳本” 系列的 第 1 部分 中編寫的一些基本腳本,以及如何基於這些基本腳本進行構建以提供更健壯的腳本。在第 3 部分中,您將繼續基於本文構建的成果進一步提供更健壯、更有用的工具。(責任編輯:A6) POST['submit'] == 'faces') { $deck['faces']--; } | 然後通過查看修改後的牌組,可以計算抽到花牌、A 或其他牌的機率。 清單 13. 計算抽到花牌、A 或其他牌的機率 使用這個基本牌面計算器作為起點,您可以構建一些更健壯的程序。
Bingo 引擎 基於我們在本文中已經完成的內容,您可以輕鬆地整合一個 Bingo 引擎以生成牌並從池中抽出編號。 Bingo 編號範圍從 1 到 75,以 15 個編號為一組(1-15 分配給 B,16-30 分配給 I 等等)。按照構建並洗一副虛擬牌的相同方法,您可以構建並洗一套虛擬的 Bingo 球。但是您無需以相同方法跟蹤牌面和花色。首先,構建基本編號集。 清單 14. 構建 Bingo 的基本編號集 接下來,您可以置換每個子數組並且同時製作牌(不要忘記:中間的部分通常是一張任意的牌)。完成後,創建一個可用作牌組的主數組。 清單 15. 創建主數組 現在已經全部完成!分發牌,並開始從主集合中抽取虛擬 Bingo 球,就像先前抽牌所做的那樣。在 代碼歸檔 中可以找到此腳本的完整運行版本。
Jumble 助手 Jumble 是在大多數報紙中可以找到的字謎,您有一些已經完全混合在一起的單詞。您必須從廢話中提取出實際單詞來,然後使用某些字母來創造新短語。從在 第 1 部分 中創建的縱橫字謎助手開始,讓我們整合一個快速腳本以幫助您構建 Jumble。 首先,打開單詞列表。需要遍歷該列表,將每個單詞拆分為經過排序的字母數組,然後再次合併數組。例如,這樣做將把單詞 “COLOR” 改為字元串 “CLOOR”;該字元串表示單詞 “COLOR” 中的所有字母,但是按照可預測的(而且更重要的是相配的)順序。該字元串隨後將被用作匹配單詞的數組的關鍵字。它必須為數組,因為 “sword” 和 “words” 擁有完全相同的字母,但是順序不同。最後,它將類似如下所示的內容: 清單 16. Jumble 的腳本 完成到此為止的程序后,只需將 Jumble 像任何其他單詞一樣處理,查找相應關鍵字的值並輸出所有結果。 清單 17. 完成 Jumble 腳本 您可以在 代碼歸檔 中看到如何將這些內容整合在一起。
置換密碼 置換密碼 是一種簡單的加密技術,採用這項技術將把字母表中的每個字母替換為字母表中的其他字母。按照現代加密技術的標準,置換密碼簡直就是小兒科。但是簡單的置換密碼玩起來很有趣,尤其是在 RPG 環境中給某個人傳遞一條可以在玩遊戲的過程中破解出來的編碼信息。 首先從 第 1 部分 的 Hangman 生成器中偷一些代碼 — 也就是,字母數組。製作另外一份數組副本,攪亂該副本,並構建一個聯合數組,其中原來的字母將獲得重組后的值。 清單 18. 修改字母數組 接下來,獲取 $_POST 中的輸入,將消息拆分為字母,然後將每個字母的值輸出到密鑰中。 清單 19. 分隔並輸出字母 在 $key[$letter] 之前使用 @ 符號將告訴 PHP 忽略在編碼期間發生的所有錯誤。如果消息有標點符號、數字或空格,PHP 將報告 $key 數組中沒有相應值。這沒問題。結果得到的編碼文本將去掉空格、數字和標點符號,從而使它(略微)更加難於解碼。
單詞搜索生成器 單詞搜索可能是我們學到的最早的基於字母的字謎。使用已有技術,再包括一些縱橫字謎助手中的邏輯,您就可以創建一個非常基本的單詞搜索生成器。為了保持簡單,您將創建一個大小為 10x10 個字母,裡面藏有 10 個單詞(垂直方向 5 個,水平方向 5 個)的單詞搜索。 第一部分,在水平方向放入單詞非常簡單 — 構建一個數組的數組,每個數組中有 10 個元素,用句點填充。然後在所有其他數組中,放入各個單詞的字母。要放入垂直方向的單詞,需要同時訪問所有數組,使用縱橫字謎助手代碼查找可能匹配的單詞。最棘手的部分可能是清單 20 中將單詞或者隨機字母填入垂直行(其中單詞短於整行)的部分。 清單 20. 在垂直行中填充單詞或者隨機字母 代碼歸檔 包含了許多註釋,可以幫助說明整個過程。該代碼還有很大的性能改進空間,但是這應當已經向您展示了如何動手處理問題的一般概念。嘗試代碼歸檔中的完整腳本以查看結果。
結束語 本文說明了如何獲取在 “用 PHP 可以編寫的 30 個遊戲腳本” 系列的 第 1 部分 中編寫的一些基本腳本,以及如何基於這些基本腳本進行構建以提供更健壯的腳本。在第 3 部分中,您將繼續基於本文構建的成果進一步提供更健壯、更有用的工具。(責任編輯:A6) POST['jumble']); sort($arr); $search = implode('', $arr); if (isset($lookup[$search])) { foreach ($lookup[$search] as $word) { echo $word; } } | 您可以在 代碼歸檔 中看到如何將這些內容整合在一起。
置換密碼 置換密碼 是一種簡單的加密技術,採用這項技術將把字母表中的每個字母替換為字母表中的其他字母。按照現代加密技術的標準,置換密碼簡直就是小兒科。但是簡單的置換密碼玩起來很有趣,尤其是在 RPG 環境中給某個人傳遞一條可以在玩遊戲的過程中破解出來的編碼信息。 首先從 第 1 部分 的 Hangman 生成器中偷一些代碼 — 也就是,字母數組。製作另外一份數組副本,攪亂該副本,並構建一個聯合數組,其中原來的字母將獲得重組后的值。 清單 18. 修改字母數組 接下來,獲取 $_POST 中的輸入,將消息拆分為字母,然後將每個字母的值輸出到密鑰中。 清單 19. 分隔並輸出字母 在 $key[$letter] 之前使用 @ 符號將告訴 PHP 忽略在編碼期間發生的所有錯誤。如果消息有標點符號、數字或空格,PHP 將報告 $key 數組中沒有相應值。這沒問題。結果得到的編碼文本將去掉空格、數字和標點符號,從而使它(略微)更加難於解碼。
單詞搜索生成器 單詞搜索可能是我們學到的最早的基於字母的字謎。使用已有技術,再包括一些縱橫字謎助手中的邏輯,您就可以創建一個非常基本的單詞搜索生成器。為了保持簡單,您將創建一個大小為 10x10 個字母,裡面藏有 10 個單詞(垂直方向 5 個,水平方向 5 個)的單詞搜索。 第一部分,在水平方向放入單詞非常簡單 — 構建一個數組的數組,每個數組中有 10 個元素,用句點填充。然後在所有其他數組中,放入各個單詞的字母。要放入垂直方向的單詞,需要同時訪問所有數組,使用縱橫字謎助手代碼查找可能匹配的單詞。最棘手的部分可能是清單 20 中將單詞或者隨機字母填入垂直行(其中單詞短於整行)的部分。 清單 20. 在垂直行中填充單詞或者隨機字母 代碼歸檔 包含了許多註釋,可以幫助說明整個過程。該代碼還有很大的性能改進空間,但是這應當已經向您展示了如何動手處理問題的一般概念。嘗試代碼歸檔中的完整腳本以查看結果。
結束語 本文說明了如何獲取在 “用 PHP 可以編寫的 30 個遊戲腳本” 系列的 第 1 部分 中編寫的一些基本腳本,以及如何基於這些基本腳本進行構建以提供更健壯的腳本。在第 3 部分中,您將繼續基於本文構建的成果進一步提供更健壯、更有用的工具。(責任編輯:A6) POST['submit'] == 'faces') { $deck['faces']--; } | 然後通過查看修改後的牌組,可以計算抽到花牌、A 或其他牌的機率。 清單 13. 計算抽到花牌、A 或其他牌的機率 使用這個基本牌面計算器作為起點,您可以構建一些更健壯的程序。
Bingo 引擎 基於我們在本文中已經完成的內容,您可以輕鬆地整合一個 Bingo 引擎以生成牌並從池中抽出編號。 Bingo 編號範圍從 1 到 75,以 15 個編號為一組(1-15 分配給 B,16-30 分配給 I 等等)。按照構建並洗一副虛擬牌的相同方法,您可以構建並洗一套虛擬的 Bingo 球。但是您無需以相同方法跟蹤牌面和花色。首先,構建基本編號集。 清單 14. 構建 Bingo 的基本編號集 接下來,您可以置換每個子數組並且同時製作牌(不要忘記:中間的部分通常是一張任意的牌)。完成後,創建一個可用作牌組的主數組。 清單 15. 創建主數組 現在已經全部完成!分發牌,並開始從主集合中抽取虛擬 Bingo 球,就像先前抽牌所做的那樣。在 代碼歸檔 中可以找到此腳本的完整運行版本。
Jumble 助手 Jumble 是在大多數報紙中可以找到的字謎,您有一些已經完全混合在一起的單詞。您必須從廢話中提取出實際單詞來,然後使用某些字母來創造新短語。從在 第 1 部分 中創建的縱橫字謎助手開始,讓我們整合一個快速腳本以幫助您構建 Jumble。 首先,打開單詞列表。需要遍歷該列表,將每個單詞拆分為經過排序的字母數組,然後再次合併數組。例如,這樣做將把單詞 “COLOR” 改為字元串 “CLOOR”;該字元串表示單詞 “COLOR” 中的所有字母,但是按照可預測的(而且更重要的是相配的)順序。該字元串隨後將被用作匹配單詞的數組的關鍵字。它必須為數組,因為 “sword” 和 “words” 擁有完全相同的字母,但是順序不同。最後,它將類似如下所示的內容: 清單 16. Jumble 的腳本 完成到此為止的程序后,只需將 Jumble 像任何其他單詞一樣處理,查找相應關鍵字的值並輸出所有結果。 清單 17. 完成 Jumble 腳本 您可以在 代碼歸檔 中看到如何將這些內容整合在一起。
置換密碼 置換密碼 是一種簡單的加密技術,採用這項技術將把字母表中的每個字母替換為字母表中的其他字母。按照現代加密技術的標準,置換密碼簡直就是小兒科。但是簡單的置換密碼玩起來很有趣,尤其是在 RPG 環境中給某個人傳遞一條可以在玩遊戲的過程中破解出來的編碼信息。 首先從 第 1 部分 的 Hangman 生成器中偷一些代碼 — 也就是,字母數組。製作另外一份數組副本,攪亂該副本,並構建一個聯合數組,其中原來的字母將獲得重組后的值。 清單 18. 修改字母數組 接下來,獲取 $_POST 中的輸入,將消息拆分為字母,然後將每個字母的值輸出到密鑰中。 清單 19. 分隔並輸出字母 在 $key[$letter] 之前使用 @ 符號將告訴 PHP 忽略在編碼期間發生的所有錯誤。如果消息有標點符號、數字或空格,PHP 將報告 $key 數組中沒有相應值。這沒問題。結果得到的編碼文本將去掉空格、數字和標點符號,從而使它(略微)更加難於解碼。
單詞搜索生成器 單詞搜索可能是我們學到的最早的基於字母的字謎。使用已有技術,再包括一些縱橫字謎助手中的邏輯,您就可以創建一個非常基本的單詞搜索生成器。為了保持簡單,您將創建一個大小為 10x10 個字母,裡面藏有 10 個單詞(垂直方向 5 個,水平方向 5 個)的單詞搜索。 第一部分,在水平方向放入單詞非常簡單 — 構建一個數組的數組,每個數組中有 10 個元素,用句點填充。然後在所有其他數組中,放入各個單詞的字母。要放入垂直方向的單詞,需要同時訪問所有數組,使用縱橫字謎助手代碼查找可能匹配的單詞。最棘手的部分可能是清單 20 中將單詞或者隨機字母填入垂直行(其中單詞短於整行)的部分。 清單 20. 在垂直行中填充單詞或者隨機字母 代碼歸檔 包含了許多註釋,可以幫助說明整個過程。該代碼還有很大的性能改進空間,但是這應當已經向您展示了如何動手處理問題的一般概念。嘗試代碼歸檔中的完整腳本以查看結果。
結束語 本文說明了如何獲取在 “用 PHP 可以編寫的 30 個遊戲腳本” 系列的 第 1 部分 中編寫的一些基本腳本,以及如何基於這些基本腳本進行構建以提供更健壯的腳本。在第 3 部分中,您將繼續基於本文構建的成果進一步提供更健壯、更有用的工具。(責任編輯:A6) POST)) { $messageletters = str_split(strtolower(PHP 是一種易於使用、易於學習且可以廣泛獲取的編程語言。它非常適合開發在各種遊戲中可以使用的簡單腳本。無論是一個人玩簡單的使用紙和筆的遊戲,還是同一群人玩複雜的桌面角色扮演遊戲,或者任意類型的聯機遊戲,本系列都提供了適合您的內容。本文將在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 基礎上,探究可以在各種類型的遊戲中使用的 10 個中級腳本。這些腳本適用於三種遊戲:角色扮演遊戲、機率遊戲和文字遊戲。 在本系列的 第 1 部分 中,您創建了一些初學者級別的 PHP 腳本。現在是時候提高要求來增加一些複雜度,進一步拓展您的 PHP 編程技能並提高您作為遊戲專家的地位。 對於角色扮演遊戲腳本,您將了解如何整合武器的破壞力計算器、特徵表統計跟蹤器及非玩家角色(Non-Player Character,NPC)生成器,同時教您如何將信息保存到文件中以及如何與 PHP 中的數組結合使用。與機率遊戲相關的腳本將幫助您練習 Blackjack,學習如何算牌,並且快速了解 Bingo(一種賭博遊戲)的基本規則,同時教您如何將機率元素插入到 PHP 腳本中。最後,文字遊戲腳本將幫助您解決 Jumble 遊戲,創建簡單的置換計算程序,並生成文字搜索圖,同時讓您的 PHP 數組處理技能更上一層樓。 我們將快速地介紹這些腳本,而不會討論如何查找主機或設置伺服器。有很多 Web 託管公司提供 PHP,並且如果需要安裝自己的 PHP,XAMPP 安裝程序使用起來也十分簡單。我們將不會花費大量時間談論 PHP 最佳實踐或遊戲設計技術。本文介紹的腳本易於理解、使用簡單並可以快速掌握。 本文的 代碼歸檔 包含所討論的每個腳本的完整源代碼,並且可以訪問 Chaoticneutral.net 查看腳本實際運行情況。 破壞力計算器 在 第 1 部分中,我們構建了一個基本的擲骰器。讓我們查看一下如何使用該擲骰器幫助整合基本的破壞力計算器。 如果您曾經運行或者玩過桌面角色扮演遊戲,則可能已經看到過書中附帶的大型武器圖表。通常,這些圖表包括武器名稱及武器的破壞力有多大。它可能類似表 1 中所示的內容。 表 1. 破壞力計算器 武器名稱 | 破壞力 | Little Stick | 1d6 | Big Stick | 1d6+4 | Chainsaw | 2d8 | 您應當能夠得到在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 中創建的簡單 roll 函數,並且使用它計算一套基本武器的破壞力。為此,需要創建一個數組來保存關於武器的信息。 對於本例,一個武器有三個基本特性:名稱(Name)、擲骰(Die Roll)和傷害獎勵(Damage Bonus)。使用這些特性,您可以構建武器數組,如下所示: 清單 1. 武器數組 $weapons = array ( 'littlestick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '0', ), 'bigstick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '4', ), 'chainsaw' => array ( 'name' => 'Little Stick', 'roll' => '2d8', 'bonus' => '0', ), ); | 使用此數組,您可以構建一張顯示武器、武器的破壞力及傷害判定結果表。 清單 2. 構建武器表 foreach ($weapons as $weapon) { list($count, $sides) = explode('d', $weapon['roll']); $result = 0; for ($i = 0; $i < $count;$i++) { $result = $result + roll($sides); } echo "<tr><td>" . $weapon['name'] . "</td><td>" . $weapon['roll']; if ($weapon['bonus'] > 0) { echo "+" . $weapon['bonus']; $result = $result + $weapon['bonus']; } echo "</td><td>" . $result . "</td></tr>"; } | 使用此腳本,您可以用集成的破壞力計算器創建基本武器圖。
統計跟蹤 現在已經可以計算破壞力,讓我們查看如何跟蹤一些基本任務統計信息,這種功能在要運行帶有多個 NPC 的遊戲時可能需要使用。創建一個簡單數組來保存人物信息並將其另存(序列化)為文本文件(將這些信息保存到資料庫中有許多方法,並且在您逐漸熟悉如何使用 PHP 后應當保存到資料庫)。對於本例,您將通過我編寫的名為 Shambles 的遊戲創建一個基本的怪物角色。首先建立一個數組以保存角色信息。 清單 3. 角色信息數組 $character = array( 'name' => 'Fred The Zombie', 'health' => '36', 'gore' => '1', 'clutch' => '5', 'brawn' => '6', 'sense' => '4', 'flail' => '2', 'chuck' => '3', 'lurch' => '4', ); | 需要生成文件名以保存這些信息。實際上不需要在傳入時就使用輸入,但是只可以使用人物姓名中的字母創建文件。 清單 4. 創建用於存儲信息的文件 $filename = substr(preg_replace("/[^a-z0-9]/", "", strtolower($character['name'])), 0, 20); file_put_contents($filename, serialize($character)); | 註:在將該腳本提供給公共使用時,需要過濾用戶輸入以避免有人將錯誤的 JavaScript 代碼或垃圾代碼惡意插入文件中。這只是供您個人使用的示例。最後,需要用表單表示信息以便可以輕鬆更新。這隻需使用輸入欄位中的默認值創建一張表單。 清單 5. 用表單顯示信息 <input name='health' value='<?php echo $character['health'] ?>' /> | 使用此基本腳本(請參閱 代碼歸檔)跟蹤幾個角色和 NPC。
NPC 生成器 在整合一個大型遊戲時,擁有一個一次性的 NPC 池十分有用。如果需要大量暴徒或者士兵,這樣做尤其有幫助。要整合 NPC 生成器,讓我們構建一個包含構造角色規則的數組,然後使用隨機姓名生成器及擲骰器一次性整合一批角色。 使用 Fred the Zombie 作為示例,您可以定義創建角色的規則。某些統計信息是固定的(生命力總是從 36 開始),某些統計信息是派生的(血=生命力/6),而某些統計信息是擲骰的結果(離合器是 1d6 — 一個六面骰子)。規則類似清單 6 中所示的內容。 清單 6. 定義角色創建的規則 $rules = array( 'health' => '36', 'gore' => 'health/6', 'clutch' => '1d6', 'brawn' => '1d6', 'sense' => '1d6', 'flail' => '1d6', 'chuck' => '1d6', 'lurch' => '1d6', ); | 現在您可以編寫少量代碼來評估規則。 清單 7. 評估規則的代碼 foreach ($rules as $stat=>$rule) { if (preg_match("/^[0-9]+$/", $rule)) { // This is only a number, and is therefore a static value $character[$stat] = $rule; } else if (preg_match("/^([0-9]+)d([0-9]+)/", $rule, $matches)) { // This is a die roll $val = 0; for ($n = 0;$n<$matches[1];$n++) { $val = $val + roll($matches[2]); } $character[$stat] = $val; } else if (preg_match("/^([a-z]+)\/([0-9]+)$/", $rule, $matches)) { // This is a derived value of some kind. $character[$stat] = $character[$matches[1]] / $matches[2]; } echo $stat . ' : ' . $character[$stat] . "<br />\n"; } | 在正確評估規則時,您可以引入使用隨機姓名生成器生成的隨機姓名並且一連幾天製作 NPC。請查看 代碼歸檔 中的腳本了解如何整合該任務。
機率計算器:擲骰 在 第 1 部分 中,您整合了一個簡單的機率計算器以確定從給定的一副牌中抽到指定牌面或花色的機率。現在讓我們構建一個擲骰機率計算器。對於本例,您將構建一個在擲兩個六面骰子(2d6)時確定可能結果的計算器。如果使用的是基於 d6 的任何 RPG 系統,玩大富豪或雙陸棋之類的棋盤類遊戲,或者要嘗試在諸如 Craps 之類的骰子遊戲中計算出機率,這將十分有用。 首先,建立在擲兩個骰子時確定可能結果的方法。可以考慮擲兩個不同顏色的骰子(如一個紅色骰子和一個藍色骰子)。如果擲紅色骰子的結果為 1,則有六個可能的結果,每個結果取決於藍色骰子的一面。這意味著可能的擲骰結果總數為 6^2 即 36 個結果。這可能看似有些奇怪,因為您實際上可以得到的最高值為 12(紅色六點加藍色六點),但是如果您認識到可以通過兩個不同的結果得到 11(紅色六點加藍色五點,或者紅色五點加藍色六點)應當更有意義。 讓我們假定,在本例中,您需要同時獲得總和(擲出 10)和骰面(擲出 6 和 4)結果,並且紅色骰子的 6 點與藍色骰子的 6 點沒有差別。重要的數字為 S(骰子面數)和 N(骰子個數)— 假定有 N 個相同的骰子,最大結果數為 S^N — 可是這其中的一些結果可能相同(一個 6 和一個 4,以及一個 4 和一個 6)。 清單 8. 構建擲骰機率計算器 $s = 6; $n = 2; $results = array(array()); for ($i = 0; $i < $n; $i ++) { $newresults = array(); foreach ($results as $result) { for ($x = 0; $x < $s; $x++) { $newresults[] = array_merge($result, array($x+1)); } } $results = $newresults; } | 這可能看似有些沉悶。您可以適當地簡化這段代碼,但是我已經在這裡完成了一些更明顯的操作,因此您可以了解數組是如何處理的。在構建完最終數組后,您可以迭代數組並生成骰子數總和的列表及其各自的機率。這段代碼包含在 代碼歸檔 中。
簡單的 Blackjack 撲克發牌器 在 第 1 部分 中,您構建了一個簡單的撲克發牌器。該發牌器不是真正地在與您玩牌;它只是發出牌盒中的牌,從而允許您開始各種牌局。現在讓我們構建一個真正與您玩牌的 Blackjack 發牌器。使用發牌器必須至少抽到 17 的簡單內部規則構建此發牌器。 這部分代碼將類似先前構建的簡單的撲克發牌器。對於 Blackjack,您需要以迭代抽取及牌局評估的形式構建。您將需要一個把牌面值指定為數字描述的數組。如果更改構建牌組的方法,您可以在原始的 $faces 數組中完成此操作。 清單 9. 修改 Blackjack 的 $faces 數組 $faces = array('Two' => 2, ... ... ... 'King' => 10, 'Ace' => 11); | 然後您需要一個基本函數來評估給定的牌局。該函數將查看手中的牌並返回手上的牌面總值。 清單 10. 評估給定牌局的函數 function evaluateHand($hand) { global $faces; $value = 0; foreach ($hand as $card) { if ($value > 11 && $card['face'] == 'Ace') { $value = $value + 1; // An ace can be 11 or 1 } else { $value = intval($value) + intval($faces[$card['face']]); } } return $value; } | 在評估手上牌局的函數就緒后,應當很容易確定您手上的牌是否超過 21 點,或者發牌器是否應當要牌。有關如何整合所有這些內容的詳細信息,請參閱 代碼歸檔。
牌面計算器 在玩 Blackjack 或者諸如紅心大戰之類基於王牌的遊戲時,知道如何算牌會十分有用。在玩 Blackjack 時,至少需要知道已經看到多少張 A 和花牌。對於紅心大戰,您可能需要知道遊戲中還有多少王牌。您將構建一個 Blackjack 基本計算器。您可以採用相同原理構建王牌遊戲的牌面計算器。 您將構建以略微不同的方式進行計算的牌組。您不必知道所有牌 — 只關注自己感興趣的牌。對於單牌組牌盒,則類似如下所示: 清單 11. 構建單牌組牌盒的牌面計算器 $deck = array ( 'faces' => 16, // 10,J,Q,K * 4 suits 'aces' => 4, // One per suit 'other' => 32, // 52 - (16 + 4) ); | 接下來,構建一張帶有三個按鈕的表單 — 一個用於花牌,一個用於 A,而另一個用於其他牌。通過在每次看到特定類型的牌時單擊相應按鈕,您可以調整留在牌組中的牌。 清單 12. 帶有三個按鈕的簡單表單 if (PHP 是一種易於使用、易於學習且可以廣泛獲取的編程語言。它非常適合開發在各種遊戲中可以使用的簡單腳本。無論是一個人玩簡單的使用紙和筆的遊戲,還是同一群人玩複雜的桌面角色扮演遊戲,或者任意類型的聯機遊戲,本系列都提供了適合您的內容。本文將在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 基礎上,探究可以在各種類型的遊戲中使用的 10 個中級腳本。這些腳本適用於三種遊戲:角色扮演遊戲、機率遊戲和文字遊戲。 在本系列的 第 1 部分 中,您創建了一些初學者級別的 PHP 腳本。現在是時候提高要求來增加一些複雜度,進一步拓展您的 PHP 編程技能並提高您作為遊戲專家的地位。 對於角色扮演遊戲腳本,您將了解如何整合武器的破壞力計算器、特徵表統計跟蹤器及非玩家角色(Non-Player Character,NPC)生成器,同時教您如何將信息保存到文件中以及如何與 PHP 中的數組結合使用。與機率遊戲相關的腳本將幫助您練習 Blackjack,學習如何算牌,並且快速了解 Bingo(一種賭博遊戲)的基本規則,同時教您如何將機率元素插入到 PHP 腳本中。最後,文字遊戲腳本將幫助您解決 Jumble 遊戲,創建簡單的置換計算程序,並生成文字搜索圖,同時讓您的 PHP 數組處理技能更上一層樓。 我們將快速地介紹這些腳本,而不會討論如何查找主機或設置伺服器。有很多 Web 託管公司提供 PHP,並且如果需要安裝自己的 PHP,XAMPP 安裝程序使用起來也十分簡單。我們將不會花費大量時間談論 PHP 最佳實踐或遊戲設計技術。本文介紹的腳本易於理解、使用簡單並可以快速掌握。 本文的 代碼歸檔 包含所討論的每個腳本的完整源代碼,並且可以訪問 Chaoticneutral.net 查看腳本實際運行情況。 破壞力計算器 在 第 1 部分中,我們構建了一個基本的擲骰器。讓我們查看一下如何使用該擲骰器幫助整合基本的破壞力計算器。 如果您曾經運行或者玩過桌面角色扮演遊戲,則可能已經看到過書中附帶的大型武器圖表。通常,這些圖表包括武器名稱及武器的破壞力有多大。它可能類似表 1 中所示的內容。 表 1. 破壞力計算器 武器名稱 | 破壞力 | Little Stick | 1d6 | Big Stick | 1d6+4 | Chainsaw | 2d8 | 您應當能夠得到在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 中創建的簡單 roll 函數,並且使用它計算一套基本武器的破壞力。為此,需要創建一個數組來保存關於武器的信息。 對於本例,一個武器有三個基本特性:名稱(Name)、擲骰(Die Roll)和傷害獎勵(Damage Bonus)。使用這些特性,您可以構建武器數組,如下所示: 清單 1. 武器數組 $weapons = array ( 'littlestick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '0', ), 'bigstick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '4', ), 'chainsaw' => array ( 'name' => 'Little Stick', 'roll' => '2d8', 'bonus' => '0', ), ); | 使用此數組,您可以構建一張顯示武器、武器的破壞力及傷害判定結果表。 清單 2. 構建武器表 foreach ($weapons as $weapon) { list($count, $sides) = explode('d', $weapon['roll']); $result = 0; for ($i = 0; $i < $count;$i++) { $result = $result + roll($sides); } echo "<tr><td>" . $weapon['name'] . "</td><td>" . $weapon['roll']; if ($weapon['bonus'] > 0) { echo "+" . $weapon['bonus']; $result = $result + $weapon['bonus']; } echo "</td><td>" . $result . "</td></tr>"; } | 使用此腳本,您可以用集成的破壞力計算器創建基本武器圖。
統計跟蹤 現在已經可以計算破壞力,讓我們查看如何跟蹤一些基本任務統計信息,這種功能在要運行帶有多個 NPC 的遊戲時可能需要使用。創建一個簡單數組來保存人物信息並將其另存(序列化)為文本文件(將這些信息保存到資料庫中有許多方法,並且在您逐漸熟悉如何使用 PHP 后應當保存到資料庫)。對於本例,您將通過我編寫的名為 Shambles 的遊戲創建一個基本的怪物角色。首先建立一個數組以保存角色信息。 清單 3. 角色信息數組 $character = array( 'name' => 'Fred The Zombie', 'health' => '36', 'gore' => '1', 'clutch' => '5', 'brawn' => '6', 'sense' => '4', 'flail' => '2', 'chuck' => '3', 'lurch' => '4', ); | 需要生成文件名以保存這些信息。實際上不需要在傳入時就使用輸入,但是只可以使用人物姓名中的字母創建文件。 清單 4. 創建用於存儲信息的文件 $filename = substr(preg_replace("/[^a-z0-9]/", "", strtolower($character['name'])), 0, 20); file_put_contents($filename, serialize($character)); | 註:在將該腳本提供給公共使用時,需要過濾用戶輸入以避免有人將錯誤的 JavaScript 代碼或垃圾代碼惡意插入文件中。這只是供您個人使用的示例。最後,需要用表單表示信息以便可以輕鬆更新。這隻需使用輸入欄位中的默認值創建一張表單。 清單 5. 用表單顯示信息 <input name='health' value='<?php echo $character['health'] ?>' /> | 使用此基本腳本(請參閱 代碼歸檔)跟蹤幾個角色和 NPC。
NPC 生成器 在整合一個大型遊戲時,擁有一個一次性的 NPC 池十分有用。如果需要大量暴徒或者士兵,這樣做尤其有幫助。要整合 NPC 生成器,讓我們構建一個包含構造角色規則的數組,然後使用隨機姓名生成器及擲骰器一次性整合一批角色。 使用 Fred the Zombie 作為示例,您可以定義創建角色的規則。某些統計信息是固定的(生命力總是從 36 開始),某些統計信息是派生的(血=生命力/6),而某些統計信息是擲骰的結果(離合器是 1d6 — 一個六面骰子)。規則類似清單 6 中所示的內容。 清單 6. 定義角色創建的規則 $rules = array( 'health' => '36', 'gore' => 'health/6', 'clutch' => '1d6', 'brawn' => '1d6', 'sense' => '1d6', 'flail' => '1d6', 'chuck' => '1d6', 'lurch' => '1d6', ); | 現在您可以編寫少量代碼來評估規則。 清單 7. 評估規則的代碼 foreach ($rules as $stat=>$rule) { if (preg_match("/^[0-9]+$/", $rule)) { // This is only a number, and is therefore a static value $character[$stat] = $rule; } else if (preg_match("/^([0-9]+)d([0-9]+)/", $rule, $matches)) { // This is a die roll $val = 0; for ($n = 0;$n<$matches[1];$n++) { $val = $val + roll($matches[2]); } $character[$stat] = $val; } else if (preg_match("/^([a-z]+)\/([0-9]+)$/", $rule, $matches)) { // This is a derived value of some kind. $character[$stat] = $character[$matches[1]] / $matches[2]; } echo $stat . ' : ' . $character[$stat] . "<br />\n"; } | 在正確評估規則時,您可以引入使用隨機姓名生成器生成的隨機姓名並且一連幾天製作 NPC。請查看 代碼歸檔 中的腳本了解如何整合該任務。
機率計算器:擲骰 在 第 1 部分 中,您整合了一個簡單的機率計算器以確定從給定的一副牌中抽到指定牌面或花色的機率。現在讓我們構建一個擲骰機率計算器。對於本例,您將構建一個在擲兩個六面骰子(2d6)時確定可能結果的計算器。如果使用的是基於 d6 的任何 RPG 系統,玩大富豪或雙陸棋之類的棋盤類遊戲,或者要嘗試在諸如 Craps 之類的骰子遊戲中計算出機率,這將十分有用。 首先,建立在擲兩個骰子時確定可能結果的方法。可以考慮擲兩個不同顏色的骰子(如一個紅色骰子和一個藍色骰子)。如果擲紅色骰子的結果為 1,則有六個可能的結果,每個結果取決於藍色骰子的一面。這意味著可能的擲骰結果總數為 6^2 即 36 個結果。這可能看似有些奇怪,因為您實際上可以得到的最高值為 12(紅色六點加藍色六點),但是如果您認識到可以通過兩個不同的結果得到 11(紅色六點加藍色五點,或者紅色五點加藍色六點)應當更有意義。 讓我們假定,在本例中,您需要同時獲得總和(擲出 10)和骰面(擲出 6 和 4)結果,並且紅色骰子的 6 點與藍色骰子的 6 點沒有差別。重要的數字為 S(骰子面數)和 N(骰子個數)— 假定有 N 個相同的骰子,最大結果數為 S^N — 可是這其中的一些結果可能相同(一個 6 和一個 4,以及一個 4 和一個 6)。 清單 8. 構建擲骰機率計算器 $s = 6; $n = 2; $results = array(array()); for ($i = 0; $i < $n; $i ++) { $newresults = array(); foreach ($results as $result) { for ($x = 0; $x < $s; $x++) { $newresults[] = array_merge($result, array($x+1)); } } $results = $newresults; } | 這可能看似有些沉悶。您可以適當地簡化這段代碼,但是我已經在這裡完成了一些更明顯的操作,因此您可以了解數組是如何處理的。在構建完最終數組后,您可以迭代數組並生成骰子數總和的列表及其各自的機率。這段代碼包含在 代碼歸檔 中。
簡單的 Blackjack 撲克發牌器 在 第 1 部分 中,您構建了一個簡單的撲克發牌器。該發牌器不是真正地在與您玩牌;它只是發出牌盒中的牌,從而允許您開始各種牌局。現在讓我們構建一個真正與您玩牌的 Blackjack 發牌器。使用發牌器必須至少抽到 17 的簡單內部規則構建此發牌器。 這部分代碼將類似先前構建的簡單的撲克發牌器。對於 Blackjack,您需要以迭代抽取及牌局評估的形式構建。您將需要一個把牌面值指定為數字描述的數組。如果更改構建牌組的方法,您可以在原始的 $faces 數組中完成此操作。 清單 9. 修改 Blackjack 的 $faces 數組 $faces = array('Two' => 2, ... ... ... 'King' => 10, 'Ace' => 11); | 然後您需要一個基本函數來評估給定的牌局。該函數將查看手中的牌並返回手上的牌面總值。 清單 10. 評估給定牌局的函數 function evaluateHand($hand) { global $faces; $value = 0; foreach ($hand as $card) { if ($value > 11 && $card['face'] == 'Ace') { $value = $value + 1; // An ace can be 11 or 1 } else { $value = intval($value) + intval($faces[$card['face']]); } } return $value; } | 在評估手上牌局的函數就緒后,應當很容易確定您手上的牌是否超過 21 點,或者發牌器是否應當要牌。有關如何整合所有這些內容的詳細信息,請參閱 代碼歸檔。
牌面計算器 在玩 Blackjack 或者諸如紅心大戰之類基於王牌的遊戲時,知道如何算牌會十分有用。在玩 Blackjack 時,至少需要知道已經看到多少張 A 和花牌。對於紅心大戰,您可能需要知道遊戲中還有多少王牌。您將構建一個 Blackjack 基本計算器。您可以採用相同原理構建王牌遊戲的牌面計算器。 您將構建以略微不同的方式進行計算的牌組。您不必知道所有牌 — 只關注自己感興趣的牌。對於單牌組牌盒,則類似如下所示: 清單 11. 構建單牌組牌盒的牌面計算器 $deck = array ( 'faces' => 16, // 10,J,Q,K * 4 suits 'aces' => 4, // One per suit 'other' => 32, // 52 - (16 + 4) ); | 接下來,構建一張帶有三個按鈕的表單 — 一個用於花牌,一個用於 A,而另一個用於其他牌。通過在每次看到特定類型的牌時單擊相應按鈕,您可以調整留在牌組中的牌。 清單 12. 帶有三個按鈕的簡單表單 然後通過查看修改後的牌組,可以計算抽到花牌、A 或其他牌的機率。 清單 13. 計算抽到花牌、A 或其他牌的機率 echo "Odds of pulling a face: " . $deck['faces'] . " out of " . $deck['faces'] + $deck['aces'] + $deck['other']; | 使用這個基本牌面計算器作為起點,您可以構建一些更健壯的程序。
Bingo 引擎 基於我們在本文中已經完成的內容,您可以輕鬆地整合一個 Bingo 引擎以生成牌並從池中抽出編號。 Bingo 編號範圍從 1 到 75,以 15 個編號為一組(1-15 分配給 B,16-30 分配給 I 等等)。按照構建並洗一副虛擬牌的相同方法,您可以構建並洗一套虛擬的 Bingo 球。但是您無需以相同方法跟蹤牌面和花色。首先,構建基本編號集。 清單 14. 構建 Bingo 的基本編號集 for ($i = 1; $i < 16; $i++) { $numbers['B'][] = $i; $numbers['I'][] = $i+15; $numbers['N'][] = $i+30; $numbers['G'][] = $i+45; $numbers['O'][] = $i+60; } | 接下來,您可以置換每個子數組並且同時製作牌(不要忘記:中間的部分通常是一張任意的牌)。完成後,創建一個可用作牌組的主數組。 清單 15. 創建主數組 $letters = array ('B','I','N','G','O'); foreach ($letters as $letter) { shuffle($numbers[$letter]); $chunks = array_chunk($numbers[$letter], 5); $cards[$i][$letter] = $chunks[0]; if ($letter == 'N') { $cards[$i][$letter][2] = ' '; // Free Space } shuffle($balls); } | 現在已經全部完成!分發牌,並開始從主集合中抽取虛擬 Bingo 球,就像先前抽牌所做的那樣。在 代碼歸檔 中可以找到此腳本的完整運行版本。
Jumble 助手 Jumble 是在大多數報紙中可以找到的字謎,您有一些已經完全混合在一起的單詞。您必須從廢話中提取出實際單詞來,然後使用某些字母來創造新短語。從在 第 1 部分 中創建的縱橫字謎助手開始,讓我們整合一個快速腳本以幫助您構建 Jumble。 首先,打開單詞列表。需要遍歷該列表,將每個單詞拆分為經過排序的字母數組,然後再次合併數組。例如,這樣做將把單詞 “COLOR” 改為字元串 “CLOOR”;該字元串表示單詞 “COLOR” 中的所有字母,但是按照可預測的(而且更重要的是相配的)順序。該字元串隨後將被用作匹配單詞的數組的關鍵字。它必須為數組,因為 “sword” 和 “words” 擁有完全相同的字母,但是順序不同。最後,它將類似如下所示的內容: 清單 16. Jumble 的腳本 foreach ($words as $word) { $arr = str_split($word); sort($arr); $key = implode('', $arr); if (isset($lookup[$key])) { array_push($lookup[$key], $word); } else { $lookup[$key] = array($word); } } | 完成到此為止的程序后,只需將 Jumble 像任何其他單詞一樣處理,查找相應關鍵字的值並輸出所有結果。 清單 17. 完成 Jumble 腳本 $arr = str_split(PHP 是一種易於使用、易於學習且可以廣泛獲取的編程語言。它非常適合開發在各種遊戲中可以使用的簡單腳本。無論是一個人玩簡單的使用紙和筆的遊戲,還是同一群人玩複雜的桌面角色扮演遊戲,或者任意類型的聯機遊戲,本系列都提供了適合您的內容。本文將在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 基礎上,探究可以在各種類型的遊戲中使用的 10 個中級腳本。這些腳本適用於三種遊戲:角色扮演遊戲、機率遊戲和文字遊戲。 在本系列的 第 1 部分 中,您創建了一些初學者級別的 PHP 腳本。現在是時候提高要求來增加一些複雜度,進一步拓展您的 PHP 編程技能並提高您作為遊戲專家的地位。 對於角色扮演遊戲腳本,您將了解如何整合武器的破壞力計算器、特徵表統計跟蹤器及非玩家角色(Non-Player Character,NPC)生成器,同時教您如何將信息保存到文件中以及如何與 PHP 中的數組結合使用。與機率遊戲相關的腳本將幫助您練習 Blackjack,學習如何算牌,並且快速了解 Bingo(一種賭博遊戲)的基本規則,同時教您如何將機率元素插入到 PHP 腳本中。最後,文字遊戲腳本將幫助您解決 Jumble 遊戲,創建簡單的置換計算程序,並生成文字搜索圖,同時讓您的 PHP 數組處理技能更上一層樓。 我們將快速地介紹這些腳本,而不會討論如何查找主機或設置伺服器。有很多 Web 託管公司提供 PHP,並且如果需要安裝自己的 PHP,XAMPP 安裝程序使用起來也十分簡單。我們將不會花費大量時間談論 PHP 最佳實踐或遊戲設計技術。本文介紹的腳本易於理解、使用簡單並可以快速掌握。 本文的 代碼歸檔 包含所討論的每個腳本的完整源代碼,並且可以訪問 Chaoticneutral.net 查看腳本實際運行情況。 破壞力計算器 在 第 1 部分中,我們構建了一個基本的擲骰器。讓我們查看一下如何使用該擲骰器幫助整合基本的破壞力計算器。 如果您曾經運行或者玩過桌面角色扮演遊戲,則可能已經看到過書中附帶的大型武器圖表。通常,這些圖表包括武器名稱及武器的破壞力有多大。它可能類似表 1 中所示的內容。 表 1. 破壞力計算器 武器名稱 | 破壞力 | Little Stick | 1d6 | Big Stick | 1d6+4 | Chainsaw | 2d8 | 您應當能夠得到在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 中創建的簡單 roll 函數,並且使用它計算一套基本武器的破壞力。為此,需要創建一個數組來保存關於武器的信息。 對於本例,一個武器有三個基本特性:名稱(Name)、擲骰(Die Roll)和傷害獎勵(Damage Bonus)。使用這些特性,您可以構建武器數組,如下所示: 清單 1. 武器數組 $weapons = array ( 'littlestick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '0', ), 'bigstick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '4', ), 'chainsaw' => array ( 'name' => 'Little Stick', 'roll' => '2d8', 'bonus' => '0', ), ); | 使用此數組,您可以構建一張顯示武器、武器的破壞力及傷害判定結果表。 清單 2. 構建武器表 foreach ($weapons as $weapon) { list($count, $sides) = explode('d', $weapon['roll']); $result = 0; for ($i = 0; $i < $count;$i++) { $result = $result + roll($sides); } echo "<tr><td>" . $weapon['name'] . "</td><td>" . $weapon['roll']; if ($weapon['bonus'] > 0) { echo "+" . $weapon['bonus']; $result = $result + $weapon['bonus']; } echo "</td><td>" . $result . "</td></tr>"; } | 使用此腳本,您可以用集成的破壞力計算器創建基本武器圖。
統計跟蹤 現在已經可以計算破壞力,讓我們查看如何跟蹤一些基本任務統計信息,這種功能在要運行帶有多個 NPC 的遊戲時可能需要使用。創建一個簡單數組來保存人物信息並將其另存(序列化)為文本文件(將這些信息保存到資料庫中有許多方法,並且在您逐漸熟悉如何使用 PHP 后應當保存到資料庫)。對於本例,您將通過我編寫的名為 Shambles 的遊戲創建一個基本的怪物角色。首先建立一個數組以保存角色信息。 清單 3. 角色信息數組 $character = array( 'name' => 'Fred The Zombie', 'health' => '36', 'gore' => '1', 'clutch' => '5', 'brawn' => '6', 'sense' => '4', 'flail' => '2', 'chuck' => '3', 'lurch' => '4', ); | 需要生成文件名以保存這些信息。實際上不需要在傳入時就使用輸入,但是只可以使用人物姓名中的字母創建文件。 清單 4. 創建用於存儲信息的文件 $filename = substr(preg_replace("/[^a-z0-9]/", "", strtolower($character['name'])), 0, 20); file_put_contents($filename, serialize($character)); | 註:在將該腳本提供給公共使用時,需要過濾用戶輸入以避免有人將錯誤的 JavaScript 代碼或垃圾代碼惡意插入文件中。這只是供您個人使用的示例。最後,需要用表單表示信息以便可以輕鬆更新。這隻需使用輸入欄位中的默認值創建一張表單。 清單 5. 用表單顯示信息 <input name='health' value='<?php echo $character['health'] ?>' /> | 使用此基本腳本(請參閱 代碼歸檔)跟蹤幾個角色和 NPC。
NPC 生成器 在整合一個大型遊戲時,擁有一個一次性的 NPC 池十分有用。如果需要大量暴徒或者士兵,這樣做尤其有幫助。要整合 NPC 生成器,讓我們構建一個包含構造角色規則的數組,然後使用隨機姓名生成器及擲骰器一次性整合一批角色。 使用 Fred the Zombie 作為示例,您可以定義創建角色的規則。某些統計信息是固定的(生命力總是從 36 開始),某些統計信息是派生的(血=生命力/6),而某些統計信息是擲骰的結果(離合器是 1d6 — 一個六面骰子)。規則類似清單 6 中所示的內容。 清單 6. 定義角色創建的規則 $rules = array( 'health' => '36', 'gore' => 'health/6', 'clutch' => '1d6', 'brawn' => '1d6', 'sense' => '1d6', 'flail' => '1d6', 'chuck' => '1d6', 'lurch' => '1d6', ); | 現在您可以編寫少量代碼來評估規則。 清單 7. 評估規則的代碼 foreach ($rules as $stat=>$rule) { if (preg_match("/^[0-9]+$/", $rule)) { // This is only a number, and is therefore a static value $character[$stat] = $rule; } else if (preg_match("/^([0-9]+)d([0-9]+)/", $rule, $matches)) { // This is a die roll $val = 0; for ($n = 0;$n<$matches[1];$n++) { $val = $val + roll($matches[2]); } $character[$stat] = $val; } else if (preg_match("/^([a-z]+)\/([0-9]+)$/", $rule, $matches)) { // This is a derived value of some kind. $character[$stat] = $character[$matches[1]] / $matches[2]; } echo $stat . ' : ' . $character[$stat] . "<br />\n"; } | 在正確評估規則時,您可以引入使用隨機姓名生成器生成的隨機姓名並且一連幾天製作 NPC。請查看 代碼歸檔 中的腳本了解如何整合該任務。
機率計算器:擲骰 在 第 1 部分 中,您整合了一個簡單的機率計算器以確定從給定的一副牌中抽到指定牌面或花色的機率。現在讓我們構建一個擲骰機率計算器。對於本例,您將構建一個在擲兩個六面骰子(2d6)時確定可能結果的計算器。如果使用的是基於 d6 的任何 RPG 系統,玩大富豪或雙陸棋之類的棋盤類遊戲,或者要嘗試在諸如 Craps 之類的骰子遊戲中計算出機率,這將十分有用。 首先,建立在擲兩個骰子時確定可能結果的方法。可以考慮擲兩個不同顏色的骰子(如一個紅色骰子和一個藍色骰子)。如果擲紅色骰子的結果為 1,則有六個可能的結果,每個結果取決於藍色骰子的一面。這意味著可能的擲骰結果總數為 6^2 即 36 個結果。這可能看似有些奇怪,因為您實際上可以得到的最高值為 12(紅色六點加藍色六點),但是如果您認識到可以通過兩個不同的結果得到 11(紅色六點加藍色五點,或者紅色五點加藍色六點)應當更有意義。 讓我們假定,在本例中,您需要同時獲得總和(擲出 10)和骰面(擲出 6 和 4)結果,並且紅色骰子的 6 點與藍色骰子的 6 點沒有差別。重要的數字為 S(骰子面數)和 N(骰子個數)— 假定有 N 個相同的骰子,最大結果數為 S^N — 可是這其中的一些結果可能相同(一個 6 和一個 4,以及一個 4 和一個 6)。 清單 8. 構建擲骰機率計算器 $s = 6; $n = 2; $results = array(array()); for ($i = 0; $i < $n; $i ++) { $newresults = array(); foreach ($results as $result) { for ($x = 0; $x < $s; $x++) { $newresults[] = array_merge($result, array($x+1)); } } $results = $newresults; } | 這可能看似有些沉悶。您可以適當地簡化這段代碼,但是我已經在這裡完成了一些更明顯的操作,因此您可以了解數組是如何處理的。在構建完最終數組后,您可以迭代數組並生成骰子數總和的列表及其各自的機率。這段代碼包含在 代碼歸檔 中。
簡單的 Blackjack 撲克發牌器 在 第 1 部分 中,您構建了一個簡單的撲克發牌器。該發牌器不是真正地在與您玩牌;它只是發出牌盒中的牌,從而允許您開始各種牌局。現在讓我們構建一個真正與您玩牌的 Blackjack 發牌器。使用發牌器必須至少抽到 17 的簡單內部規則構建此發牌器。 這部分代碼將類似先前構建的簡單的撲克發牌器。對於 Blackjack,您需要以迭代抽取及牌局評估的形式構建。您將需要一個把牌面值指定為數字描述的數組。如果更改構建牌組的方法,您可以在原始的 $faces 數組中完成此操作。 清單 9. 修改 Blackjack 的 $faces 數組 $faces = array('Two' => 2, ... ... ... 'King' => 10, 'Ace' => 11); | 然後您需要一個基本函數來評估給定的牌局。該函數將查看手中的牌並返回手上的牌面總值。 清單 10. 評估給定牌局的函數 function evaluateHand($hand) { global $faces; $value = 0; foreach ($hand as $card) { if ($value > 11 && $card['face'] == 'Ace') { $value = $value + 1; // An ace can be 11 or 1 } else { $value = intval($value) + intval($faces[$card['face']]); } } return $value; } | 在評估手上牌局的函數就緒后,應當很容易確定您手上的牌是否超過 21 點,或者發牌器是否應當要牌。有關如何整合所有這些內容的詳細信息,請參閱 代碼歸檔。
牌面計算器 在玩 Blackjack 或者諸如紅心大戰之類基於王牌的遊戲時,知道如何算牌會十分有用。在玩 Blackjack 時,至少需要知道已經看到多少張 A 和花牌。對於紅心大戰,您可能需要知道遊戲中還有多少王牌。您將構建一個 Blackjack 基本計算器。您可以採用相同原理構建王牌遊戲的牌面計算器。 您將構建以略微不同的方式進行計算的牌組。您不必知道所有牌 — 只關注自己感興趣的牌。對於單牌組牌盒,則類似如下所示: 清單 11. 構建單牌組牌盒的牌面計算器 $deck = array ( 'faces' => 16, // 10,J,Q,K * 4 suits 'aces' => 4, // One per suit 'other' => 32, // 52 - (16 + 4) ); | 接下來,構建一張帶有三個按鈕的表單 — 一個用於花牌,一個用於 A,而另一個用於其他牌。通過在每次看到特定類型的牌時單擊相應按鈕,您可以調整留在牌組中的牌。 清單 12. 帶有三個按鈕的簡單表單 if (PHP 是一種易於使用、易於學習且可以廣泛獲取的編程語言。它非常適合開發在各種遊戲中可以使用的簡單腳本。無論是一個人玩簡單的使用紙和筆的遊戲,還是同一群人玩複雜的桌面角色扮演遊戲,或者任意類型的聯機遊戲,本系列都提供了適合您的內容。本文將在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 基礎上,探究可以在各種類型的遊戲中使用的 10 個中級腳本。這些腳本適用於三種遊戲:角色扮演遊戲、機率遊戲和文字遊戲。 在本系列的 第 1 部分 中,您創建了一些初學者級別的 PHP 腳本。現在是時候提高要求來增加一些複雜度,進一步拓展您的 PHP 編程技能並提高您作為遊戲專家的地位。 對於角色扮演遊戲腳本,您將了解如何整合武器的破壞力計算器、特徵表統計跟蹤器及非玩家角色(Non-Player Character,NPC)生成器,同時教您如何將信息保存到文件中以及如何與 PHP 中的數組結合使用。與機率遊戲相關的腳本將幫助您練習 Blackjack,學習如何算牌,並且快速了解 Bingo(一種賭博遊戲)的基本規則,同時教您如何將機率元素插入到 PHP 腳本中。最後,文字遊戲腳本將幫助您解決 Jumble 遊戲,創建簡單的置換計算程序,並生成文字搜索圖,同時讓您的 PHP 數組處理技能更上一層樓。 我們將快速地介紹這些腳本,而不會討論如何查找主機或設置伺服器。有很多 Web 託管公司提供 PHP,並且如果需要安裝自己的 PHP,XAMPP 安裝程序使用起來也十分簡單。我們將不會花費大量時間談論 PHP 最佳實踐或遊戲設計技術。本文介紹的腳本易於理解、使用簡單並可以快速掌握。 本文的 代碼歸檔 包含所討論的每個腳本的完整源代碼,並且可以訪問 Chaoticneutral.net 查看腳本實際運行情況。 破壞力計算器 在 第 1 部分中,我們構建了一個基本的擲骰器。讓我們查看一下如何使用該擲骰器幫助整合基本的破壞力計算器。 如果您曾經運行或者玩過桌面角色扮演遊戲,則可能已經看到過書中附帶的大型武器圖表。通常,這些圖表包括武器名稱及武器的破壞力有多大。它可能類似表 1 中所示的內容。 表 1. 破壞力計算器 武器名稱 | 破壞力 | Little Stick | 1d6 | Big Stick | 1d6+4 | Chainsaw | 2d8 | 您應當能夠得到在 “可以用 PHP 編寫的 30 個遊戲腳本” 系列的 第 1 部分 中創建的簡單 roll 函數,並且使用它計算一套基本武器的破壞力。為此,需要創建一個數組來保存關於武器的信息。 對於本例,一個武器有三個基本特性:名稱(Name)、擲骰(Die Roll)和傷害獎勵(Damage Bonus)。使用這些特性,您可以構建武器數組,如下所示: 清單 1. 武器數組 $weapons = array ( 'littlestick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '0', ), 'bigstick' => array ( 'name' => 'Little Stick', 'roll' => '1d6', 'bonus' => '4', ), 'chainsaw' => array ( 'name' => 'Little Stick', 'roll' => '2d8', 'bonus' => '0', ), ); | 使用此數組,您可以構建一張顯示武器、武器的破壞力及傷害判定結果表。 清單 2. 構建武器表 foreach ($weapons as $weapon) { list($count, $sides) = explode('d', $weapon['roll']); $result = 0; for ($i = 0; $i < $count;$i++) { $result = $result + roll($sides); } echo "<tr><td>" . $weapon['name'] . "</td><td>" . $weapon['roll']; if ($weapon['bonus'] > 0) { echo "+" . $weapon['bonus']; $result = $result + $weapon['bonus']; } echo "</td><td>" . $result . "</td></tr>"; } | 使用此腳本,您可以用集成的破壞力計算器創建基本武器圖。
統計跟蹤 現在已經可以計算破壞力,讓我們查看如何跟蹤一些基本任務統計信息,這種功能在要運行帶有多個 NPC 的遊戲時可能需要使用。創建一個簡單數組來保存人物信息並將其另存(序列化)為文本文件(將這些信息保存到資料庫中有許多方法,並且在您逐漸熟悉如何使用 PHP 后應當保存到資料庫)。對於本例,您將通過我編寫的名為 Shambles 的遊戲創建一個基本的怪物角色。首先建立一個數組以保存角色信息。 清單 3. 角色信息數組 $character = array( 'name' => 'Fred The Zombie', 'health' => '36', 'gore' => '1', 'clutch' => '5', 'brawn' => '6', 'sense' => '4', 'flail' => '2', 'chuck' => '3', 'lurch' => '4', ); | 需要生成文件名以保存這些信息。實際上不需要在傳入時就使用輸入,但是只可以使用人物姓名中的字母創建文件。 清單 4. 創建用於存儲信息的文件 $filename = substr(preg_replace("/[^a-z0-9]/", "", strtolower($character['name'])), 0, 20); file_put_contents($filename, serialize($character)); | 註:在將該腳本提供給公共使用時,需要過濾用戶輸入以避免有人將錯誤的 JavaScript 代碼或垃圾代碼惡意插入文件中。這只是供您個人使用的示例。最後,需要用表單表示信息以便可以輕鬆更新。這隻需使用輸入欄位中的默認值創建一張表單。 清單 5. 用表單顯示信息 <input name='health' value='<?php echo $character['health'] ?>' /> | 使用此基本腳本(請參閱 代碼歸檔)跟蹤幾個角色和 NPC。
NPC 生成器 在整合一個大型遊戲時,擁有一個一次性的 NPC 池十分有用。如果需要大量暴徒或者士兵,這樣做尤其有幫助。要整合 NPC 生成器,讓我們構建一個包含構造角色規則的數組,然後使用隨機姓名生成器及擲骰器一次性整合一批角色。 使用 Fred the Zombie 作為示例,您可以定義創建角色的規則。某些統計信息是固定的(生命力總是從 36 開始),某些統計信息是派生的(血=生命力/6),而某些統計信息是擲骰的結果(離合器是 1d6 — 一個六面骰子)。規則類似清單 6 中所示的內容。 清單 6. 定義角色創建的規則 $rules = array( 'health' => '36', 'gore' => 'health/6', 'clutch' => '1d6', 'brawn' => '1d6', 'sense' => '1d6', 'flail' => '1d6', 'chuck' => '1d6', 'lurch' => '1d6', ); | 現在您可以編寫少量代碼來評估規則。 清單 7. 評估規則的代碼 foreach ($rules as $stat=>$rule) { if (preg_match("/^[0-9]+$/", $rule)) { // This is only a number, and is therefore a static value $character[$stat] = $rule; } else if (preg_match("/^([0-9]+)d([0-9]+)/", $rule, $matches)) { // This is a die roll $val = 0; for ($n = 0;$n<$matches[1];$n++) { $val = $val + roll($matches[2]); } $character[$stat] = $val; } else if (preg_match("/^([a-z]+)\/([0-9]+)$/", $rule, $matches)) { // This is a derived value of some kind. $character[$stat] = $character[$matches[1]] / $matches[2]; } echo $stat . ' : ' . $character[$stat] . "<br />\n"; } | 在正確評估規則時,您可以引入使用隨機姓名生成器生成的隨機姓名並且一連幾天製作 NPC。請查看 代碼歸檔 中的腳本了解如何整合該任務。
機率計算器:擲骰 在 第 1 部分 中,您整合了一個簡單的機率計算器以確定從給定的一副牌中抽到指定牌面或花色的機率。現在讓我們構建一個擲骰機率計算器。對於本例,您將構建一個在擲兩個六面骰子(2d6)時確定可能結果的計算器。如果使用的是基於 d6 的任何 RPG 系統,玩大富豪或雙陸棋之類的棋盤類遊戲,或者要嘗試在諸如 Craps 之類的骰子遊戲中計算出機率,這將十分有用。 首先,建立在擲兩個骰子時確定可能結果的方法。可以考慮擲兩個不同顏色的骰子(如一個紅色骰子和一個藍色骰子)。如果擲紅色骰子的結果為 1,則有六個可能的結果,每個結果取決於藍色骰子的一面。這意味著可能的擲骰結果總數為 6^2 即 36 個結果。這可能看似有些奇怪,因為您實際上可以得到的最高值為 12(紅色六點加藍色六點),但是如果您認識到可以通過兩個不同的結果得到 11(紅色六點加藍色五點,或者紅色五點加藍色六點)應當更有意義。 讓我們假定,在本例中,您需要同時獲得總和(擲出 10)和骰面(擲出 6 和 4)結果,並且紅色骰子的 6 點與藍色骰子的 6 點沒有差別。重要的數字為 S(骰子面數)和 N(骰子個數)— 假定有 N 個相同的骰子,最大結果數為 S^N — 可是這其中的一些結果可能相同(一個 6 和一個 4,以及一個 4 和一個 6)。 清單 8. 構建擲骰機率計算器 $s = 6; $n = 2; $results = array(array()); for ($i = 0; $i < $n; $i ++) { $newresults = array(); foreach ($results as $result) { for ($x = 0; $x < $s; $x++) { $newresults[] = array_merge($result, array($x+1)); } } $results = $newresults; } | 這可能看似有些沉悶。您可以適當地簡化這段代碼,但是我已經在這裡完成了一些更明顯的操作,因此您可以了解數組是如何處理的。在構建完最終數組后,您可以迭代數組並生成骰子數總和的列表及其各自的機率。這段代碼包含在 代碼歸檔 中。
簡單的 Blackjack 撲克發牌器 在 第 1 部分 中,您構建了一個簡單的撲克發牌器。該發牌器不是真正地在與您玩牌;它只是發出牌盒中的牌,從而允許您開始各種牌局。現在讓我們構建一個真正與您玩牌的 Blackjack 發牌器。使用發牌器必須至少抽到 17 的簡單內部規則構建此發牌器。 這部分代碼將類似先前構建的簡單的撲克發牌器。對於 Blackjack,您需要以迭代抽取及牌局評估的形式構建。您將需要一個把牌面值指定為數字描述的數組。如果更改構建牌組的方法,您可以在原始的 $faces 數組中完成此操作。 清單 9. 修改 Blackjack 的 $faces 數組 $faces = array('Two' => 2, ... ... ... 'King' => 10, 'Ace' => 11); | 然後您需要一個基本函數來評估給定的牌局。該函數將查看手中的牌並返回手上的牌面總值。 清單 10. 評估給定牌局的函數 function evaluateHand($hand) { global $faces; $value = 0; foreach ($hand as $card) { if ($value > 11 && $card['face'] == 'Ace') { $value = $value + 1; // An ace can be 11 or 1 } else { $value = intval($value) + intval($faces[$card['face']]); } } return $value; } | 在評估手上牌局的函數就緒后,應當很容易確定您手上的牌是否超過 21 點,或者發牌器是否應當要牌。有關如何整合所有這些內容的詳細信息,請參閱 代碼歸檔。
牌面計算器 在玩 Blackjack 或者諸如紅心大戰之類基於王牌的遊戲時,知道如何算牌會十分有用。在玩 Blackjack 時,至少需要知道已經看到多少張 A 和花牌。對於紅心大戰,您可能需要知道遊戲中還有多少王牌。您將構建一個 Blackjack 基本計算器。您可以採用相同原理構建王牌遊戲的牌面計算器。 您將構建以略微不同的方式進行計算的牌組。您不必知道所有牌 — 只關注自己感興趣的牌。對於單牌組牌盒,則類似如下所示: 清單 11. 構建單牌組牌盒的牌面計算器 $deck = array ( 'faces' => 16, // 10,J,Q,K * 4 suits 'aces' => 4, // One per suit 'other' => 32, // 52 - (16 + 4) ); | 接下來,構建一張帶有三個按鈕的表單 — 一個用於花牌,一個用於 A,而另一個用於其他牌。通過在每次看到特定類型的牌時單擊相應按鈕,您可以調整留在牌組中的牌。 清單 12. 帶有三個按鈕的簡單表單 然後通過查看修改後的牌組,可以計算抽到花牌、A 或其他牌的機率。 清單 13. 計算抽到花牌、A 或其他牌的機率 echo "Odds of pulling a face: " . $deck['faces'] . " out of " . $deck['faces'] + $deck['aces'] + $deck['other']; | 使用這個基本牌面計算器作為起點,您可以構建一些更健壯的程序。
Bingo 引擎 基於我們在本文中已經完成的內容,您可以輕鬆地整合一個 Bingo 引擎以生成牌並從池中抽出編號。 Bingo 編號範圍從 1 到 75,以 15 個編號為一組(1-15 分配給 B,16-30 分配給 I 等等)。按照構建並洗一副虛擬牌的相同方法,您可以構建並洗一套虛擬的 Bingo 球。但是您無需以相同方法跟蹤牌面和花色。首先,構建基本編號集。 清單 14. 構建 Bingo 的基本編號集 for ($i = 1; $i < 16; $i++) { $numbers['B'][] = $i; $numbers['I'][] = $i+15; $numbers['N'][] = $i+30; $numbers['G'][] = $i+45; $numbers['O'][] = $i+60; } | 接下來,您可以置換每個子數組並且同時製作牌(不要忘記:中間的部分通常是一張任意的牌)。完成後,創建一個可用作牌組的主數組。 清單 15. 創建主數組 $letters = array ('B','I','N','G','O'); foreach ($letters as $letter) { shuffle($numbers[$letter]); $chunks = array_chunk($numbers[$letter], 5); $cards[$i][$letter] = $chunks[0]; if ($letter == 'N') { $cards[$i][$letter][2] = ' '; // Free Space } shuffle($balls); } | 現在已經全部完成!分發牌,並開始從主集合中抽取虛擬 Bingo 球,就像先前抽牌所做的那樣。在 代碼歸檔 中可以找到此腳本的完整運行版本。
Jumble 助手 Jumble 是在大多數報紙中可以找到的字謎,您有一些已經完全混合在一起的單詞。您必須從廢話中提取出實際單詞來,然後使用某些字母來創造新短語。從在 第 1 部分 中創建的縱橫字謎助手開始,讓我們整合一個快速腳本以幫助您構建 Jumble。 首先,打開單詞列表。需要遍歷該列表,將每個單詞拆分為經過排序的字母數組,然後再次合併數組。例如,這樣做將把單詞 “COLOR” 改為字元串 “CLOOR”;該字元串表示單詞 “COLOR” 中的所有字母,但是按照可預測的(而且更重要的是相配的)順序。該字元串隨後將被用作匹配單詞的數組的關鍵字。它必須為數組,因為 “sword” 和 “words” 擁有完全相同的字母,但是順序不同。最後,它將類似如下所示的內容: 清單 16. Jumble 的腳本 foreach ($words as $word) { $arr = str_split($word); sort($arr); $key = implode('', $arr); if (isset($lookup[$key])) { array_push($lookup[$key], $word); } else { $lookup[$key] = array($word); } } | 完成到此為止的程序后,只需將 Jumble 像任何其他單詞一樣處理,查找相應關鍵字的值並輸出所有結果。 清單 17. 完成 Jumble 腳本 您可以在 代碼歸檔 中看到如何將這些內容整合在一起。
置換密碼 置換密碼 是一種簡單的加密技術,採用這項技術將把字母表中的每個字母替換為字母表中的其他字母。按照現代加密技術的標準,置換密碼簡直就是小兒科。但是簡單的置換密碼玩起來很有趣,尤其是在 RPG 環境中給某個人傳遞一條可以在玩遊戲的過程中破解出來的編碼信息。 首先從 第 1 部分 的 Hangman 生成器中偷一些代碼 — 也就是,字母數組。製作另外一份數組副本,攪亂該副本,並構建一個聯合數組,其中原來的字母將獲得重組后的值。 清單 18. 修改字母數組 $letters = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p', 'q','r','s','t','u','v','w','x','y','z'); $code = $letters; shuffle($code); $key = array_combine($letters, $code); | 接下來,獲取 $_POST 中的輸入,將消息拆分為字母,然後將每個字母的值輸出到密鑰中。 清單 19. 分隔並輸出字母 在 $key[$letter] 之前使用 @ 符號將告訴 PHP 忽略在編碼期間發生的所有錯誤。如果消息有標點符號、數字或空格,PHP 將報告 $key 數組中沒有相應值。這沒問題。結果得到的編碼文本將去掉空格、數字和標點符號,從而使它(略微)更加難於解碼。
單詞搜索生成器 單詞搜索可能是我們學到的最早的基於字母的字謎。使用已有技術,再包括一些縱橫字謎助手中的邏輯,您就可以創建一個非常基本的單詞搜索生成器。為了保持簡單,您將創建一個大小為 10x10 個字母,裡面藏有 10 個單詞(垂直方向 5 個,水平方向 5 個)的單詞搜索。 第一部分,在水平方向放入單詞非常簡單 — 構建一個數組的數組,每個數組中有 10 個元素,用句點填充。然後在所有其他數組中,放入各個單詞的字母。要放入垂直方向的單詞,需要同時訪問所有數組,使用縱橫字謎助手代碼查找可能匹配的單詞。最棘手的部分可能是清單 20 中將單詞或者隨機字母填入垂直行(其中單詞短於整行)的部分。 清單 20. 在垂直行中填充單詞或者隨機字母 代碼歸檔 包含了許多註釋,可以幫助說明整個過程。該代碼還有很大的性能改進空間,但是這應當已經向您展示了如何動手處理問題的一般概念。嘗試代碼歸檔中的完整腳本以查看結果。
結束語 本文說明了如何獲取在 “用 PHP 可以編寫的 30 個遊戲腳本” 系列的 第 1 部分 中編寫的一些基本腳本,以及如何基於這些基本腳本進行構建以提供更健壯的腳本。在第 3 部分中,您將繼續基於本文構建的成果進一步提供更健壯、更有用的工具。(責任編輯:A6) POST['submit'] == 'faces') { $deck['faces']--; } | 然後通過查看修改後的牌組,可以計算抽到花牌、A 或其他牌的機率。 清單 13. 計算抽到花牌、A 或其他牌的機率 使用這個基本牌面計算器作為起點,您可以構建一些更健壯的程序。
Bingo 引擎 基於我們在本文中已經完成的內容,您可以輕鬆地整合一個 Bingo 引擎以生成牌並從池中抽出編號。 Bingo 編號範圍從 1 到 75,以 15 個編號為一組(1-15 分配給 B,16-30 分配給 I 等等)。按照構建並洗一副虛擬牌的相同方法,您可以構建並洗一套虛擬的 Bingo 球。但是您無需以相同方法跟蹤牌面和花色。首先,構建基本編號集。 清單 14. 構建 Bingo 的基本編號集 接下來,您可以置換每個子數組並且同時製作牌(不要忘記:中間的部分通常是一張任意的牌)。完成後,創建一個可用作牌組的主數組。 清單 15. 創建主數組 現在已經全部完成!分發牌,並開始從主集合中抽取虛擬 Bingo 球,就像先前抽牌所做的那樣。在 代碼歸檔 中可以找到此腳本的完整運行版本。
Jumble 助手 Jumble 是在大多數報紙中可以找到的字謎,您有一些已經完全混合在一起的單詞。您必須從廢話中提取出實際單詞來,然後使用某些字母來創造新短語。從在 第 1 部分 中創建的縱橫字謎助手開始,讓我們整合一個快速腳本以幫助您構建 Jumble。 首先,打開單詞列表。需要遍歷該列表,將每個單詞拆分為經過排序的字母數組,然後再次合併數組。例如,這樣做將把單詞 “COLOR” 改為字元串 “CLOOR”;該字元串表示單詞 “COLOR” 中的所有字母,但是按照可預測的(而且更重要的是相配的)順序。該字元串隨後將被用作匹配單詞的數組的關鍵字。它必須為數組,因為 “sword” 和 “words” 擁有完全相同的字母,但是順序不同。最後,它將類似如下所示的內容: 清單 16. Jumble 的腳本 完成到此為止的程序后,只需將 Jumble 像任何其他單詞一樣處理,查找相應關鍵字的值並輸出所有結果。 清單 17. 完成 Jumble 腳本 您可以在 代碼歸檔 中看到如何將這些內容整合在一起。
置換密碼 置換密碼 是一種簡單的加密技術,採用這項技術將把字母表中的每個字母替換為字母表中的其他字母。按照現代加密技術的標準,置換密碼簡直就是小兒科。但是簡單的置換密碼玩起來很有趣,尤其是在 RPG 環境中給某個人傳遞一條可以在玩遊戲的過程中破解出來的編碼信息。 首先從 第 1 部分 的 Hangman 生成器中偷一些代碼 — 也就是,字母數組。製作另外一份數組副本,攪亂該副本,並構建一個聯合數組,其中原來的字母將獲得重組后的值。 清單 18. 修改字母數組 接下來,獲取 $_POST 中的輸入,將消息拆分為字母,然後將每個字母的值輸出到密鑰中。 清單 19. 分隔並輸出字母 在 $key[$letter] 之前使用 @ 符號將告訴 PHP 忽略在編碼期間發生的所有錯誤。如果消息有標點符號、數字或空格,PHP 將報告 $key 數組中沒有相應值。這沒問題。結果得到的編碼文本將去掉空格、數字和標點符號,從而使它(略微)更加難於解碼。
單詞搜索生成器 單詞搜索可能是我們學到的最早的基於字母的字謎。使用已有技術,再包括一些縱橫字謎助手中的邏輯,您就可以創建一個非常基本的單詞搜索生成器。為了保持簡單,您將創建一個大小為 10x10 個字母,裡面藏有 10 個單詞(垂直方向 5 個,水平方向 5 個)的單詞搜索。 第一部分,在水平方向放入單詞非常簡單 — 構建一個數組的數組,每個數組中有 10 個元素,用句點填充。然後在所有其他數組中,放入各個單詞的字母。要放入垂直方向的單詞,需要同時訪問所有數組,使用縱橫字謎助手代碼查找可能匹配的單詞。最棘手的部分可能是清單 20 中將單詞或者隨機字母填入垂直行(其中單詞短於整行)的部分。 清單 20. 在垂直行中填充單詞或者隨機字母 代碼歸檔 包含了許多註釋,可以幫助說明整個過程。該代碼還有很大的性能改進空間,但是這應當已經向您展示了如何動手處理問題的一般概念。嘗試代碼歸檔中的完整腳本以查看結果。
結束語 本文說明了如何獲取在 “用 PHP 可以編寫的 30 個遊戲腳本” 系列的 第 1 部分 中編寫的一些基本腳本,以及如何基於這些基本腳本進行構建以提供更健壯的腳本。在第 3 部分中,您將繼續基於本文構建的成果進一步提供更健壯、更有用的工具。(責任編輯:A6) POST['jumble']); sort($arr); $search = implode('', $arr); if (isset($lookup[$search])) { foreach ($lookup[$search] as $word) { echo $word; } } | 您可以在 代碼歸檔 中看到如何將這些內容整合在一起。
置換密碼 置換密碼 是一種簡單的加密技術,採用這項技術將把字母表中的每個字母替換為字母表中的其他字母。按照現代加密技術的標準,置換密碼簡直就是小兒科。但是簡單的置換密碼玩起來很有趣,尤其是在 RPG 環境中給某個人傳遞一條可以在玩遊戲的過程中破解出來的編碼信息。 首先從 第 1 部分 的 Hangman 生成器中偷一些代碼 — 也就是,字母數組。製作另外一份數組副本,攪亂該副本,並構建一個聯合數組,其中原來的字母將獲得重組后的值。 清單 18. 修改字母數組 接下來,獲取 $_POST 中的輸入,將消息拆分為字母,然後將每個字母的值輸出到密鑰中。 清單 19. 分隔並輸出字母 在 $key[$letter] 之前使用 @ 符號將告訴 PHP 忽略在編碼期間發生的所有錯誤。如果消息有標點符號、數字或空格,PHP 將報告 $key 數組中沒有相應值。這沒問題。結果得到的編碼文本將去掉空格、數字和標點符號,從而使它(略微)更加難於解碼。
單詞搜索生成器 單詞搜索可能是我們學到的最早的基於字母的字謎。使用已有技術,再包括一些縱橫字謎助手中的邏輯,您就可以創建一個非常基本的單詞搜索生成器。為了保持簡單,您將創建一個大小為 10x10 個字母,裡面藏有 10 個單詞(垂直方向 5 個,水平方向 5 個)的單詞搜索。 第一部分,在水平方向放入單詞非常簡單 — 構建一個數組的數組,每個數組中有 10 個元素,用句點填充。然後在所有其他數組中,放入各個單詞的字母。要放入垂直方向的單詞,需要同時訪問所有數組,使用縱橫字謎助手代碼查找可能匹配的單詞。最棘手的部分可能是清單 20 中將單詞或者隨機字母填入垂直行(其中單詞短於整行)的部分。 清單 20. 在垂直行中填充單詞或者隨機字母 代碼歸檔 包含了許多註釋,可以幫助說明整個過程。該代碼還有很大的性能改進空間,但是這應當已經向您展示了如何動手處理問題的一般概念。嘗試代碼歸檔中的完整腳本以查看結果。
結束語 本文說明了如何獲取在 “用 PHP 可以編寫的 30 個遊戲腳本” 系列的 第 1 部分 中編寫的一些基本腳本,以及如何基於這些基本腳本進行構建以提供更健壯的腳本。在第 3 部分中,您將繼續基於本文構建的成果進一步提供更健壯、更有用的工具。(責任編輯:A6) POST['submit'] == 'faces') { $deck['faces']--; } | 然後通過查看修改後的牌組,可以計算抽到花牌、A 或其他牌的機率。 清單 13. 計算抽到花牌、A 或其他牌的機率 使用這個基本牌面計算器作為起點,您可以構建一些更健壯的程序。
Bingo 引擎 基於我們在本文中已經完成的內容,您可以輕鬆地整合一個 Bingo 引擎以生成牌並從池中抽出編號。 Bingo 編號範圍從 1 到 75,以 15 個編號為一組(1-15 分配給 B,16-30 分配給 I 等等)。按照構建並洗一副虛擬牌的相同方法,您可以構建並洗一套虛擬的 Bingo 球。但是您無需以相同方法跟蹤牌面和花色。首先,構建基本編號集。 清單 14. 構建 Bingo 的基本編號集 接下來,您可以置換每個子數組並且同時製作牌(不要忘記:中間的部分通常是一張任意的牌)。完成後,創建一個可用作牌組的主數組。 清單 15. 創建主數組 現在已經全部完成!分發牌,並開始從主集合中抽取虛擬 Bingo 球,就像先前抽牌所做的那樣。在 代碼歸檔 中可以找到此腳本的完整運行版本。
Jumble 助手 Jumble 是在大多數報紙中可以找到的字謎,您有一些已經完全混合在一起的單詞。您必須從廢話中提取出實際單詞來,然後使用某些字母來創造新短語。從在 第 1 部分 中創建的縱橫字謎助手開始,讓我們整合一個快速腳本以幫助您構建 Jumble。 首先,打開單詞列表。需要遍歷該列表,將每個單詞拆分為經過排序的字母數組,然後再次合併數組。例如,這樣做將把單詞 “COLOR” 改為字元串 “CLOOR”;該字元串表示單詞 “COLOR” 中的所有字母,但是按照可預測的(而且更重要的是相配的)順序。該字元串隨後將被用作匹配單詞的數組的關鍵字。它必須為數組,因為 “sword” 和 “words” 擁有完全相同的字母,但是順序不同。最後,它將類似如下所示的內容: 清單 16. Jumble 的腳本 完成到此為止的程序后,只需將 Jumble 像任何其他單詞一樣處理,查找相應關鍵字的值並輸出所有結果。 清單 17. 完成 Jumble 腳本 您可以在 代碼歸檔 中看到如何將這些內容整合在一起。
置換密碼 置換密碼 是一種簡單的加密技術,採用這項技術將把字母表中的每個字母替換為字母表中的其他字母。按照現代加密技術的標準,置換密碼簡直就是小兒科。但是簡單的置換密碼玩起來很有趣,尤其是在 RPG 環境中給某個人傳遞一條可以在玩遊戲的過程中破解出來的編碼信息。 首先從 第 1 部分 的 Hangman 生成器中偷一些代碼 — 也就是,字母數組。製作另外一份數組副本,攪亂該副本,並構建一個聯合數組,其中原來的字母將獲得重組后的值。 清單 18. 修改字母數組 接下來,獲取 $_POST 中的輸入,將消息拆分為字母,然後將每個字母的值輸出到密鑰中。 清單 19. 分隔並輸出字母 在 $key[$letter] 之前使用 @ 符號將告訴 PHP 忽略在編碼期間發生的所有錯誤。如果消息有標點符號、數字或空格,PHP 將報告 $key 數組中沒有相應值。這沒問題。結果得到的編碼文本將去掉空格、數字和標點符號,從而使它(略微)更加難於解碼。
單詞搜索生成器 單詞搜索可能是我們學到的最早的基於字母的字謎。使用已有技術,再包括一些縱橫字謎助手中的邏輯,您就可以創建一個非常基本的單詞搜索生成器。為了保持簡單,您將創建一個大小為 10x10 個字母,裡面藏有 10 個單詞(垂直方向 5 個,水平方向 5 個)的單詞搜索。 第一部分,在水平方向放入單詞非常簡單 — 構建一個數組的數組,每個數組中有 10 個元素,用句點填充。然後在所有其他數組中,放入各個單詞的字母。要放入垂直方向的單詞,需要同時訪問所有數組,使用縱橫字謎助手代碼查找可能匹配的單詞。最棘手的部分可能是清單 20 中將單詞或者隨機字母填入垂直行(其中單詞短於整行)的部分。 清單 20. 在垂直行中填充單詞或者隨機字母 代碼歸檔 包含了許多註釋,可以幫助說明整個過程。該代碼還有很大的性能改進空間,但是這應當已經向您展示了如何動手處理問題的一般概念。嘗試代碼歸檔中的完整腳本以查看結果。
結束語 本文說明了如何獲取在 “用 PHP 可以編寫的 30 個遊戲腳本” 系列的 第 1 部分 中編寫的一些基本腳本,以及如何基於這些基本腳本進行構建以提供更健壯的腳本。在第 3 部分中,您將繼續基於本文構建的成果進一步提供更健壯、更有用的工具。(責任編輯:A6) POST['message'])); $show = ''; foreach ($messageletters as $letter) { $show .= @$key[$letter]; } } | 在 $key[$letter] 之前使用 @ 符號將告訴 PHP 忽略在編碼期間發生的所有錯誤。如果消息有標點符號、數字或空格,PHP 將報告 $key 數組中沒有相應值。這沒問題。結果得到的編碼文本將去掉空格、數字和標點符號,從而使它(略微)更加難於解碼。
單詞搜索生成器 單詞搜索可能是我們學到的最早的基於字母的字謎。使用已有技術,再包括一些縱橫字謎助手中的邏輯,您就可以創建一個非常基本的單詞搜索生成器。為了保持簡單,您將創建一個大小為 10x10 個字母,裡面藏有 10 個單詞(垂直方向 5 個,水平方向 5 個)的單詞搜索。 第一部分,在水平方向放入單詞非常簡單 — 構建一個數組的數組,每個數組中有 10 個元素,用句點填充。然後在所有其他數組中,放入各個單詞的字母。要放入垂直方向的單詞,需要同時訪問所有數組,使用縱橫字謎助手代碼查找可能匹配的單詞。最棘手的部分可能是清單 20 中將單詞或者隨機字母填入垂直行(其中單詞短於整行)的部分。 清單 20. 在垂直行中填充單詞或者隨機字母 代碼歸檔 包含了許多註釋,可以幫助說明整個過程。該代碼還有很大的性能改進空間,但是這應當已經向您展示了如何動手處理問題的一般概念。嘗試代碼歸檔中的完整腳本以查看結果。
結束語 本文說明了如何獲取在 “用 PHP 可以編寫的 30 個遊戲腳本” 系列的 第 1 部分 中編寫的一些基本腳本,以及如何基於這些基本腳本進行構建以提供更健壯的腳本。在第 3 部分中,您將繼續基於本文構建的成果進一步提供更健壯、更有用的工具。(責任編輯:A6) POST['submit'] == 'faces') { $deck['faces']--; } | 然後通過查看修改後的牌組,可以計算抽到花牌、A 或其他牌的機率。 清單 13. 計算抽到花牌、A 或其他牌的機率 使用這個基本牌面計算器作為起點,您可以構建一些更健壯的程序。
Bingo 引擎 基於我們在本文中已經完成的內容,您可以輕鬆地整合一個 Bingo 引擎以生成牌並從池中抽出編號。 Bingo 編號範圍從 1 到 75,以 15 個編號為一組(1-15 分配給 B,16-30 分配給 I 等等)。按照構建並洗一副虛擬牌的相同方法,您可以構建並洗一套虛擬的 Bingo 球。但是您無需以相同方法跟蹤牌面和花色。首先,構建基本編號集。 清單 14. 構建 Bingo 的基本編號集 接下來,您可以置換每個子數組並且同時製作牌(不要忘記:中間的部分通常是一張任意的牌)。完成後,創建一個可用作牌組的主數組。 清單 15. 創建主數組 現在已經全部完成!分發牌,並開始從主集合中抽取虛擬 Bingo 球,就像先前抽牌所做的那樣。在 代碼歸檔 中可以找到此腳本的完整運行版本。
Jumble 助手 Jumble 是在大多數報紙中可以找到的字謎,您有一些已經完全混合在一起的單詞。您必須從廢話中提取出實際單詞來,然後使用某些字母來創造新短語。從在 第 1 部分 中創建的縱橫字謎助手開始,讓我們整合一個快速腳本以幫助您構建 Jumble。 首先,打開單詞列表。需要遍歷該列表,將每個單詞拆分為經過排序的字母數組,然後再次合併數組。例如,這樣做將把單詞 “COLOR” 改為字元串 “CLOOR”;該字元串表示單詞 “COLOR” 中的所有字母,但是按照可預測的(而且更重要的是相配的)順序。該字元串隨後將被用作匹配單詞的數組的關鍵字。它必須為數組,因為 “sword” 和 “words” 擁有完全相同的字母,但是順序不同。最後,它將類似如下所示的內容: 清單 16. Jumble 的腳本 完成到此為止的程序后,只需將 Jumble 像任何其他單詞一樣處理,查找相應關鍵字的值並輸出所有結果。 清單 17. 完成 Jumble 腳本 您可以在 代碼歸檔 中看到如何將這些內容整合在一起。
置換密碼 置換密碼 是一種簡單的加密技術,採用這項技術將把字母表中的每個字母替換為字母表中的其他字母。按照現代加密技術的標準,置換密碼簡直就是小兒科。但是簡單的置換密碼玩起來很有趣,尤其是在 RPG 環境中給某個人傳遞一條可以在玩遊戲的過程中破解出來的編碼信息。 首先從 第 1 部分 的 Hangman 生成器中偷一些代碼 — 也就是,字母數組。製作另外一份數組副本,攪亂該副本,並構建一個聯合數組,其中原來的字母將獲得重組后的值。 清單 18. 修改字母數組 接下來,獲取 $_POST 中的輸入,將消息拆分為字母,然後將每個字母的值輸出到密鑰中。 清單 19. 分隔並輸出字母 在 $key[$letter] 之前使用 @ 符號將告訴 PHP 忽略在編碼期間發生的所有錯誤。如果消息有標點符號、數字或空格,PHP 將報告 $key 數組中沒有相應值。這沒問題。結果得到的編碼文本將去掉空格、數字和標點符號,從而使它(略微)更加難於解碼。
單詞搜索生成器 單詞搜索可能是我們學到的最早的基於字母的字謎。使用已有技術,再包括一些縱橫字謎助手中的邏輯,您就可以創建一個非常基本的單詞搜索生成器。為了保持簡單,您將創建一個大小為 10x10 個字母,裡面藏有 10 個單詞(垂直方向 5 個,水平方向 5 個)的單詞搜索。 第一部分,在水平方向放入單詞非常簡單 — 構建一個數組的數組,每個數組中有 10 個元素,用句點填充。然後在所有其他數組中,放入各個單詞的字母。要放入垂直方向的單詞,需要同時訪問所有數組,使用縱橫字謎助手代碼查找可能匹配的單詞。最棘手的部分可能是清單 20 中將單詞或者隨機字母填入垂直行(其中單詞短於整行)的部分。 清單 20. 在垂直行中填充單詞或者隨機字母 代碼歸檔 包含了許多註釋,可以幫助說明整個過程。該代碼還有很大的性能改進空間,但是這應當已經向您展示了如何動手處理問題的一般概念。嘗試代碼歸檔中的完整腳本以查看結果。
結束語 本文說明了如何獲取在 “用 PHP 可以編寫的 30 個遊戲腳本” 系列的 第 1 部分 中編寫的一些基本腳本,以及如何基於這些基本腳本進行構建以提供更健壯的腳本。在第 3 部分中,您將繼續基於本文構建的成果進一步提供更健壯、更有用的工具。(責任編輯:A6) POST['jumble']); sort($arr); $search = implode('', $arr); if (isset($lookup[$search])) { foreach ($lookup[$search] as $word) { echo $word; } } | 您可以在 代碼歸檔 中看到如何將這些內容整合在一起。
置換密碼 置換密碼 是一種簡單的加密技術,採用這項技術將把字母表中的每個字母替換為字母表中的其他字母。按照現代加密技術的標準,置換密碼簡直就是小兒科。但是簡單的置換密碼玩起來很有趣,尤其是在 RPG 環境中給某個人傳遞一條可以在玩遊戲的過程中破解出來的編碼信息。 首先從 第 1 部分 的 Hangman 生成器中偷一些代碼 — 也就是,字母數組。製作另外一份數組副本,攪亂該副本,並構建一個聯合數組,其中原來的字母將獲得重組后的值。 清單 18. 修改字母數組 接下來,獲取 $_POST 中的輸入,將消息拆分為字母,然後將每個字母的值輸出到密鑰中。 清單 19. 分隔並輸出字母 在 $key[$letter] 之前使用 @ 符號將告訴 PHP 忽略在編碼期間發生的所有錯誤。如果消息有標點符號、數字或空格,PHP 將報告 $key 數組中沒有相應值。這沒問題。結果得到的編碼文本將去掉空格、數字和標點符號,從而使它(略微)更加難於解碼。
單詞搜索生成器 單詞搜索可能是我們學到的最早的基於字母的字謎。使用已有技術,再包括一些縱橫字謎助手中的邏輯,您就可以創建一個非常基本的單詞搜索生成器。為了保持簡單,您將創建一個大小為 10x10 個字母,裡面藏有 10 個單詞(垂直方向 5 個,水平方向 5 個)的單詞搜索。 第一部分,在水平方向放入單詞非常簡單 — 構建一個數組的數組,每個數組中有 10 個元素,用句點填充。然後在所有其他數組中,放入各個單詞的字母。要放入垂直方向的單詞,需要同時訪問所有數組,使用縱橫字謎助手代碼查找可能匹配的單詞。最棘手的部分可能是清單 20 中將單詞或者隨機字母填入垂直行(其中單詞短於整行)的部分。 清單 20. 在垂直行中填充單詞或者隨機字母 代碼歸檔 包含了許多註釋,可以幫助說明整個過程。該代碼還有很大的性能改進空間,但是這應當已經向您展示了如何動手處理問題的一般概念。嘗試代碼歸檔中的完整腳本以查看結果。
結束語 本文說明了如何獲取在 “用 PHP 可以編寫的 30 個遊戲腳本” 系列的 第 1 部分 中編寫的一些基本腳本,以及如何基於這些基本腳本進行構建以提供更健壯的腳本。在第 3 部分中,您將繼續基於本文構建的成果進一步提供更健壯、更有用的工具。(責任編輯:A6) POST['submit'] == 'faces') { $deck['faces']--; } |