UNPKG

scrabble-solver

Version:

Scrabble Solver 2 - Free, open-source, cross-platform, multi-language analysis tool for Scrabble, Scrabble Duel, Super Scrabble, Letter League, Literaki, and Kelimelik. Quickly find the top-scoring words using the given board and tiles.

116 lines (115 loc) 4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Board = void 0; const constants_1 = require("@scrabble-solver/constants"); const Cell_1 = require("./Cell"); const Tile_1 = require("./Tile"); class Board { static fromStringArray(stringArray) { return new Board({ rows: stringArray.map((row, y) => row.split('').map((character, x) => new Cell_1.Cell({ isEmpty: !character || character === constants_1.EMPTY_CELL, tile: character === constants_1.EMPTY_CELL ? Tile_1.Tile.Null : new Tile_1.Tile({ character }), x, y, }))), }); } constructor({ rows }) { this.rows = rows; this.columnsCount = rows[0].length; this.rowsCount = rows.length; } get center() { const x = Math.floor(this.columnsCount / 2); const y = Math.floor(this.rowsCount / 2); return this.rows[y][x]; } clone() { const rows = this.rows.map((row) => row.map((cell) => cell.clone())); return new Board({ rows }); } collides(cell) { return this.collidesUp(cell) || this.collidesDown(cell) || this.collidesLeft(cell) || this.collidesRight(cell); } collidesDown({ x, y }) { return y < this.rowsCount - 1 && !this.rows[y + 1][x].isEmpty; } collidesLeft({ x, y }) { return x > 0 && !this.rows[y][x - 1].isEmpty; } collidesRight({ x, y }) { return x < this.columnsCount - 1 && !this.rows[y][x + 1].isEmpty; } collidesUp({ x, y }) { return y > 0 && !this.rows[y - 1][x].isEmpty; } equals(other) { return (this.columnsCount === other.columnsCount && this.rowsCount === other.rowsCount && this.rows.every((row, rowIndex) => { return row.every((cell, cellIndex) => { return cell.equals(other.rows[rowIndex][cellIndex]); }); })); } getBlanksCount() { return this.rows.reduce((count, row) => { return count + row.reduce((rowCount, cell) => rowCount + (cell.tile.isBlank ? 1 : 0), 0); }, 0); } getColumn(index) { return this.rows.map((row) => row[index]); } getRow(index) { return this.rows[index]; } getTilesCount() { return this.rows.reduce((count, row) => { return count + row.reduce((rowCount, cell) => rowCount + (cell.hasTile() ? 1 : 0), 0); }, 0); } getWords() { const columns = []; for (let x = 0; x < this.columnsCount; ++x) { const column = []; for (let y = 0; y < this.rowsCount; ++y) { column.push(this.rows[y][x]); } columns.push(column); } const columnsBoard = new Board({ rows: columns }); const lines = this.toString().split('\n').concat(columnsBoard.toString().split('\n')); const words = lines .flatMap((line) => line.replaceAll(/\s+/g, constants_1.EMPTY_CELL).split(' ')) .filter((word) => word.length > 1); return words; } isEmpty() { return this.rows.every((row) => row.every(({ isEmpty }) => isEmpty)); } toJson() { return this.rows.map((row) => row.map((cell) => cell.toJson())); } toString() { return this.rows.map((row) => row.map(String).join('')).join('\n'); } updateCell(x, y, updateCell) { this.rows[y][x] = updateCell(this.rows[y][x]); } updateRow(y, updateRow) { this.rows[y] = updateRow(this.rows[y]); } } exports.Board = Board; Board.create = (width, height) => { const rows = Array(height); const emptyRow = Array(width).fill(' ').join(''); const emptyRows = rows.fill(emptyRow); return Board.fromStringArray(emptyRows); }; Board.fromJson = (json) => { return new Board({ rows: json.map((row) => row.map(Cell_1.Cell.fromJson)), }); };