JavaScript Essentials: JavaScript のマスターマインドの一部)

Barbara Streisand
リリース: 2024-10-30 17:09:02
オリジナル
866 人が閲覧しました

JavaScript Essentials: Part Mastermind in Javascript)

このセクションでは、Mastermind というゲームを JavaScript で実装します。このゲーム開発では、これまでに説明した多くの概念がカバーされます。関数を定義し、関数に引数を渡し、変数を使用し、ループと if ステートメントを使用します。 IIFE (即時呼び出し関数式) として知られる、関数に関する別の概念を簡単に説明します。コマンドライン経由でユーザー入力を取得する方法についても説明します。現時点では、これは単なるコンソール アプリケーションです。

Python のマスターマインドで同様の実装を参照できます

マスターマインドは色を使用するシンプルなボード ゲームですが、代わりに数字を使用します。

概要: バーの後ろには、1 人のプレイヤーが配置した 4 つの色があります。他のプレイヤーは最初のプレイヤーの色を見ることができません。最初のプレイヤーの色はコードメーカーと呼ばれ、他のプレイヤーの色はコードブレイカーと呼ばれます。コード ブレーカーは、コード作成者の推測を合計 2 回から 12 回試行します。試行回数は偶数である必要があります。

実装

  • PC (またはプロジェクトを配置する場所) 上に mastermind というフォルダーを作成し、mastermind で npm init -y (コマンド ラインで) を使用してノード プロジェクトを初期化します。 。私は Linux マシンを使用しているので、これがプロジェクトをセットアップする方法です。

    • ターミナルを開いて実行し、cd を実行してユーザー フォルダーに移動します。
    • 次に、cd ~/projects を実行します。プロジェクトは私のプロジェクトを保管する場所です。
    • 次に、mkdir mastermind と cd mastermind を実行して mastermind フォルダーを作成し、そのフォルダーに変更します。
    • npm init -y を使用してノード プロジェクトを初期化します。 package.json ファイルが作成されます。
    • touch app.js を使用して app.js を作成します。
    • console.log("Mastermind") を app.js に書き込み、ノード app.js で実行します。 マスターマインドが登場することを期待しています。そうでない場合は、設定に問題があります。
  • このゲームの開始 (エントリ) ポイントは アプリ という関数になります。 App という関数を作成し、console.log("App") を追加しましょう。次に、App() を呼び出し、ノード 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 を初期化することでこれを更新し、if ブロックの外側の console.log(x) でスクラッチ パッドを実行します。これと同様のエラーが表示されるはずです。
for (let i = 0; i < 4; i++) {
  console.log(Math.random());
}
// 0.10037268097853191
// 0.20981624777230534
// 0.47828165742292583
// 0.8160883929470153
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

この時点で、スコープについての考え方に注目してもらいたいと思います。

  • コード メーカーを生成するとき、重複が許可されているかどうかを知りたいのですが、この時点で、コード メーカーが数値 (または数値文字列) の配列であることがわかっています。スクラッチパッドから始めましょう。重複が許可されるかどうかを示すブール値引数を受け取る関数を実装したいと考えています。この関数は 4 つの数値をコード メーカーに追加 (プッシュ) しますが、その前に、重複が許可されているかどうかを確認し、許可されていない場合は処理する必要があります。
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 で、コード メーカー関数とコード make 用の変数を追加できるようになりました。
  • ここでスクラッチパッドに戻ります。端末からユーザーからの入力を取得したいと考えています。 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を使用して入力を解決できます。ただし、プロセス全体を関数でラップする必要があります。 readlineOInstance.question にはいくつかの部分がありますが、question(query: string, callback: (answer: string) => void に似たヘッダーがあります。クエリはユーザーへのクエリ (またはプロンプト) であり、コールバックはユーザーへのクエリ (またはプロンプト) です。入力コレクションを処理します。同じ関数を後でどこかで再利用する可能性があるため、クエリを引数として渡します。

    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
    
    ログイン後にコピー
    ログイン後にコピー
    ログイン後にコピー
    ログイン後にコピー
    • アプリ関数の本体では、入力を要求して検証できます。ラウンド数については、引き続き適切な入力を求めます。コード内の重複値については、ユーザーが予想以外の値を入力した場合、ユーザーは重複を望んでいないものと想定されます。 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 回プレイされますが、ユーザーがすべてのコードを正しく推測したとき、つまりヒントの値がすべて 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
    
    ログイン後にコピー
    ログイン後にコピー
    ログイン後にコピー
    ログイン後にコピー
    • Enterを押したとき
    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 はヒント変数に割り当てられたヒントを返します。
     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 ]
    
    ログイン後にコピー
    ログイン後にコピー
    • スタンドアロンできるすべての関数を独自のファイル function.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
    • ウィキペディア-マスターマインド
    • Python のマスターマインド

    以上がJavaScript Essentials: JavaScript のマスターマインドの一部)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!