Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
aa29827
downloaded dependencies
asaniDev Nov 19, 2025
7718c3a
Update project description and bump Jest version in package.json
MohammedNaru Nov 20, 2025
1584ba3
Implement printBoard function to display tic-tac-toe board in the ter…
zilinskyte Nov 22, 2025
55f2678
Refactor printBoard function to improve output formatting and clarity
zilinskyte Nov 22, 2025
1a38062
added tests to check if game is over
asaniDev Nov 22, 2025
c7564b9
Refactor printBoard function to use index-based iteration and improve…
zilinskyte Nov 23, 2025
9e94b66
added tests for checkColum, checkRow and checkDiagonal functions, add…
asaniDev Nov 26, 2025
f5a3800
completed status checker function and added tests for checking a row,…
asaniDev Dec 4, 2025
875712c
Merge pull request #1 from MohammedNaru/Move-maker-Branch
MohammedNaru Dec 4, 2025
f6eac8d
final
zilinskyte Dec 4, 2025
9c5045d
Merge branch 'main' into status-checker
asaniDev Dec 4, 2025
7bd2262
Merge pull request #2 from asaniDev/status-checker
MohammedNaru Dec 4, 2025
c825edf
Merge pull request #3 from zilinskyte/board-printer-function
zilinskyte Dec 4, 2025
822cb1d
exported function
zilinskyte Dec 4, 2025
8477fbb
Merge pull request #1 from zilinskyte/main
asaniDev Dec 4, 2025
1d539c2
Merge pull request #4 from zilinskyte/board-printer-function
zilinskyte Dec 6, 2025
03caf98
Merge branch 'zilinskyte:main' into main
asaniDev Dec 6, 2025
37a6e22
"_"
zilinskyte Dec 6, 2025
aad9fec
Merge pull request #6 from zilinskyte/board-printer-function
zilinskyte Dec 6, 2025
8c387b5
Merge pull request #7 from asaniDev/main
asaniDev Dec 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions __tests__/status-checker.tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import {
isGameOver,
checkIfPlayerWon,
checkRow,
checkColumn,
checkDiagonal,
} from "../status-checker";

describe("test the status of the board at a given time", () => {
test("checkRow returns true when player occupies entire row and false otherwise", () => {
const board = [
["X", "_", "O"],
["X", "X", "X"],
["O", "_", "O"],
];

expect(checkRow(board, "X", 1)).toBe(true);
expect(checkRow(board, "O", 1)).toBe(false);
expect(checkRow(board, "X", 0)).toBe(false);
});

test("checkColumn returns true when player occupies entire column and false otherwise", () => {
const board = [
["O", "X", "_"],
["O", "X", "X"],
["O", "_", "_"],
];

expect(checkColumn(board, "O", 0)).toBe(true);
expect(checkColumn(board, "X", 1)).toBe(false);
expect(checkColumn(board, "X", 2)).toBe(false);
});

test("checkDiagonal returns true for both diagonal wins", () => {
const board = [
["X", "O", "_"],
["O", "X", "_"],
["_", "_", "X"],
];

expect(checkDiagonal(board, "X")).toBe(true);

const anti = [
["_", "_", "O"],
["_", "O", "_"],
["O", "_", "_"],
];

expect(checkDiagonal(anti, "O")).toBe(true);
});
});

describe("checks if a player has won given a board and player value", () => {
test("checkIfPlayerWon detects wins via rows, columns and diagonals", () => {
const rowWin = [
["X", "X", "X"],
["O", "_", "O"],
["_", "_", "_"],
];

const colWin = [
["O", "X", "_"],
["O", "X", "_"],
["O", "_", "X"],
];

const diagWin = [
["X", "O", "_"],
["_", "X", "O"],
["_", "_", "X"],
];

const diagWinAnti = [
["X", "X", "O"],
["X", "O", "O"],
["O", "_", "X"],
];

expect(checkIfPlayerWon(rowWin, "X")).toBe(true);
expect(checkIfPlayerWon(colWin, "O")).toBe(true);
expect(checkIfPlayerWon(diagWin, "X")).toBe(true);
expect(checkIfPlayerWon(diagWinAnti, "O")).toBe(true);
});
});
29 changes: 27 additions & 2 deletions board-printer.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,38 @@
=================
Test your function by calling it with an example tic-tac-toe board.
*/
export function printBoard(board) {

let board = [
["_", "_", "_"],
["_", "_", "_"],
["_", "_", "_"],
];

export function printBoard(board) {
// Setting parameter board within the function printBoard
for (let i = 0; i < board.length; i++) {
// loop array of 3 arrays, adds count of one to index
const rowString = board[i].map((cell) => ` ${cell} `).join("|"); // map each cell to a string with spaces and join with '|'
console.log(rowString); // print the row string
if (i < board.length - 1) {
console.log("-----------"); // print separator after each row except the last
}
}
}
printBoard(board);

/*
Given a tic-tac-toe board (an array of arrays),
- return true if there are no moves left to make (there are no more '_' values)
- return false if there are still moves that can be made
*/
export function checkIfNoMovesLeft(board) {
export function checkIfNoMovesLeft(board) {
for (let row of board) {
for (let cell of row) {
if (cell === "_") {
return false;
}
}
}
return true;
}
52 changes: 21 additions & 31 deletions move-maker.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,26 @@
/*
Given a move and a board (an array of arrays), return true if the move is valid.
A move is represented by 2 numbers separated by a comma.
The first number is the row (1, 2 or 3) and the second number is the column (1, 2 or 3).
Some valid example moves are 1,3 and 2,2.
Some invalid examples are 0,1 and 2-1.
Also, a move can only be made in a free space ('_') on the board.
If the move is not valid:
- you can output 'Try again...'
- and then return false
Testing your function by calling it with some values. An example board is:
let board = [
['X', '_', '_'],
['_', 'X', '_'],
['O', 'O', 'X']
];
*/
function validateMove(move, board) {
// Implement this at the end if you have time, otherwise you can help your teammates!
export function validateMove(move, board) {
const [row, col] = move.split(",").map(Number);

// check if row/col are numbers 1-3
if (![1, 2, 3].includes(row) || ![1, 2, 3].includes(col)) {
console.log("Try again...");
return false;
}

// check if the space is free
if (board[row - 1][col - 1] !== "_") {
console.log("Try again...");
return false;
}

return true;
}

/*
Given 3 parameters:
- a board (an array of arrays)
- a move (2 numbers separated by a comma)
- a player ('X' or 'O'):
Check that the move is valid using the validateMove function.
If the move is not valid, the function should just return false.
If the move is valid, the function should:
- Update the board with the player's value ('X' or 'O') in the correct position
- Return true
*/
export function makeMove(board, move, player) {
return false;
if (!validateMove(move, board)) return false;

const [row, col] = move.split(",").map(Number);
board[row - 1][col - 1] = player;

return true;
}
57 changes: 57 additions & 0 deletions move-maker.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { makeMove, validateMove } from "./move-maker.js";

describe("validateMove", () => {
let board;

beforeEach(() => {
board = [
["X", "_", "_"],
["_", "X", "_"],
["O", "O", "X"]
];
});

test("valid move on empty space", () => {
expect(validateMove("1,2", board)).toBe(true);
});

test("invalid move outside board", () => {
expect(validateMove("0,1", board)).toBe(false);
expect(validateMove("4,2", board)).toBe(false);
});

test("invalid move in occupied space", () => {
expect(validateMove("1,1", board)).toBe(false);
expect(validateMove("3,1", board)).toBe(false);
});

test("invalid move with wrong format", () => {
expect(validateMove("2-1", board)).toBe(false);
});
});

describe("makeMove", () => {
let board;

beforeEach(() => {
board = [
["X", "_", "_"],
["_", "X", "_"],
["O", "O", "X"]
];
});

test("makes a valid move for player X", () => {
expect(makeMove(board, "1,2", "X")).toBe(true);
expect(board[0][1]).toBe("X");
});

test("makes a valid move for player O", () => {
expect(makeMove(board, "2,1", "O")).toBe(true);
expect(board[1][0]).toBe("O");
});

test("returns false for invalid move", () => {
expect(makeMove(board, "1,1", "X")).toBe(false);
});
});
Loading