2022.05.01(更新日: 2024.08.08)
TypeScript 学習 part8
はじめに
こちらの本でTypeScriptの学習を進めています。
前回は、ユーザーが想定外の難易度を入力した時の対処を行いました。今回は、その続きです。
コミット履歴はこちら
行ったこと
ユーザーがゲームを選択できるようにしました
新たにジャンケンゲームを追加して、ゲーム開始時にユーザーが、「ヒット・アンド・ブロー」か「ジャンケン」のどちらで遊ぶかを選択できるようにしました。
実行の様子
jankenを選んだので、ジャンケンが開始されました。
GameProcedureクラス
新たにGameProcedureというクラスを作成して、今回の機能を実装しました。
class GameProcedure {
private currentGameTitle: GameTitle | '' = ''
private currentGame: HitAndBlow | Janken | null = null
constructor(private readonly gameStore: GameStore) {}
public async start() {
await this.select()
await this.play()
}
private async select() {
this.currentGameTitle = await promptSelect<GameTitle>('ゲームのタイトルを入力してください', gameTitles)
this.currentGame = this.gameStore[this.currentGameTitle]
}
private async play() {
if(!this.currentGame) throw new ErrorEvent('ゲームが選択されていません')
printLine(`===\n${this.currentGameTitle} を開始します。\n==`)
await this.currentGame.setting()
await this.currentGame.play()
this.currentGame.end()
const action = await promptSelect<NextAction>('ゲームを続けますか?', nextActions)
if (action === 'play again') {
await this.play()
} else if (action === 'exit') {
this.end()
} else {
const neverValue: never = action
throw new Error(`${neverValue} is an invalid action.`)
}
}
private end() {
printLine('ゲームを終了しました。')
process.exit()
}
}
こちらの定数の宣言と型定義も行いました。
const nextActions = ['play again', 'exit'] as const
type NextAction = typeof nextActions[number]
const gameTitles = ['hit and blow', 'janken'] as const
type GameTitle = typeof gameTitles[number]
type GameStore = {
'hit and blow': HitAndBlow
'janken': Janken
}
即時関数で、GameProcedureのインスタンスのstartメソッドを実行しました。
;(async () => {
new GameProcedure({
'hit and blow': new HitAndBlow(),
'janken': new Janken(),
}).start()
})()
ジャンケンクラス
ジャンケンクラスを記述しました。(ソースコードはこちらからコピペしました)
const jankenOptions = ['rock', 'paper', 'scissors'] as const
type JankenOption = typeof jankenOptions[number]
class Janken {
private rounds = 0
private currentRound = 1
private result = {
win: 0,
lose: 0,
draw: 0,
}
async setting() {
const rounds = Number(await promptInput('何本勝負にしますか?'))
if (Number.isInteger(rounds) && 0 < rounds) {
this.rounds = rounds
} else {
await this.setting()
}
}
async play() {
const userSelected = await promptSelect(`【${this.currentRound}回戦】選択肢を入力してください。`, jankenOptions)
const randomSelected = jankenOptions[Math.floor(Math.random() * 3)]
const result = Janken.judge(userSelected, randomSelected)
let resultText: string
switch (result) {
case 'win':
this.result.win += 1
resultText = '勝ち'
break
case 'lose':
this.result.lose += 1
resultText = '負け'
break
case 'draw':
this.result.draw += 1
resultText = 'あいこ'
break
}
printLine(`---\nあなた: ${userSelected}\n相手${randomSelected}\n${resultText}\n---`)
if (this.currentRound < this.rounds) {
this.currentRound += 1
await this.play()
}
}
end() {
printLine(`\n${this.result.win}勝${this.result.lose}敗${this.result.draw}引き分けでした。`)
this.reset()
}
private reset() {
this.rounds = 0
this.currentRound = 1
this.result = {
win: 0,
lose: 0,
draw: 0,
}
}
static judge(userSelected: JankenOption, randomSelected: JankenOption) {
if (userSelected === 'rock') {
if (randomSelected === 'rock') return 'draw'
if (randomSelected === 'paper') return 'lose'
return 'win'
} else if (userSelected === 'paper') {
if (randomSelected === 'rock') return 'win'
if (randomSelected === 'paper') return 'draw'
return 'lose'
} else {
if (randomSelected === 'rock') return 'lose'
if (randomSelected === 'paper') return 'win'
return 'draw'
}
}
}
次回
次回は、ゲームが終わった時に、次のゲームを選択できるようにしていきます。
投稿ID : 2754
コメントを残す