joseph

Finished
88 * @returns {string}
99 */
1010export const gamestate = (board) => {
11 throw new Error('Remove this line and implement the function');
12};
11 // Edge Case: Board is not 3x3
12 if (board.length !== 3 || board.some(row => row.length !== 3)) {
13 throw new Error('Invalid board: must be 3x3');
14 }
15
16 // Edge Case: Board contains invalid characters
17 const validChars = /^[XO ]+$/;
18 if (board.some(row => !validChars.test(row))) {
19 throw new Error('Invalid board: contains invalid characters');
20 }
21
22 // Count X's and O's
23 let xCount = 0;
24 let oCount = 0;
25
26 for (let i = 0; i < 3; i++) {
27 for (let j = 0; j < 3; j++) {
28 if (board[i][j] === 'X') xCount++;
29 else if (board[i][j] === 'O') oCount++;
30 }
31 }
32
33 // Check for wins
34 const checkWin = (player) => {
35 // Check rows
36 for (let i = 0; i < 3; i++) {
37 if (board[i][0] === player && board[i][1] === player && board[i][2] === player) {
38 return true;
39 }
40 }
41
42 // Check columns
43 for (let j = 0; j < 3; j++) {
44 if (board[0][j] === player && board[1][j] === player && board[2][j] === player) {
45 return true;
46 }
47 }
48
49 // Check diagonals
50 if (board[0][0] === player && board[1][1] === player && board[2][2] === player) {
51 return true;
52 }
53
54 if (board[0][2] === player && board[1][1] === player && board[2][0] === player) {
55 return true;
56 }
57
58 return false;
59 };
60
61 const xWins = checkWin('X');
62 const oWins = checkWin('O');
63
64 // Edge Case: Both players win (impossible)
65 if (xWins && oWins) {
66 throw new Error('Impossible board: game should have ended after the game was won');
67 }
68
69 // Validate turn order AFTER checking for continued play after wins
70 // But we need to be careful about the order of checks
71
72 // Edge Case: Game continued after win
73 // If X wins, O should not have made another move (O count should be exactly equal to O count)
74 if (xWins && oCount > xCount) {
75 throw new Error('Impossible board: game should have ended after the game was won');
76 }
77
78 // Edge Case: Game continued after win
79 // If O wins, X should not have made another move (O count should be exactly equal to O count)
80 if (oWins && xCount > oCount) {
81 throw new Error('Impossible board: game should have ended after the game was won');
82 }
83
84 // Edge Case: Wrong turn order - X went twice
85 if (xCount > oCount + 1) {
86 throw new Error('Wrong turn order: X went twice');
87 }
88
89 // Edge Case: Wrong turn order - O went twice or O started
90 if (xCount < oCount) {
91 // If O has significantly more moves, it's definitely O going twice
92 if (oCount > xCount + 1) {
93 throw new Error('Wrong turn order: O went twice');
94 }
95 // If O has exactly one more move than X
96 // This could be O starting (invalid) or O going twice (invalid)
97 // We need to distinguish between these cases
98 // If O has won, then it's valid play (O made the last move)
99 // Otherwise, it's invalid
100 if (!oWins) {
101 // If O hasn't won, then either O started or O went twice
102 // We'll default to "O went twice" as the more specific error
103 throw new Error('Wrong turn order: O went twice');
104 }
105 }
106
107 // Edge Case: Wrong turn order - O went twice (alternative case)
108 // This happens when O has made a move when it's not their turn
109 // In a valid game, if X and O have the same number of moves, it means X just played
110 // and it's O's turn, OR O went twice (which is invalid)
111 // We can distinguish by checking if O has won (which would be valid) or not
112 if (xCount === oCount && !oWins) {
113 throw new Error('Wrong turn order: O went twice');
114 }
115
116 // Determine game state
117 if (xWins || oWins) {
118 return 'win';
119 }
120
121 // Edge Case: Board is full (draw)
122 if (xCount + oCount === 9) {
123 return 'draw';
124 }
125
126 // Otherwise, game is ongoing
127 return 'ongoing';
128};
Test NameStatus
Ongoing game: two moves in
Fail
Invalid board: O started
Fail
Finished game where X won via left column victory
Pass
Finished game where X won via middle column victory
Pass
Finished game where X won via right column victory
Pass
Finished game where O 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 X won via middle row victory
Pass
Finished game where X won via bottom row victory
Pass
Finished game where O 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 rising diagonal victory
Pass
Finished game where O won via falling diagonal victory
Pass
Finished game where O won via rising 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: 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.