From f38f18a1b077c60909fd0bff1d7ae32f7aaf77bf Mon Sep 17 00:00:00 2001 From: diego Date: Thu, 17 Apr 2025 17:12:18 -0300 Subject: [PATCH] implement Connect4 challenge --- .../coding/__tests__/connect4.test.mjs | 12 +- technical-fundamentals/coding/connect4.mjs | 129 ++++++++++++++++-- 2 files changed, 126 insertions(+), 15 deletions(-) diff --git a/technical-fundamentals/coding/__tests__/connect4.test.mjs b/technical-fundamentals/coding/__tests__/connect4.test.mjs index 21e1f125..c9c27736 100644 --- a/technical-fundamentals/coding/__tests__/connect4.test.mjs +++ b/technical-fundamentals/coding/__tests__/connect4.test.mjs @@ -1,12 +1,12 @@ -import { describe, it, expect, vi } from "vitest"; -import { Connect4, PLAYER_ONE, PLAYER_TWO } from "../connect4.mjs"; +import { describe, it, expect } from "vitest"; +import { Connect4, PLAYER_ONE } from "../connect4.mjs"; describe("Connect4", () => { it("It should allow you play within bounds", async () => { const c4 = new Connect4({ width: 10, height: 10 }); - expect(c4.getValue(10, 1)).toBeFalsy(); + expect(c4.getValue(9, 1)).toBeFalsy(); c4.play(1); - expect(c4.getValue(10, 1)).toEqual(PLAYER_ONE); + expect(c4.getValue(9, 1)).toEqual(PLAYER_ONE); }); it("It should do nothing if you play out of bounds", async () => { @@ -33,14 +33,14 @@ describe("Connect4", () => { expect(c4.winner()).toEqual(PLAYER_ONE); }); - it("it should detect diagonal winning", () => { + it("it should detect diagonal winning right", () => { const c4 = new Connect4({ width: 10, height: 10 }); const plays = [1, 2, 2, 3, 4, 3, 3, 4, 5, 4, 4]; plays.forEach((p) => c4.play(p)); expect(c4.winner()).toEqual(PLAYER_ONE); }); - it("it should detect diagonal winning", () => { + it("it should detect diagonal winning left", () => { const c4 = new Connect4({ width: 10, height: 10 }); const plays = [1, 2, 2, 3, 4, 3, 3, 4, 5, 4, 4].reverse(); plays.forEach((p) => c4.play(p)); diff --git a/technical-fundamentals/coding/connect4.mjs b/technical-fundamentals/coding/connect4.mjs index 7b673c75..9438a894 100644 --- a/technical-fundamentals/coding/connect4.mjs +++ b/technical-fundamentals/coding/connect4.mjs @@ -1,20 +1,131 @@ /** -Connect4 + Connect4 -Connect4 is a game where two players take turns placing a token on columns that drop to the bottom. -When a player forms 4 of his tokens in a line - horizontally, vertically,or diagonally - the player wins. + Connect4 is a game where two players take turns placing a token on columns that drop to the bottom. + When a player forms 4 of his tokens in a line - horizontally, vertically,or diagonally - the player wins. -[Visualization](https://i.ebayimg.com/images/g/DzMAAOSwSjxj6m0e/s-l1600.jpg) + [Visualization](https://i.ebayimg.com/images/g/DzMAAOSwSjxj6m0e/s-l1600.jpg) -Implement Connect 4 with the class below. -*/ + Implement Connect 4 with the class below. + */ export const PLAYER_ONE = 1; export const PLAYER_TWO = 2; export class Connect4 { - constructor() {} - play(col) {} - checkWinner() {} + board = []; + currentPlayer; + theWinner; + constructor() { + this.board = Array.from({length: 10}, () => Array(10).fill(0)); + this.currentPlayer = PLAYER_ONE; + } + play(col) { + + if (this.theWinner) return; + + for (let row=this.board.length - 1; row>=0; row--) { + if (this.board[row][col] === 0) { + this.board[row][col] = this.currentPlayer; + this.checkWinner(row, col); + break; + } + } + + this.currentPlayer = this.currentPlayer === PLAYER_ONE ? PLAYER_TWO : PLAYER_ONE; + + } + + getValue(row, col) { + if (row<0 || col<0 || row>this.board.length - 1 || col>this.board[0].length) { + return false; + } + + return this.board[row][col]; + } + checkWinner(row, col) { + + const height = this.board.length; + const width = this.board[0].length; + + const checkFour = (self, count) => { + if (count >= 4) { + self.theWinner = self.currentPlayer; + return true; + } + } + + let count = 0; + //vertically bottom + let y = row; + while (y<=height - 1 && this.currentPlayer === this.board[y][col]) { + y++; + count++; + } + if (checkFour(this, count)) return; + + //horizontally left + count = 0; + let x = col; + while (x>=0 && this.currentPlayer === this.board[row][x]) { + x--; + count++; + } + if (checkFour(this, count)) return; + //horizontally right + x = col+1; + while (x<=width && this.currentPlayer === this.board[row][x]) { + x++; + count++; + } + if (checkFour(this, count)) return; + + // diagonally left top + count = 0; + x = col; + y = row; + while (x>=0 && y>=0 && this.currentPlayer === this.board[y][x]) { + x--; + y--; + count++; + } + if (checkFour(this, count)) return; + + // diagonally right bottom + x = col+1; + y = row+1; + while (x<=width - 1 && y<=height - 1 && this.currentPlayer === this.board[y][x]) { + x++; + y++; + count++; + } + if (checkFour(this, count)) return; + + // diagonally right top + count = 0; + x = col; + y = row; + while (x<=width - 1 && y>=0 && this.currentPlayer === this.board[y][x]) { + x++; + y--; + count++; + } + if (checkFour(this, count)) return; + + // diagonally left bottom + x = col-1; + y = row+1; + while (x>=0 && y<=height - 1 && this.currentPlayer === this.board[y][x]) { + x--; + y++; + count++; + } + checkFour(this, count); + + } print() {} + + winner() { + return this.theWinner; + } }