wtnb_dev
ヌメロンで学ぶJavaScriptの基本文法

ヌメロンで学ぶJavaScriptの基本文法

wtnb_dev

こんにちは、ワタナベ(wtnb_dev)です。

なるべく毎日投稿しようと思ってますが、早速ネタを考えるのを忘れていたので簡単なものを。

対象読者

・JavaScript初学者
・ヌメロン(※後述)に興味がある方

ヌメロンとは?

私もさっき知ったばかりですが。笑

3桁の数値を当てるゲームみたいです。

ルールは以下を参照させて頂きました。m(__)m

Numer0n数当てゲーム

今回は、ヌメロンをJavaScriptで実装していき、JavaScriptの基本文法について見ていきたいと思います。

その前に脱線

私自身、プログラミングを始めたばかりの頃は、マルバツゲームやオセロなどのミニゲームを実装することで、基本文法を身につけていた記憶があります。

プログラミングを始めたばかりの方にとって、今回のヌメロンも丁度良い題材になるのではと思っています。

それでは実装しましょう

1. 開発環境の構築

まずは開発環境を構築します。

今回は、JavaScriptの実行環境として、Node.jsを用います。

まだインストールされていない方は、以下からインストールできます。

JavaScriptというと、ブラウザ上で動作させるイメージの方も多いかと思いますが、Node.jsを用いることで、コマンドプロンプト(ターミナル)上でJavaScriptを実行することが可能になります。

興味のある方は、上記公式サイトを読んでみると良いでしょう。

Node.jsのインストールの確認は、コマンドプロンプト(ターミナル)上で「node -v」と実行し、バージョン情報が表示されればOKです。

$ node -v
v12.9.1

2. Node.jsを使ってみる

"Hello World"と出力するサンプルのJavaScriptを作成し、Node.jsで実行してみましょう。

まず以下のJavaScriptファイルを任意のエディタで作成します。

ファイル名は何でも良いですが、今回は「index.js」としましょう。

console.log("Hello World");

次に、index.jsを作成したディレクトリでコマンドプロンプト(ターミナル)を開き、「node index.js」と実行します。

$ node index.js 
Hello World

"Hello World"と出力されれば成功です。

このように、nodeコマンドの後に実行したいJavaScriptファイルを指定することで実行できます。

3. ヌメロンの実装

それでは準備が整ったので、ヌメロンを実装してきましょう。

今回作成するファイルは1つのみです。

まとまりごとに説明していきます。本記事の最後に、全ソースを記載しますので、コピペしたい方はそちらをどうぞ。

Step1. 回答を格納する配列を用意

const ansNum = new Array(3);

回答は3桁の数値なので、要素数3の配列を用意します。

Step2. 回答を生成する関数を定義

function initAnsNum() {
  ansNum[0] = Math.floor(Math.random() * 10);
  do {
    ansNum[1] = Math.floor(Math.random() * 10);
  } while (ansNum[0] === ansNum[1]);
  do {
    ansNum[2] = Math.floor(Math.random() * 10);
  } while (ansNum[0] === ansNum[2] || ansNum[1] === ansNum[2]);
}

initAnsNum();

今回は乱数を用いて、3桁の回答を生成します。

最初に1桁目を乱数で生成し、2桁目は、do-while文を用いて、1桁目と異なる乱数になるまでループしています。

これは、ヌメロンのルールで、3桁の数値は異なる必要があるためです。

3桁目も同様にdo-while文を使用し、1桁目、2桁目と異なる乱数になるまでループしています。

最後に、本関数を呼び出すことで、回答を生成します。

Step3. ゲームループ処理

let isFinish = false;
const pat = /^\d{3}$/

while(!isFinish) {
  // ゲームループ処理
}

最初に、変数isFinishを初期値falseで宣言します。このフラグがtrueになるまで、ゲームループを繰り返します。

変数patは、入力された文字列が、数値3桁かどうかを判定するための正規表現です。固定値なので、ループの外で宣言しています。

正規表現については以下の記事などが参考になります。

JavaScript 正規表現まとめ

Step4. ゲームループの中身の実装

ゲームループの中身を実装してきます。

console.log("予想数値を入力");
let input = require('fs').readFileSync('/dev/stdin', 'UTF-8');
input = input.slice(0, input.length - 1);

if (!pat.test(input)) {
  console.log("3桁の数値を入力してください。");
  continue;
}

if (input[0] === input[1] || input[0] === input[2] || input[1] === input[2]) {
  console.log("異なる3桁の数値を入力してください。");
  continue;
}

最初に、標準入力された文字列を、変数inputに格納しています。

# 上記の標準入力は、Macで試しており、Windowsでは動きません(試してないですが動かないはず)。Windowsユーザの方は、「windows node 標準入力」などで調べて、readFileSyncの行を変更していただければと思います。

# 標準入力の方法は、入力の終わりを表すctrl+Dを用いて、以下のようになります。

予想数値を入力
123             // 1つ目の入力
ctrl+D          // ctrl+Dで入力の終了
0 EAT, 3 BITE
予想数値を入力
230             // 2つ目の入力
ctrl+D          // ctrl+Dで入力の終了

ctrl+C          // ゲームを終了したい場合はctrl+C

次に、sliceメソッドを用いて、末尾の1文字を削除しています。これは、標準入力から文字列を取得した際に、末尾に改行コードが含まれるため、それを取り除く処理になります。

次のif文で、Step3で用意した正規表現を用いて、入力された文字列が3桁の数値かどうかを判定しています。違う場合は、continueを用いて、ループ処理を始めからやり直します。

その次のif文では、入力された3桁の数値が、全て異なる数値かどうかを判定しています。これはヌメロンのルールによるものです。

Step5. 入力値と回答が一致しているかチェック

let eat = 0;
let bite = 0;
for (let i = 0; i < input.length; i++) {
  for (let j = 0; j < ansNum.length; j++) {
    if (input[i] == ansNum[j]) {
      if (i === j) {
        eat = eat+1;
      } else {
        bite = bite+1;
      }
    }
  }
}

2重ループを用いて、入力値と回答を比較し、eatの個数とbiteの個数をカウントしています。

Step6. 結果を出力

console.log(`${eat} EAT, ${bite} BITE`);
if (eat === 3) {
  console.log("正解です。おめでとう!");
  isFinish = true;
}

カウントしたeatとbiteの個数を出力しています。

バッククォート(`)で囲んだ文字列内では、${変数}のように記載することで、変数の値を埋め込むことができます。

eatが3の場合は、入力値と回答が一致しているので、isFinishをtrueに更新し、ゲームループを抜けて処理を終了します。

まとめ

あまり動かしてないので、もし誤りありましたらコメント等で教えていただけると修正します。

ヌメロンに限らず、オセロや囲碁、マルバツゲームなど、自分の興味のあるゲームを実装することは、楽しみながら基本文法を身につけられる良き勉強方法だと思います。

他にも自作ゲームなどを作ってみても面白いかもですね。

<参考>ソース全文

const ansNum = new Array(3);
function initAnsNum() {
  ansNum[0] = Math.floor(Math.random() * 10);
  do {
    ansNum[1] = Math.floor(Math.random() * 10);
  } while (ansNum[0] === ansNum[1]);
  do {
    ansNum[2] = Math.floor(Math.random() * 10);
  } while (ansNum[0] === ansNum[2] || ansNum[1] === ansNum[2]);
}

initAnsNum();

let isFinish = false;
const pat = /^\d{3}$/

while(!isFinish) {
  // ゲームループ処理
  console.log("予想数値を入力");
  let input = require('fs').readFileSync('/dev/stdin', 'UTF-8');
  input = input.slice(0, input.length - 1);
  if (!pat.test(input)) {
    console.log("3桁の数値を入力してください。");
    continue;
  }
  if (input[0] === input[1] || input[0] === input[2] || input[1] === input[2]) {
    console.log("異なる3桁の数値を入力してください。");
    continue;
  }
  
  let eat = 0;
  let bite = 0;
  for (let i = 0; i < input.length; i++) {
    for (let j = 0; j < ansNum.length; j++) {
      if (input[i] == ansNum[j]) {
        if (i === j) {
          eat = eat+1;
        } else {
          bite = bite+1;
        }
      }
    }
  }
  console.log(`${eat} EAT, ${bite} BITE`);
  if (eat === 3) {
    console.log("正解です。おめでとう!");
    isFinish = true;
  }
}
この記事が気に入ったら、サポートをしてみませんか?
気軽にクリエイターの支援と、記事のオススメができます!
wtnb_dev
はじめまして、ワタナベと申します。 都内でフリーランスエンジニアをやっています。 技術的なnoteを書いていく予定です。 YouTubeでプログラミング関連の配信をしています。 http://urx.red/ZNOW