1,787 bytes View directory
1 import { allowed, words } from './words.server.ts';
2
3 export class Game {
4 index: number;
5 guesses: string[];
6 answers: string[];
7 answer: string;
8
9 /**
10 * Create a game object from the player's cookie, or initialise a new game
11 */
12 constructor(serialized: string | undefined = undefined) {
13 if (serialized) {
14 const [index, guesses, answers] = serialized.split('-');
16 this.index = +index;
17 this.guesses = guesses ? guesses.split(' ') : [];
18 this.answers = answers ? answers.split(' ') : [];
19 } else {
20 this.index = Math.floor(Math.random() * words.length);
21 this.guesses = ['', '', '', '', '', ''];
22 this.answers = [];
23 }
25 this.answer = words[this.index];
26 }
28 /**
29 * Update game state based on a guess of a five-letter word. Returns
30 * true if the guess was valid, false otherwise
31 */
32 enter(letters: string[]) {
33 const word = letters.join('');
34 const valid = allowed.has(word);
36 if (!valid) return false;
38 this.guesses[this.answers.length] = word;
40 const available = Array.from(this.answer);
41 const answer = Array(5).fill('_');
43 // first, find exact matches
44 for (let i = 0; i < 5; i += 1) {
45 if (letters[i] === available[i]) {
46 answer[i] = 'x';
47 available[i] = ' ';
48 }
49 }
51 // then find close matches (this has to happen
52 // in a second step, otherwise an early close
53 // match can prevent a later exact match)
54 for (let i = 0; i < 5; i += 1) {
55 if (answer[i] === '_') {
56 const index = available.indexOf(letters[i]);
57 if (index !== -1) {
58 answer[i] = 'c';
59 available[index] = ' ';
60 }
61 }
62 }
64 this.answers.push(answer.join(''));
66 return true;
67 }
69 /**
70 * Serialize game state so it can be set as a cookie
71 */
72 toString() {
73 return `${this.index}-${this.guesses.join(' ')}-${this.answers.join(' ')}`;
74 }
75 }