I've been tackling the logic for determining the winner in a Tic Tac Toe game, and found inspiration from this reference:
Connect Four Game Checking for Wins JS
The original win check algorithm was designed for a Connect Four game, so I made some adjustments.
When I run a single loop, like checking for down wins, it works fine. However, if I try to run both loops simultaneously, I encounter this error.
TTT.js:121 Uncaught TypeError: Cannot read properties of undefined (reading '0')
at Object.checkWinner (TTT.js:121)
at <anonymous>:1:4
Searching online for solutions to this error didn't yield much help.
const gameBoard = (() => {
const rows = 3;
const columns = 3;
const board = [];
// creating a 2D array in the console
for (let i = 0; i < rows; i++) {
board[i] = [];
for (let j = 0; j < columns; j++) {
board[i].push(Cell());
}
}
// method for retrieving the entire board for UI rendering
const getboard = () => board;
const printBoard = () => {
const boardWithCellValues = board.map((row) => row.map((cell) => cell.getValue()));
console.log(boardWithCellValues);
return boardWithCellValues;
}
// playMove function for available space checking and validating moves
const playMove = (row, column, player) => {
const availableCells = board.filter((row) => row.map((cell) => cell.getValue().value = 0));
board[row][column].addToken(player);
};
return {
getboard,
printBoard,
playMove,
board
}
})();
// cell represents one square on the board
function Cell() {
let value = 0;
const addToken = (player) => {
value = player;
return value;
}
const getValue = () => value;
return {
getValue,
addToken
}
}
// GameController module/function. Controls flow of game, win logic
function gameController(
playerOneName = "Player One",
playerTwoName = "Player Two"
) {
const players = [
{
name : playerOneName,
token : 1
},
{
name : playerTwoName,
token : 2
}
];
let activePlayer = players[0];
const switchPlayerTurn = () => {
activePlayer = activePlayer === players[0] ? players[1] : players[0];
};
const getActivePlayer = () => activePlayer;
const printNewRound = () => {
gameBoard.printBoard();
console.log(`${getActivePlayer().name}'s turn'`);
};
function checkLine (a,b,c) {
return ((a != 0) && (a == b) && (a == c));
}
function checkWinner (bd) {
for (r = 0; r < 3; r++)
for (c = 0; c < 3; c++)
if (checkLine(bd[r][c], bd[r+1][c], bd[r+2][c])) {
return bd[r][c];
}
for (r = 0; r < 3; r++)
for (c = 0; c < 3; c++)
if (checkLine(bd[r][c], bd[r][c+1], bd[r][c+2])) {
return bd[r][c];
}
return 0;
};
const playRound = (row, column) => {
gameBoard.playMove(row, column, getActivePlayer().token);
switchPlayerTurn();
printNewRound();
}
return {
activePlayer,
switchPlayerTurn,
getActivePlayer,
players,
printNewRound,
playRound,
checkWinner
};
}
const gc = gameController();
gc.playRound(0,0);
gc.playRound(1,0);
gc.playRound(0,1);
gc.playRound(2,2);
gc.playRound(0,2);
/*
gc.playRound(0,0);
gc.playRound(0,1);
gc.playRound(1,0);
gc.playRound(2,2);
gc.playRound(2,0);
*/
I have included code below to auto-populate the array with player tokens in the console. Example:
(3) [Array(3), Array(3), Array(3)]
0: (3) [1, 1, 1]
1: (3) [2, 0, 0]
2: (3) [0, 0, 2]
Individually, these loops work fine. But when combined as intended above, with the down check preceding the right check, it throws the mentioned error.
Why am I encountering issues trying to execute both loops?