TypeScript 学習 part5

はじめに

こちらの本でTypeScriptの学習を進めています。

前回は、Hit&Blowが一通り完成しました。今回は、その続きです。

コミット履歴はこちら

行ったこと

前回の不具合修正

前回、ゲーム実行時にendメソッド内の「試行回数」が表示されなかったのですが、もう一度コードを実行したら直っていました。

バリデーションの追加

ユーザーが、イレギュラーな値を入力した場合の処理を追加しました。

バリデーション実行結果

ソースコード

validateメソッド(HitAndBlowクラス内に追記)

  private validate(inputArr: string[]) {
    const isLengthValid = inputArr.length === this.answer.length
    const isAllAnswerSourseOption = inputArr.every((val) => this.answerSource.includes(val))
    const isAllDifferentValues = inputArr.every((val, i) => inputArr.indexOf(val) === i)
    return isLengthValid && isAllAnswerSourseOption && isAllDifferentValues
  }

validateメソッドの使用

  async play() {
    const inputArr = (await promptInput('「,」区切りで3つの数字を入力してください')).split(',')

    if (!this.validate(inputArr)) {
      printLine('無効な入力です。')
      await this.play()
      return
    }
    
    const result = this.check(inputArr)

    if (result.hit !== this.answer.length) {
      printLine(`---\nHit: ${result.hit}\nBlow: ${result.blow}\n---`)
      this.tryCount += 1
      await this.play()
    } else {
      this.tryCount += 1
    }
  }

モードという概念の導入

ゲームの難易度をhardモードとnormalモードで調整できるようにしました。

normalモードの場合は、入力する数字は3つです。

hardモードの場合は、入力する数字が4つになります。

ソースコード

HitAndBlowクラスで、ユニオン型のmodeプロパティを定義しました。

  private mode: 'normal' | 'hard'

  constructor(mode: 'normal' | 'hard') {
    this.mode = mode
  }

そして、インスタンス生成時にnormalを引数として渡しました。

  ;(async () => {
    const hitAndBlow = new HitAndBlow('normal')
    hitAndBlow.setting()
    await hitAndBlow.play()
    hitAndBlow.end()
  })()

その後、getAnswerLengthというメソッドを作成して、ゲームの難易度を変えられるようにしました。

  private getAnswerLength() {
    switch (this.mode) {
      case 'normal':
        return 3
      case 'hard':
        return 4
    }
  }

settingメソッド内で使用しました。

  setting() {
    const answerLength = this.getAnswerLength()

    while (this.answer.length < answerLength) {
      const randNum = Math.floor(Math.random() * this.answerSource.length)
      const selectedItem = this.answerSource[randNum]
      if (!this.answer.includes(selectedItem)) {
        this.answer.push(selectedItem)
      }
    }
  }

また、playメソッド内でも使用しました。

  async play() {
    const answerLength = this.getAnswerLength()
    const inputArr = (await promptInput(`「,」区切りで${answerLength}つの数字を入力してください`)).split(',')

    if (!this.validate(inputArr)) {
      printLine('無効な入力です。')
      await this.play()
      return
    }

    const result = this.check(inputArr)

    if (result.hit !== this.answer.length) {
      printLine(`---\nHit: ${result.hit}\nBlow: ${result.blow}\n---`)
      this.tryCount += 1
      await this.play()
    } else {
      this.tryCount += 1
    }
  }

これで、インスタンス生成時にhardを引数に渡せば、hardモードにすることが出来るようになりました。

  ;(async () => {
    const hitAndBlow = new HitAndBlow('hard')
    hitAndBlow.setting()
    await hitAndBlow.play()
    hitAndBlow.end()
  })()

経験したエラー

名前 ‘answerLength’ が見つかりません。ts(2304)

エラーの原因

playメソッド内でsettingメソッド内で定義した定数を使用したため発生しました。

  async play() {
    const inputArr = (await promptInput(`「,」区切りで${answerLength}つの数字を入力してください`)).split(',')

// 以下省略
}

解決方法

すぐ上で定数を定義したら解決しました。

async play() {
    const answerLength = this.getAnswerLength()
    const inputArr = (await promptInput(`「,」区切りで${answerLength}つの数字を入力してください`)).split(',')

// 以下省略
}

次回

次回もchapter3を進めていきます。

chapter4では、TO DOアプリをブラウザで表示できるようにしていくみたいなので、楽しみです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です