76 lines
1.7 KiB
TypeScript
76 lines
1.7 KiB
TypeScript
|
import { words, allowed } from './words.server';
|
||
|
|
||
|
export class Game {
|
||
|
index: number;
|
||
|
guesses: string[];
|
||
|
answers: string[];
|
||
|
answer: string;
|
||
|
|
||
|
/**
|
||
|
* Create a game object from the player's cookie, or initialise a new game
|
||
|
*/
|
||
|
constructor(serialized: string | undefined = undefined) {
|
||
|
if (serialized) {
|
||
|
const [index, guesses, answers] = serialized.split('-');
|
||
|
|
||
|
this.index = +index;
|
||
|
this.guesses = guesses ? guesses.split(' ') : [];
|
||
|
this.answers = answers ? answers.split(' ') : [];
|
||
|
} else {
|
||
|
this.index = Math.floor(Math.random() * words.length);
|
||
|
this.guesses = ['', '', '', '', '', ''];
|
||
|
this.answers = [];
|
||
|
}
|
||
|
|
||
|
this.answer = words[this.index];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Update game state based on a guess of a five-letter word. Returns
|
||
|
* true if the guess was valid, false otherwise
|
||
|
*/
|
||
|
enter(letters: string[]) {
|
||
|
const word = letters.join('');
|
||
|
const valid = allowed.has(word);
|
||
|
|
||
|
if (!valid) return false;
|
||
|
|
||
|
this.guesses[this.answers.length] = word;
|
||
|
|
||
|
const available = Array.from(this.answer);
|
||
|
const answer = Array(5).fill('_');
|
||
|
|
||
|
// first, find exact matches
|
||
|
for (let i = 0; i < 5; i += 1) {
|
||
|
if (letters[i] === available[i]) {
|
||
|
answer[i] = 'x';
|
||
|
available[i] = ' ';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// then find close matches (this has to happen
|
||
|
// in a second step, otherwise an early close
|
||
|
// match can prevent a later exact match)
|
||
|
for (let i = 0; i < 5; i += 1) {
|
||
|
if (answer[i] === '_') {
|
||
|
const index = available.indexOf(letters[i]);
|
||
|
if (index !== -1) {
|
||
|
answer[i] = 'c';
|
||
|
available[index] = ' ';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.answers.push(answer.join(''));
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Serialize game state so it can be set as a cookie
|
||
|
*/
|
||
|
toString() {
|
||
|
return `${this.index}-${this.guesses.join(' ')}-${this.answers.join(' ')}`;
|
||
|
}
|
||
|
}
|