LoginSignup
2
1

More than 3 years have passed since last update.

【JavaScript/初学者向け】打倒!ズンドコキヨシ(後半戦)

Last updated at Posted at 2020-09-26

こんにちは!どいこです。

ズンドコキヨシ問題について、前回の記事で
「「ズン」「ドコ」のいずれかをランダムで出力」する所までできました。

前回:【JavaScript/初学者向け】打倒!ズンドコキヨシ(前半戦)

しかし、まだキヨシは倒れていない・・・!

あきらめたらそこで試合終了なので、続きをやります。

ズンドコキヨシとは(再掲)

「ズン」「ドコ」のいずれかをランダムで出力し続けて
「ズン」「ズン」「ズン」「ズン」「ドコ」の配列が出たら
「キ・ヨ・シ!」って出力した後終了する

手順その②

「ズン」「ズン」「ズン」「ズン」「ドコ」の配列が出たら
「キ・ヨ・シ!」って出力した後終了する

・ まずは「この並びで出たら反応するよ~」の「この並び」を判定するための配列(targetList)と
 「反応」の内容(answer)を定義しておきます。

const targetList = ['ズン', 'ズン', 'ズン', 'ズン', 'ドコ']
const answer = 'キ・ヨ・シ!'


・ 次は「並びがtargetListと同じか」を判定する段階ですね。
  勇者どいこはココでつまづきました。

つまづいた所(キヨシが出てこない)

if (randomOutput === targetList) {
   console.log(answer)
}

要は「ランダムで作った配列の内容がtargetListと同じ=
['ズン', 'ズン', 'ズン', 'ズン', 'ドコ']だったら
'キ・ヨ・シ!'って表示させようぜ!」
って意味なんですが

「'ズン', 'ズン', 'ズン', 'ズン', 'ドコ'」って出力されてる時もキヨシが出てこない。

♪せつなさよりも遠くへ~:joy:

なぜ?
その理由とは・・・

変数の中に直接配列が入っているわけではありません。
変数の中には、「参照」と呼ばれる「配列の場所」が記録されていて、
配列の実体は別の場所(メモリ上のどこか)にあります。

JavaScriptの変数と配列と参照について


この事から、上のif文での比較においても
配列の中身の値を見比べているのではなく、参照先(保管場所)を見比べている事になります。

randomOutputtargetListは、そもそも保管場所は異なりますよね。
(それぞれ別々に作られたものなので)

中身の値ではなく「お互いの保管場所を比較している」ため
結果はelseとなり、我々は「キ・ヨ・シ!」と叫ぶ事もままならないわけです。

解決策

join()を使う事にしました。
※当初はjson()を使うやり方を記載していましたが、物々しいので
 コメントでのアドバイスを元に修正しました。ありがとうございます!

if (randomOutput.join() === targetList.join()) {
   console.log(answer)
}

join() メソッドは、配列 (または配列風オブジェクト) の全要素を順に連結した文字列を新たに作成して返します。
区切り文字はコンマ、または指定された文字列です。

Array.prototype.join() - MDN web docs

join()効果で、むきだしの値同士を突き合わせる事ができ
randomOutputの出力が「'ズン', 'ズン', 'ズン', 'ズン', 'ドコ'」の時に
無事「'キ・ヨ・シ!'」と表示されるようになりました。

やったね:relaxed:


ちなみに「'キ・ヨ・シ!'」と叫んだら、ズンドコタイムは終了するのがお約束です。
forとは違って回数の決まっていないループ処理なので、while文を使います。
(条件式に当てはまる間だけ処理を繰り返し、当てはまらなくなったら終了させる)

なおかつ今回は、先に「ランダム配列を作る」必要があるので
do...whileを使います。

do...while 文は指定された文を、テスト条件が false に評価されるまで実行するループを作成します。条件は文を実行した後に評価されます。
結果として、指定された文は少なくとも 1 回は実行されます。

do...while - MDN web docs

■ do   : ランダム配列のrandomOutputを生成&出力
■ while : 生成された配列とtargetListを比較、一致しなければ再びdoを実行
      (一致しない間処理を繰り返す ⇒ 一致したら終了)

do {
    // wordListのインデックス[0] or [1]をランダムで生成し、結果をrandomOutputの要素へ代入する処理を
    // 要素数(5個)分ループさせる
    for (let i = 0; i < randomOutput.length; i++) {
      randomOutput[i] = wordList[Math.floor(Math.random() * wordList.length)]
    }
    console.log(randomOutput) // ランダムに生成された配列を表示
    // トリガーとなる配列が現れるまで処理をループ
} while (randomOutput.join() !== targetList.join())


回答まとめ(コード全体)

function kiyoshi() {

  const wordList = ['ズン','ドコ'] // ランダムで表示するワード候補2種
  const elementsLength = 5
  const randomOutput = [...Array(elementsLength)] // 未定義の要素 × 5個の配列
  const targetList = ['ズン', 'ズン', 'ズン', 'ズン', 'ドコ'] // トリガーとなる配列
  const answer = 'キ・ヨ・シ!' //トリガーとなる配列が現れたら表示させるワード

  do {
    // wordListのインデックス[0] or [1]をランダムで生成し、結果をrandomOutputの要素へ代入する処理を
    // 要素数(5個)分ループさせる
      for (let i = 0; i < randomOutput.length; i++) {
        randomOutput[i] = wordList[Math.floor(Math.random() * wordList.length)]
      }
      console.log(randomOutput) // ランダムに生成された配列を表示
      // トリガーとなる配列が現れるまで処理をループ
  } while (randomOutput.join() !== targetList.join())
  // トリガー配列が現れたらループから抜けてanswerを表示させる
  console.log(answer)

}

(当初whileで書いていた所を、これまたコメントでアドバイスを頂き
 do…whileに修正しています。ありがとうございます。)

俺たちの戦いはこれからだ!:innocent:


ー最後までお読み頂き、とてもうれしく思います。
 ありがとうございました。

2
1
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1