2022.04.28(更新日: 2024.08.08)
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以外も遊べるようなゲームにしていきます。
投稿ID : 2624
コメントを残す