import { Constants } from "./Constants.js"; import { elt } from "./elt.js"; import { State } from "./State.js"; /** * Represents a game. */ export class Game { /** * The width of the board. */ static #width = 7; /** * The height of the board. */ static #height = 6; /** * The state of the game. * * @type {State} */ #state; /** * The actual board. * * @type {HTMLElement} */ #board; /** * The element containing a log message. * * @type {HTMLElement} */ #log; /** * The id of the element to add the board to. * * @type {string} */ id; /** * Initializes a new instance of the {@link Game `Game`} class. * * @param {string} id * The id of the element to add the board to. */ constructor(id) { this.id = id; this.#state = new State(Game.#width, Game.#height); } /** * Gets the state of the game. */ get state() { return this.#state; } /** * Gets the board of the game. */ get board() { return this.state.board; } /** * Initializes the game. */ initialize() { let container = document.getElementById(this.id); this.#board = elt( "div", { class: "board" }); this.#log = elt( "div", { class: "log" }); container.appendChild(this.#board); container.appendChild(this.#log); this.draw(); } /** * Resets the game. */ reset() { this.#state = new State(Game.#width, Game.#height); this.draw(); } /** * Replaces the content of the board with the current state. */ draw() { let board = this.#board; board.innerHTML = ""; for (let y = 0; y < Game.#height; y++) { for (let x = 0; x < Game.#width; x++) { /** @type {Node[]} */ let children = []; let playerId = this.board[y][x]; if (playerId !== "") { children.push( elt( "div", { class: `piece ${Constants.PLAYER_NAMES[playerId]}` })); } let field = elt( "div", { class: "field" }, ...children); field.onclick = () => { if (this.addChip(x, y)) { this.state.turnCount++; this.draw(); } }; board.appendChild(field); } } board.appendChild( elt( "div", { style: "clear: both;" })); this.#log.className = ""; this.#log.classList.add(this.state.currentPlayer); this.#log.innerHTML = ""; this.#log.textContent = `It's player "${Constants.PLAYER_NAMES[this.state.currentPlayer]}"s turn`; } /** * Adds a chip to the board indicated by the {@link x `x`} and the {@link y `y`} coordinate. * * @param {number} x * The x coordinate to add the chip to. * * @param {number} y * The y coordinate to add the chip to. * * @returns {boolean} * A value indicating whether the chip could be added. */ addChip(x, y) { for (let i = Game.#height - 1; i >= 0; i--) { if (this.board[i][x] === "") { this.board[i][x] = this.state.currentPlayer; return true; } } return false; } }