JSFiddle - React, Tailwind, and code Playground
by jcubed111
HTML
<canvas id="overlay" width=500 height=500></canvas>
<div class="row" id="r7">
<div class="cell" id="c0"></div>
<div class="cell" id="c1"></div>
<div class="cell" id="c2"></div>
<div class="cell" id="c3"></div>
<div class="cell" id="c4"></div>
<div class="cell" id="c5"></div>
<div class="cell" id="c6"></div>
<div class="cell" id="c7"></div>
</div>
<div class="row" id="r6">
<div class="cell" id="c0"></div>
<div class="cell" id="c1"></div>
<div class="cell" id="c2"></div>
<div class="cell" id="c3"></div>
<div class="cell" id="c4"></div>
<div class="cell" id="c5"></div>
<div class="cell" id="c6"></div>
<div class="cell" id="c7"></div>
</div>
<div class="row" id="r5">
<div class="cell" id="c0"></div>
<div class="cell" id="c1"></div>
<div class="cell" id="c2"></div>
<div class="cell" id="c3"></div>
<div class="cell" id="c4"></div>
<div class="cell" id="c5"></div>
<div class="cell" id="c6"></div>
<div class="cell" id="c7"></div>
</div>
<div class="row" id="r4">
<div class="cell" id="c0"></div>
<div class="cell" id="c1"></div>
<div class="cell" id="c2"></div>
<div class="cell" id="c3"></div>
<div class="cell" id="c4"></div>
<div class="cell" id="c5"></div>
<div class="cell" id="c6"></div>
<div class="cell" id="c7"></div>
</div>
<div class="row" id="r3">
<div class="cell" id="c0"></div>
<div class="cell" id="c1"></div>
<div class="cell" id="c2"></div>
<div class="cell" id="c3"></div>
<div class="cell" id="c4"></div>
<div class="cell" id="c5"></div>
<div class="cell" id="c6"></div>
<div class="cell" id="c7"></div>
</div>
<div class="row" id="r2">
<div class="cell" id="c0"></div>
<div class="cell" id="c1"></div>
<div class="cell" id="c2"></div>
<div class="cell" id="c3"></div>
<div class="cell" id="c4"></div>
<div class="cell" id="c5"></div>
<div class="cell" id="c6"></div>
<div...
SCSS
#overlay{
position: absolute;
left: 8px;
top: 8px;
pointer-events: none;
z-index: 5;
}
.row{
display: flex;
}
.cell{
box-sizing: border-box;
width: 50px;
height: 50px;
background: #eee;
text-align: center;
padding-top: 4px;
}
.row:nth-child(2n+1) {
.cell:nth-child(2n) {
background: #ddd;
}
}
.row:nth-child(2n) {
.cell:nth-child(2n+1) {
background: #ddd;
}
}
.cell.goal{
box-shadow: inset 0 0 0 2px #0af;
}
.cell.current{
font-size: 40px;
font-family: sans-serif;
}
.cell.option{
cursor: pointer;
box-shadow: inset 0 0 0 2px #3d3;
}
.cell.void{
background: #555 !important;
}
#pieces{
margin-top: 5px;
font-size: 40px;
font-family: sans-serif;
display: flex;
}
.piece{
width: 50px;
height: 50px;
background: #eee;
text-align: center;
padding-top: 4px;
box-sizing: border-box;
&.active{
background: #fff;
}
}
JavaScript
const ctx = document.getElementById('overlay').getContext('2d');
function getCell(x, y) {
return document.querySelector(`#r${y} #c${x}`);
}
function strBoardToBin(boardString) {
const rows = boardString.trim().split('\n').reverse();
return rows.map(row => {
let rowValue = 0;
row.trim().split(' ').reverse().forEach(cell => {
if(cell == '1') rowValue++;
rowValue *= 2;
});
return rowValue >> 1;
});
}
class BoardPos{
constructor(x, y) {
this.x = x;
this.y = y;
}
isValid() {
return this.x >= 0 && this.x < 8 && this.y >= 0 && this.y < 8;
}
cell() {
return getCell(this.x, this.y);
}
plus(dx, dy) {
return new BoardPos(this.x + dx, this.y + dy);
}
}
class Level{
constructor(board, pieces, start, goal) {
this.board = board;
this.pieces = pieces.split('');
this.start = start;
this.goal = goal;
}
}
class GameState{
constructor() {
this.boardCells = [[],[],[],[],[],[],[],[]];
this.pieces = [];
this.moveNum = 0;
this.pastSpots = [];
this.goalPos = null;
this.moveOptions = [];
}
isNotVoid(pos) {
return pos.isValid() && this.boardCells[pos.x][pos.y];
}
loadLevel(level) {
// load board
for(let y=0; y<8; y++) {
let row = level.board[y];
for(let x=0; x<8; x++) {
this.boardCells[x][y] = row & 1;
row >>= 1;
}
}
// load goal
this.goalPos = level.goal;
// load pieces
this.pieces = level.pieces.slice(0);
// load start pos
this.pastSpots = [level.start];
this.moveNum = 0;
// update currnet position
this.calculateMoveOptions();
this.render();
}
isAtGoal() {
const current = this.pastSpots[this.moveNum];
return...