Skip to content

Instantly share code, notes, and snippets.

@jvalduvieco
Last active September 4, 2021 07:05
Show Gist options
  • Save jvalduvieco/dbae893bbe9860a9651577f56f4cb6c3 to your computer and use it in GitHub Desktop.
Save jvalduvieco/dbae893bbe9860a9651577f56f4cb6c3 to your computer and use it in GitHub Desktop.
Just a TDD kata wirting a hangman
import React from 'react';
type HangmanGameState = {
result: GameResult | null;
lastGuessStatus: GuessStatus | null;
doneGuesses: string[];
wordToGuess: string;
stage: GameStage;
maxTries: number;
failures: number;
}
enum GuessStatus {
Present = ' Present',
Missing = 'Missing',
Repeated = 'Repeated',
}
enum GameStage {
PLAYING = 'PLAYING',
END = 'END'
}
enum GameResult {
WINNER = 'WINNER',
LOSER = 'LOSER'
}
function createNewGame(wordToGuess: string, maxTries: number = 8): HangmanGameState {
return {
wordToGuess,
lastGuessStatus: null,
doneGuesses: [],
stage: GameStage.PLAYING,
maxTries: maxTries,
result: null,
failures: 0
};
}
function determineGuessStatus(wordToGuess: string, doneGuesses: string[], guess: string): GuessStatus {
if (doneGuesses.includes(guess)) {
return GuessStatus.Repeated;
}
return wordToGuess.includes(guess) ? GuessStatus.Present : GuessStatus.Missing;
}
function makeGuess(state: HangmanGameState, guess: string): HangmanGameState {
const doneGuesses = [...state.doneGuesses, guess];
const lastGuessStatus = determineGuessStatus(state.wordToGuess, state.doneGuesses, guess);
const failures = lastGuessStatus === GuessStatus.Missing ? state.failures + 1 : state.failures;
const isMatching = state.wordToGuess.split('').every(letter => doneGuesses.includes(letter))
const stage = failures === state.maxTries || isMatching ? GameStage.END : state.stage;
const resultIfGameEnds = isMatching ? GameResult.WINNER : GameResult.LOSER;
return {
...state,
lastGuessStatus: lastGuessStatus,
doneGuesses: doneGuesses,
failures: failures,
stage: stage,
result: stage === GameStage.END ? resultIfGameEnds : state.result
}
}
test('can create a new game', () => {
const state = createNewGame('supernova', 8)
expect(state).toEqual({
wordToGuess: 'supernova',
lastGuessStatus: null,
doneGuesses: [],
stage: GameStage.PLAYING,
maxTries: 8,
failures: 0,
result: null
})
});
test('can make a guess', () => {
const state = createNewGame('supernova')
const newState = makeGuess(state, 'a')
expect(newState.doneGuesses).toEqual(['a'])
});
test('can make several guesses', () => {
const state = createNewGame('supernova')
const newState = makeGuess(makeGuess(state, 'a'), 'b')
expect(newState.doneGuesses).toEqual(['a', 'b'])
});
test('a guess might be present', () => {
const state = createNewGame('supernova')
const newState = makeGuess(state, 'a')
expect(newState.lastGuessStatus).toEqual(GuessStatus.Present)
expect(newState.failures).toEqual(0)
});
test('a guess might be missing', () => {
const state = createNewGame('supernova')
const newState = makeGuess(state, 'b')
expect(newState.lastGuessStatus).toEqual(GuessStatus.Missing)
expect(newState.failures).toEqual(1)
});
test('a guess might be repeated, failures are not incremented', () => {
const state = createNewGame('supernova')
const newState = makeGuess(makeGuess(state, 'b'), 'b')
expect(newState.lastGuessStatus).toEqual(GuessStatus.Repeated)
expect(newState.failures).toEqual(1)
});
test('a game can end losing', () => {
const state = createNewGame('supernova', 8)
const endResult = ['b', 'c', 'd', 'f', 'g', 'h', 'i', 'j'].reduce((acc: HangmanGameState, guess: string) => makeGuess(acc, guess), state)
expect(endResult.stage).toEqual(GameStage.END)
expect(endResult.result).toEqual(GameResult.LOSER)
});
test('a game can end winning', () => {
const state = createNewGame('supernova', 8)
const endResult = ['s', 'u', 'p', 'e', 'r', 'n', 'o', 'v', 'a'].reduce((acc: HangmanGameState, guess: string) => makeGuess(acc, guess), state)
expect(endResult.stage).toEqual(GameStage.END)
expect(endResult.result).toEqual(GameResult.WINNER)
});
test('a game can end winning with some failures', () => {
const state = createNewGame('supernova', 8)
const endResult = ['s', 'u', 'p', 'b', 'e', 'r', 'n', 'g', 'g', 'o', 'v', 'a'].reduce((acc: HangmanGameState, guess: string) => makeGuess(acc, guess), state)
expect(endResult.stage).toEqual(GameStage.END)
expect(endResult.result).toEqual(GameResult.WINNER)
expect(endResult.failures).toEqual(2)
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment