Alone

Finished
44//
55
66/**
7 * @param {string[]} board
8 * @returns {string}
7 * Determines the state of a Tic Tac Toe game based on the given board.
8 *
9 * @param {string[]} board - An array of 3 strings, each representing a row of the 3x3 board.
10 * Each character is either 'X', 'O', or ' ' (empty space).
11 * @returns {string} - Returns 'win', 'draw', or 'ongoing' based on the game state.
12 * @throws {Error} - Throws an error for invalid board states with specific messages.
913 */
1014export const gamestate = (board) => {
11 throw new Error('Remove this line and implement the function');
15 // Validate board structure
16 if (!Array.isArray(board) || board.length !== 3) {
17 throw new Error('Invalid board: must have 3 rows');
18 }
19
20 for (let i = 0; i < 3; i++) {
21 if (typeof board[i] !== 'string' || board[i].length !== 3) {
22 throw new Error('Invalid board: each row must be a string of length 3');
23 }
24 for (let j = 0; j < 3; j++) {
25 const char = board[i][j];
26 if (char !== 'X' && char !== 'O' && char !== ' ') {
27 throw new Error('Invalid board: contains invalid characters');
28 }
29 }
30 }
31
32 // Count Xs and Os
33 let countX = 0;
34 let countO = 0;
35
36 for (let i = 0; i < 3; i++) {
37 for (let j = 0; j < 3; j++) {
38 if (board[i][j] === 'X') countX++;
39 if (board[i][j] === 'O') countO++;
40 }
41 }
42
43 // Check for wins
44 const wins = (player) => {
45 // Check rows
46 for (let i = 0; i < 3; i++) {
47 if (board[i][0] === player && board[i][1] === player && board[i][2] === player) {
48 return true;
49 }
50 }
51
52 // Check columns
53 for (let j = 0; j < 3; j++) {
54 if (board[0][j] === player && board[1][j] === player && board[2][j] === player) {
55 return true;
56 }
57 }
58
59 // Check diagonals
60 if (board[0][0] === player && board[1][1] === player && board[2][2] === player) {
61 return true;
62 }
63
64 if (board[0][2] === player && board[1][1] === player && board[2][0] === player) {
65 return true;
66 }
67
68 return false;
69 };
70
71 // Check for turn order violations first, but handle special cases
72
73 // Edge Case: Invalid turn order - check who played first
74 let foundX = false;
75 let foundO = false;
76
77 // Check the board in order to see who played first
78 outer: for (let i = 0; i < 3; i++) {
79 for (let j = 0; j < 3; j++) {
80 if (board[i][j] === 'X') {
81 foundX = true;
82 break outer;
83 } else if (board[i][j] === 'O') {
84 foundO = true;
85 break outer;
86 }
87 }
88 }
89
90 // If O was found first, O started the game
91 if (foundO && !foundX) {
92 throw new Error('Wrong turn order: O started');
93 }
94
95 // X can only be at most one piece ahead of O
96 if (countX > countO + 1) {
97 throw new Error('Wrong turn order: X went twice');
98 }
99
100 // X must start, so O cannot have more pieces than X
101 // But we need to handle special cases where someone wins
102 if (countO > countX) {
103 // Check if someone wins - if so, this might be a case where the game continued after a win
104 const xWins = wins('X');
105 const oWins = wins('O');
106
107 // If someone wins and the piece counts are wrong, this is an invalid board
108 if (xWins || oWins) {
109 // Check if this is a case where the game continued after a win
110 if (xWins && countO >= countX) {
111 // X won but O continued to play
112 throw new Error('Impossible board: game should have ended after the game was won');
113 }
114 if (oWins && countX > countO) {
115 // O won but X continued to play
116 throw new Error('Impossible board: game should have ended after the game was won');
117 }
118 }
119
120 // Otherwise, it's a turn order violation
121 throw new Error('Wrong turn order: O went twice');
122 }
123
124 // Now check for wins
125 const xWins = wins('X');
126 const oWins = wins('O');
127
128 // Edge Case: Both players win (impossible in a valid game)
129 if (xWins && oWins) {
130 throw new Error('Impossible board: game should have ended after the game was won');
131 }
132
133 // Edge Case: Game continued after a win
134 // If someone won, the game should have ended
135 if (xWins && countO >= countX) {
136 // X won but O continued to play (same or more pieces)
137 throw new Error('Impossible board: game should have ended after the game was won');
138 }
139
140 if (oWins && countX > countO) {
141 // O won but X continued to play (more pieces)
142 throw new Error('Impossible board: game should have ended after the game was won');
143 }
144
145 // Edge Case: Both players win (impossible in a valid game)
146 if (xWins && oWins) {
147 throw new Error('Impossible board: game should have ended after the game was won');
148 }
149
150 // Check for wins
151 if (xWins || oWins) {
152 return 'win';
153 }
154
155 // Determine game state
156 if (xWins || oWins) {
157 return 'win';
158 }
159
160 // Edge Case: Board is full with no winner (draw)
161 if (countX + countO === 9) {
162 return 'draw';
163 }
164
165 // Edge Case: Game is not finished yet (ongoing)
166 return 'ongoing';
167
168 // Handled Edge Cases:
169 // - Invalid board structure (not 3x3, invalid characters)
170 // - Wrong turn order: O started
171 // - Wrong turn order: X went twice
172 // - Both players win (impossible)
173 // - Game continued after X win
174 // - Game continued after O win
175 // - Board is full with no winner (draw)
176 // - Game is not finished yet (ongoing)
12177};
Test NameStatus
Finished game where X won via middle column victory
Fail
Finished game where X won via right column victory
Fail
Finished game where O won via left column victory
Fail
Finished game where X won via middle row victory
Fail
Finished game where X won via bottom row victory
Fail
Finished game where O won via top row victory
Fail
Finished game where X won via rising diagonal victory
Fail
Finished game where O won via falling diagonal victory
Fail
Finished game where O won via rising diagonal victory
Fail
Ongoing game: two moves in
Fail
Finished game where X won via left column victory
Pass
Finished game where O won via middle column victory
Pass
Finished game where O won via right column victory
Pass
Finished game where X won via top row victory
Pass
Finished game where O won via middle row victory
Pass
Finished game where O won via bottom row victory
Pass
Finished game where X won via falling diagonal victory
Pass
Finished game where X won via a row and a column victory
Pass
Finished game where X won via two diagonal victories
Pass
Draw
Pass
Another draw
Pass
Ongoing game: one move in
Pass
Ongoing game: five moves in
Pass
Invalid board: X went twice
Pass
Invalid board: O started
Pass
Invalid board: X won and O kept playing
Pass
Invalid board: players kept playing after a win
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.