首頁  >  文章  >  web前端  >  JavaScript 重點:Javascript 的部分策劃者)

JavaScript 重點:Javascript 的部分策劃者)

Barbara Streisand
Barbara Streisand原創
2024-10-30 17:09:02869瀏覽

JavaScript Essentials: Part Mastermind in Javascript)

在本節中,我們將用 JavaScript 實作一個名為 Mastermind 的遊戲。這個遊戲開發將涵蓋我們迄今為止討論過的許多概念。我們將定義函數、向它們傳遞參數、使用變數以及使用迴圈和 if 語句。我們將簡要介紹函數的另一個概念,即 IIFE,即立即呼叫函數表達式。我們還將了解如何透過命令列獲取用戶輸入。此時,它只是控制台應用程式。

您可以在這裡參考類似的實現,Master mind in python

Mastermind 是一款簡單的棋盤遊戲,使用顏色,但我們會使用數字。

摘要:條形後面是一名玩家放置的四種顏色。其他玩家看不到第一個玩家的顏色。第一個玩家的顏色稱為代碼製作者,另一個玩家的顏色稱為代碼破壞者。密碼破解者嘗試猜測密碼編寫者的密碼(包括 2 到 12 次)。嘗試次數必須是偶數。

執行

  • 在您的電腦(或放置項目的位置)上建立一個名為mastermind 的資料夾,並在mastermind 中,使用npm init -y (在命令列上)初始化節點項目。我在 Linux 機器上,所以這就是我設定專案的方式。

    • 打開我的終端,運行,cd 將我移動到用戶資料夾。
    • 然後,cd ~/projects。項目是我保存項目的地方。
    • 然後 mkdir mastermind 和 cd mastermind 建立 mastermind 資料夾並切換到該資料夾。
    • 使用 npm init -y 初始化節點項目。將建立 package.json 檔案。
    • 使用觸控 app.js 建立 app.js
    • 將 console.log("Mastermind") 寫入 app.js 並使用 Node app.js 運行它。我希望見到Mastermind,否則我的設定有問題。
  • 這個遊戲的起點(入口)將在App中,一個函數。讓我們建立一個名為 App 的函數並加入 console.log("App")。然後我們可以呼叫 App() 並使用 Node app.js 執行程式碼。我不會告訴您運行程式碼,但這是您在編寫程式碼時應該做的事情。這是我的 app.js 檔案的目前內容。

console.log("Mastermind");

function App() {
  console.log("App");
}

App();
  • 比賽開始時

    • 使用者輸入他們想要玩的回合數,並且輸入的值必須經過驗證
    • 使用者選擇是否允許重複
    • 程式碼產生器是隨機產生的
    • 使用者已輸入密碼破解器
    • 破碼器與破碼器比較,如果不匹配就會給予提示
    • 在這個過程中,我們進行了輪數
    • 為了讓這個更像遊戲,我們將整個應用程式放入無限循環
  • 讓我們實作一個為程式碼產生器產生隨機數的函數,從而為程式碼產生器設定隨機值。

  • 首先,我們需要一種產生隨機數的方法。為了不干擾 app.js 中的程式碼,讓我們建立另一個名為 scratch_pad.js 的文件,並在這個檔案中進行實驗。

  • JavaScript 有一個簡單的方法來呼叫 Math.random() 產生隨機數。在便條本中,讓我們使用循環構造記錄 4 個隨機數。

console.log("Mastermind");

function App() {
  console.log("App");
}

App();
  • 我們要的是整數(如數字)0、1、2、...、9,而不是小數。我們可以將 Math.random() 傳回的值乘以 10,得到 x.something,其中 x 現在是 1,2,3,...,9。請記住,這些實驗都是在草稿本上完成的。嘗試一下。

  • 我們想要的是點之前的數字,也就是整數部分。我們可以編寫程式碼將數字轉換為字串,然後用“.”分隔它。並獲取第一個元素。然而,我們可以使用一個名為「地板」的功能。

for (let i = 0; i < 4; i++) {
  console.log(Math.random());
}
// 0.10037268097853191
// 0.20981624777230534
// 0.47828165742292583
// 0.8160883929470153
  • 其工作原理是,如果我們想得到某個數字min 和max 之間的隨機數,其中max 大於min,那麼我們可以這樣做, min Math.floor(Math.random() * (max -分鐘1))。 min 是最小期望值,max 是最大期望值。在我們的例子中,最小值為 0,最大值為 9。
  • 這是我用來產生隨機數的片段。我向函數添加了參數,因為我不希望函數具有內部狀態。
for (let i = 0; i < 4; i++) {
  console.log(Math.floor(Math.random() * 10));
}
// 4
// 7
// 3
// 4
  • 此時,我們現在可以回到 app.js 並加入上面的函數來為程式碼產生器產生隨機數。將其放在 App 函數上方。

  • 從摘要來看,使用的顏色數量是 4。因此我們需要為程式碼產生器產生 4 個數字。我們還必須處理是否允許重複。回到草稿本。

  • 我們有函數、if 和 else 語句、for 和 while 迴圈等。這些構造都有一個區塊或一個主體。在這些區塊中初始化的變數可以在區塊內使用,而不能在區塊外使用。這稱為變數的範圍。因此,變數可以存在於全域範圍內,這意味著該變數可以在任何地方使用或評估。當我們在區塊中聲明變數時。該變數成為內部變數或限制在該範圍內。在暫存器中運行它。

console.log("Mastermind");

function App() {
  console.log("App");
}

App();
  • 現在透過在 if 語句中初始化變數 x 來更新它,console.log(x) 在 if 區塊之外並執行便簽本。您應該會收到與此類似的錯誤。
for (let i = 0; i < 4; i++) {
  console.log(Math.random());
}
// 0.10037268097853191
// 0.20981624777230534
// 0.47828165742292583
// 0.8160883929470153

此時我想提請您注意有關作用域的想法。

  • 產生程式碼產生器時,我們想知道是否允許重複,此時,我們知道程式碼產生器是一個數字(或數字字串)陣列。讓我們從便條本開始。我們想要實作一個函數,它接受一個布林參數來指示是否允許重複。該函數會將四個數字添加(推送)到程式碼產生器中,但在此之前,我們必須檢查是否允許重複,並在不允許時進行處理。
for (let i = 0; i < 4; i++) {
  console.log(Math.floor(Math.random() * 10));
}
// 4
// 7
// 3
// 4
  • 我們也以這樣的方式編寫程式碼,即程式碼產生器不能在程式碼產生器函數中全域存取。因此將返回代碼生成器。
function generateRandomNumbersBetween(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

for (let i = 0; i < 4; i++) {
  console.log(generateRandomNumbersBetween(0, 9));
}
  • app.js 中,我們現在可以加入程式碼產生器函數和用於程式碼產生的變數。
  • 現在回到草稿本。我們希望從終端獲取用戶的輸入。 JavaScript 也有辦法做到這一點。試試這個片段。
const HP = 100;

if (true) {
  console.log("IF BLOCK::", HP);
}

console.log("End::", HP);

// IF BLOCK:: 100
// End:: 100
  • 這種取得使用者輸入的方法沒有問題。只是我們必須使用回呼函數,並且無法將輸入的輸入傳遞到 readlineOInstance.question 回呼函數的外部範圍。

  • 你在想什麼?在「便箋簿」中試試看。如果您正在考慮在 readlineOInstance.question 的外部範圍中聲明一個變數並將輸入的輸入分配給它,那麼這是一個很好的方法,但是......仍然嘗試一下。

  • 你還記得 Promise 的概念嗎?我們可以在這裡使用 Promise 並解析輸入。然而,我們必須將整個過程包裝在函數中。 readlineOInstance.question 有幾個部分有一個類似於Question(query: string, callback: (answer: string) => void 的header。query 是對使用者的查詢(或提示),callback 是如何我們處理輸入集合。由於稍後可能會在某個地方重複使用相同的函數,因此我們會將查詢作為參數傳遞。

console.log("Mastermind");

function App() {
  console.log("App");
}

App();
  • 現在我們可以將 getInput 函數加入到 app.js 中。不要忘記導入,const readline = require("readline")。 app.js 的內容應類似下面的程式碼片段。
for (let i = 0; i < 4; i++) {
  console.log(Math.random());
}
// 0.10037268097853191
// 0.20981624777230534
// 0.47828165742292583
// 0.8160883929470153
  • 現在我們要求使用者輸入輪數以及是否允許重複。我們知道輪數必須是偶數並且在 2 到 12 之間。我們將實作一個函數來驗證值(數字)是否為偶數並且在 2 到 12 之間。它將傳回一個布林值。當數模 2 為零時,該數為偶數。 (即數字 % 2 == 0)。
for (let i = 0; i < 4; i++) {
  console.log(Math.floor(Math.random() * 10));
}
// 4
// 7
// 3
// 4
  • 在App函數的主體中,我們可以要求輸入並驗證它們。我們將不斷要求輸入正確的輪數。對於程式碼中的重複值,當使用者輸入預期之外的任何內容時,我們會假設使用者不想要重複值。我們將使用while 循環並將條件設為true,並且僅在回合有效時才中斷,但使用try 和catch(用於錯誤處理),當使用者輸入無效值時,我們會記錄一條訊息,指示輸入的值無效。嘗試一下。
function generateRandomNumbersBetween(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

for (let i = 0; i < 4; i++) {
  console.log(generateRandomNumbersBetween(0, 9));
}

運行 app.js 並與其互動。這是交互過程中的類似輸出。

const HP = 100;

if (true) {
  console.log("IF BLOCK::", HP);
}

console.log("End::", HP);

// IF BLOCK:: 100
// End:: 100
  • 我們已經計算了輪數和重複值。現在我們可以產生程式碼產生器了。為此,我們可以呼叫generateCodeMaker函數並將複製選項值傳遞給它(或保留它,因為它預設為false)。
 IF BLOCK:: 100
 /home/Projects/mastermind/scratch_pad.js:8
 console.log(x)
    ^

 ReferenceError: x is not defined
    at Object.<anonymous> (/home/Projects/mastermind/scratch_pad.js:8:13)
    at Module._compile (node:internal/modules/cjs/loader:1469:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1548:10)
    at Module.load (node:internal/modules/cjs/loader:1288:32)
    at Module._load (node:internal/modules/cjs/loader:1104:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:174:12)
    at node:internal/main/run_main_module:28:49

 Node.js v20.17.0
  • 現在我們可以向使用者詢問代碼破解器並將其與代碼產生器進行比較。破碼器也是一個數字數組。我們還將添加一個提示,讓用戶知道他們距離特定代碼有多遠。因此,如果破碼者的程式碼大於破碼者的程式碼,我們就說得更多。當它們相等時我們說相等,而當來自破碼器的代碼小於破碼器的代碼時我們說更少。讓我們進入草稿本。
  • 我們將建立一個函數,該函數將採用 4 個元素的數字數組,然後比較使用者的輸入(程式碼斷路器)。
// a global code maker that is accessible inside any other scope
let CODE_MAKER = [];

function generateRandomNumbersBetween(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

function generateCodeMaker(isDuplicatesAllowed = false) {
  let counter = 0;

  while (counter < 4) {
    let code = generateRandomNumbersBetween(0, 9);

    if (isDuplicatesAllowed) {
      CODE_MAKER.push(code);
      counter += 1;
    } else if (!CODE_MAKER.includes(code)) {
      CODE_MAKER.push(code);
      counter += 1;
    }
  }
}

console.log(CODE_MAKER);
generateCodeMaker(true);
console.log(CODE_MAKER);

// reset the code maker
CODE_MAKER = [];
generateCodeMaker(false);
console.log(CODE_MAKER);
// []
// [ 6, 6, 0, 9 ]
// [ 2, 5, 0, 8 ]
  • 我們有一個變數來處理提示,以及與程式碼創建者和破壞者相關的每個程式碼的值。
  • 我們將程式碼產生器傳遞給函數,以將其與使用者的輸入進行比較。
  • 我們更新了提示,讓使用者知道如何更新程式碼斷路器中的值
  • 現在我們可以將 HINTS 和 CompareCode 函數加入到 app.js 中。現在是在 App 功能之上運行 app.js 的好時機。

  • 現在我們實作了一個比較程式碼產生器和程式碼破解器的函數,現在我們可以將其放入循環中以計算輪數(輪數 = 玩遊戲的次數)。因此,如果輪數為 6,那麼遊戲將進行 6 次,但當使用者正確猜出所有程式碼時,即 HINTS 中的值全為 0 時,我們必須終止遊戲。因此,當我們數出 HINTS 中 0 的數量並且為 4 時,我們就可以終止遊戲並說用戶獲勝。

console.log("Mastermind");

function App() {
  console.log("App");
}

App();
  • 回合數減少,如果回合數不為0,我們就知道使用者是否獲勝。
for (let i = 0; i < 4; i++) {
  console.log(Math.random());
}
// 0.10037268097853191
// 0.20981624777230534
// 0.47828165742292583
// 0.8160883929470153
  • 執行程式時的某些輸出
for (let i = 0; i < 4; i++) {
  console.log(Math.floor(Math.random() * 10));
}
// 4
// 7
// 3
// 4
  • 當我按下回車鍵時
function generateRandomNumbersBetween(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

for (let i = 0; i < 4; i++) {
  console.log(generateRandomNumbersBetween(0, 9));
}
  • 我想我們可以享受到目前為止的辛苦工作了。我有大約130行。你有多少個?

  • 這是完整程式碼

const HP = 100;

if (true) {
  console.log("IF BLOCK::", HP);
}

console.log("End::", HP);

// IF BLOCK:: 100
// End:: 100

還有改進的空間嗎?

儘管這是一個簡單的控制台/終端/基於文字的應用程序,但我們可以做更多的事情。

  • 我們可以替換所有常數,例如字串和數字。
  • 我們可以從比較程式碼中提取(重構)程式碼斷路器輸入並將其拆分,然後將程式碼斷路器和程式碼產生器作為參數傳遞。我們甚至可以讓函數傳回提示,而不是全域存取提示。我們將創建一個新的提示變數並返回它。因此,compareCode 將傳回指派給hints 變數的提示。
 IF BLOCK:: 100
 /home/Projects/mastermind/scratch_pad.js:8
 console.log(x)
    ^

 ReferenceError: x is not defined
    at Object.<anonymous> (/home/Projects/mastermind/scratch_pad.js:8:13)
    at Module._compile (node:internal/modules/cjs/loader:1469:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1548:10)
    at Module.load (node:internal/modules/cjs/loader:1288:32)
    at Module._load (node:internal/modules/cjs/loader:1104:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:174:12)
    at node:internal/main/run_main_module:28:49

 Node.js v20.17.0
  • 我們也可以將 console.clear() 包裝到一個函數中。
  • 我們可以在下一場比賽前讓程式放慢速度
  • 我們可以將 HINTS.filter((value) => 0 === value).length === 4 取出為函數。其目的是檢查密碼破解者是否正確猜出密碼製作者。
  • 我們也可以用同樣的方法來宣布誰贏了比賽
// a global code maker that is accessible inside any other scope
let CODE_MAKER = [];

function generateRandomNumbersBetween(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

function generateCodeMaker(isDuplicatesAllowed = false) {
  let counter = 0;

  while (counter < 4) {
    let code = generateRandomNumbersBetween(0, 9);

    if (isDuplicatesAllowed) {
      CODE_MAKER.push(code);
      counter += 1;
    } else if (!CODE_MAKER.includes(code)) {
      CODE_MAKER.push(code);
      counter += 1;
    }
  }
}

console.log(CODE_MAKER);
generateCodeMaker(true);
console.log(CODE_MAKER);

// reset the code maker
CODE_MAKER = [];
generateCodeMaker(false);
console.log(CODE_MAKER);
// []
// [ 6, 6, 0, 9 ]
// [ 2, 5, 0, 8 ]
  • 將所有可以獨立的函數放入自己的檔案functions.js中並匯出它們。然後,我們可以重構依賴全域變數的獨立函數,然後使用參數將該資料作為參數傳遞給函數。
  • 我們甚至可以有一個單獨的文件
// a global code maker that is accessible inside any other scope
let CODE_MAKER = [];

function generateRandomNumbersBetween(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

function generateCodeMaker(isDuplicatesAllowed = false) {
  let counter = 0;
  let codeMaker = [];

  while (counter < 4) {
    let code = generateRandomNumbersBetween(0, 9);

    if (isDuplicatesAllowed) {
      codeMaker.push(code);
      counter += 1;
    } else if (!codeMaker.includes(code)) {
      codeMaker.push(code);
      counter += 1;
    }
  }

  return codeMaker;
}

console.log(CODE_MAKER);
CODE_MAKER = generateCodeMaker(true);
console.log(CODE_MAKER);

CODE_MAKER = generateCodeMaker(false);
console.log(CODE_MAKER);

// []
// [ 6, 6, 0, 9 ]
// [ 2, 5, 0, 8 ]

結論

我們已經使用了在這個專案中學到的所有知識,而且還有更多。我提到我們可以對一些函數進行分組並導出它們。為此,我們將討論如何在 Javascript 中匯入和匯出。我將提供另一個我認為對您有用的項目。智者遊戲到此結束,希望大家也能進行一些重構,因為還有很多需要重構的地方。祝你好運...

const readline = require("readline");

const readlineOInstance = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

readlineOInstance.question("Enter code maker: ", (userInput) => {
  console.clear();
  console.log(`INPUT: ${userInput}`);
  readlineOInstance.close();
});

來源

  • wiki-play-mastermind
  • 維基百科-mastermind
  • Python 大師思想

以上是JavaScript 重點:Javascript 的部分策劃者)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn