JavaScript:
class Wall {
constructor() {
}
values() {
return [9,9,9,9]
}
}
class Card {
constructor(values) {
this._values = values;
}
values() {
return this._values;
}
getOwnPosition() {
const index = $GameBoard.tiles().findIndex(card => card === this);
const row = Math.floor(index / $GameBoard.width);
const column = index % $GameBoard.width;
return {row, column, index}
}
leftNeighbor() {
const pos = this.getOwnPosition();
if (pos.column === 0) {
return new Wall();
}
return $GameBoard.tiles()[pos.index - 1];
}
rightNeighbor() {
const pos = this.getOwnPosition();
if (pos.column === $GameBoard.width - 1) {
return new Wall();
}
return $GameBoard.tiles()[pos.index + 1];
}
topNeighbor() {
const pos = this.getOwnPosition();
if (pos.row === 0) {
return new Wall();
}
return $GameBoard.tiles()[pos.index - $GameBoard.width];
}
bottomNeighbor() {
const pos = this.getOwnPosition();
if (pos.row === $GameBoard.height - 1) {
return new Wall();
}
return $GameBoard.tiles()[pos.index + $GameBoard.width];
}
}
class Gameboard {
constructor(width, height) {
this.width = width;
this.height = height;
this.createTiles();
}
tiles() {
return this._tiles;
}
createTiles() {
this._tiles = [];
for (let i = 1; i <= this.width * this.height; i++) {
this.addCardToSlot();
}
}
addCardToSlot() {
const min = 1;
const max = 9;
const values = Array.from({ length: 4 }, () => this.createRandomNumber(min, max))
this._tiles.push(new Card(values));
}
createRandomNumber(min, max) {
return Math.floor((Math.random() * (max - min + 1))) + min;
}
}
// Create Board
const $GameBoard = new Gameboard(3, 3);
// Neighbor example
// retrieves the values of the card above the fourth card (row 2, column 1)
console.log($GameBoard.tiles()[3].topNeighbor().values)
I create a Wall object which will be returned with predefined values whenever we don't have a neighbor. (Can be used for Wall mechanics, e.g. Triple Triad).
This is basically just a gimmick addition, the computer should in the prompt always return "null" (meaning no tile), whereas I decided to hand over the wall.
Then I create the Card Object. This is created with external values, so if I instead of random values wanted to retrieve values from a DB (e.g. a Card Database) I can integrate this easily.
Values is used to always get the cards values (.e.g Triple Triad Card Attack values).
getOwnPosition hands back an object with this card's location data that is dynamically generated. If I simply switch to cards in the main array, the position will automatically update without any further input from me.
The Neighbor checks simply get my own tile's data from the gameboard, then check if there cannot be a Neighbor. (In which case I hand back the Wall)
If it's not a wall, it calculates the correct card index based on the width of the game board and hands me those values.
The Gameboard is pretty simple in its generation.
Some of the advantages present here is that I can access all of the boards tiles through the $GameBoard.tiles() method and don't have to deal with multiple subarrays inside an array.
The Gameboard's position data is always right, the Neighbors always correct, even should the Board for some reason change in size.
While this version is slower (due to retrieving values & doing calculations instead of just picking up pre-defined values), it's very robust. Parameters can be changed easily, and everything still works. It also has a, in my opinion, much more coherent and readable structure, which means the code is much easier to edit & maintain.