ki-hi-ro.com WEB制作フリーランスエンジニア
  • Service
    • WEBサイトの更新サポート
    • 新規サイトコーディング
  • Introduce
    • メッセージ
    • 自宅兼事務所
    • Twitter
  • Blog
    • 技術ブログ
    • 学習ブログ
    • 雑記ブログ
  • Others
    • スケジュールのお知らせ
    • お問い合わせ
    • WEBに関する無料相談
  • Top
  • Service
  • Introduce
  • Blog
  • Contact

TypeScript 学習 part7

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

前回は、ユーザーがゲームの難易度を選択できるようにしました。今回は、その続きです。

コミット履歴はこちら

行ったこと

ユーザーが想定外の難易度を入力した時の対処

ゲームの設定では、normalとhardモードしか選ぶことが出来ません。仮にユーザーがvery hardと入力してしまった場合は、エラーが発生してしまう状態でした。

完成後の画面

まずnormalかhardを選ぶことが明示され、ユーザーがvery hardを選んでしまったら、再入力を促すようになりました。

promptSelect関数の作成

ユーザーにモードの選択肢を表示するpromptSelect関数を作成しました。赤字の関数(printLine, readLineについて、この後解説します)

const promptSelect = async (text: string, values: readonly string[]): Promise<string> => {
  printLine(`\n${text}`)
  values.forEach((value) => {
    printLine(`- ${value}`)
  })
  printLine(`> `, false)

  const input = await readLine()
  if (values.includes(input)) {
    return input
  } else {
    return promptSelect(text, values)
  }
}

printLine関数はこちらです。

const printLine = (text: string, breakLine: boolean = true) => {
  process.stdout.write(text + (breakLine ? '\n' : ''))
}

また、readLine関数はこちらです。

const readLine = async () => {
  const input: string = await new Promise((resolve) =>
                          process.stdin.once('data', (data) => resolve(data.toString())))
  return input.trim()
}

promptSelect関数は、settingメソッド内で使用しました。

  async setting() {
    this.mode = await promptSelect('モードを入力してください。', ['normal', 'hard']) as Mode
    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)
      }
    }
  }

ジェネリクスの使用

型を動的に扱えるジェネリクスを使用しました。

const promptSelect = async <T extends string>(text: string, values: readonly string[]): Promise<T> => {
  printLine(`\n${text}`)
  values.forEach((value) => {
    printLine(`- ${value}`)
  })
  printLine(`> `, false)

  const input = (await readLine()) as T
  if (values.includes(input)) {
    return input
  } else {
    return promptSelect<T>(text, values)
  }
}
  async setting() {
    this.mode = await promptSelect<Mode>('モードを入力してください。', ['normal', 'hard'])
    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)
      }
    }
  }

DRYなコードにした

DRY(Don’t repeat yourself)なコードにしました。(繰り返しを避けたコード)

const modes = ['normal', 'hard'] as const
type Mode = typeof modes[number]

class HitAndBlow {
  private readonly answerSource = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
  private answer: string[] = []
  private tryCount = 0
  private mode: Mode = 'normal'

  async setting() {
    this.mode = await promptSelect<Mode>('モードを入力してください。', modes)
    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)
      }
    }
  }
// 以下省略

次回

次回は、新しいブランチを切って、hit and blow以外も遊べるようなゲームにしていきます。

関連記事

2022.05.15 TypeScript TypeScript 学習 part10
2022.05.12 TypeScript TypeScript 学習 part9
2022.05.01 TypeScript TypeScript 学習 part8
2022.04.25 TypeScript TypeScript 学習 part6
2022.04.24 TypeScript TypeScript 学習 part5
2022.04.22 TypeScript TypeScript 学習 part4

サービス一覧

  • WEBサイトの更新サポート
  • 新規サイトコーディング

自己紹介

  • メッセージ
  • 自宅兼事務所
  • Twitter

ブログ

  • 技術ブログ
  • 学習ブログ
  • 雑記ブログ

その他

  • スケジュールのお知らせ
  • お問い合わせ