JSFiddle - React, Tailwind, and code Playground

by Arnauld Chevallier

HTML

<p><label>Input <input id="str"></label><button id="btn">Play!</button></p>
<p>
<select id="list">
<option>-- test cases --</option>
<option>1. ""</option>
<option>2. "L"</option>
<option>3. "FFR"</option>
<option>4. "LFLR"</option>
<option>5. "BBBB"</option>
<option>6. "BRRFFFL"</option>
<option>7. "LFFRLFFFFRF"</option>
<option>8. "BRFRLRFRLFR"</option>
<option>9. "FFLRLFFLLLLFFBFLFLRRRLRRFRFLRLFFFLFLLLLFRRFBRLLLFBLFFLBFRLLR"</option>
</select>
</p>
<p>
<label><input name="speed" value="0" type="radio">Very slow</label>
<label><input name="speed" value="1" type="radio" checked="checked">Slow</label>
<label><input name="speed" value="2" type="radio">Medium</label>
<label><input name="speed" value="3" type="radio">Fast</label>
<label><input name="speed" value="4" type="radio">Very fast</label>
</p>
<p id="log" style="font-family:Courier">Dots: 0<br>Moves:</p>
<canvas id="c" width=335 height=371></canvas>

JavaScript

var ctx = document.getElementById("c").getContext("2d"),
    dx = [ 1, 0, -1,  0 ],
    dy = [ 0, 1,  0, -1 ],
    px, py,
    maze;

isFree = (x, y) => x < 0 || x > 27 || y < 0 || y > 30 || !(maze[y][x] & 1);
isJunction = (x, y) => [ 0, 1, 2, 3 ].reduce((p, c, n) => p + isFree(x + dx[n], y + dy[n]), 0) > 2;

function drawMaze() {
  ctx.fillStyle = '#000';
  ctx.fillRect(0, 0, 336, 372);

  maze.map((r, y) =>
    r.map((n, x) => {
      drawCell(x, y, n, true);
    })
  );
}

function drawCell(x, y, n, drawHero) {
  if(!(n & 5)) {
    ctx.fillStyle = '#222';
    ctx.fillRect(x * 12, y * 12, 11, 11);
  }
  switch(n) {
    case 1:
      ctx.fillStyle = '#24e';
      ctx.fillRect(x * 12, y * 12, 11, 11);
      break;
    case 2:
      ctx.fillStyle = '#ee0';
      ctx.fillRect(x * 12 + 4, y * 12 + 4, 3, 3);
      break;
  }
  if(!(n & 5) && isJunction(x, y)) {
    ctx.beginPath();
    ctx.strokeStyle = '#4e4';
    ctx.rect(x * 12 + 1.5, y * 12 + 1.5, 8, 8);
    ctx.stroke();
  }
  if(drawHero && x == px && y == py) {
    ctx.fillStyle = '#ec0';
    ctx.fillRect(x * 12, y * 12, 11, 11);
  }
}

function initMaze() {
  maze = [
    'XXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    'X............XX............X',
    'X.XXXX.XXXXX.XX.XXXXX.XXXX.X',
    'X.X//X.X///X.XX.X///X.X//X.X',
    'X.XXXX.XXXXX.XX.XXXXX.XXXX.X',
    'X..........................X',
    'X.XXXX.XX.XXXXXXXX.XX.XXXX.X',
    'X.XXXX.XX.XXXXXXXX.XX.XXXX.X',
    'X......XX....XX....XX......X',
    'XXXXXX.XXXXX XX XXXXX.XXXXXX',
    '/////X.XXXXX XX XXXXX.X/////',
    '/////X.XX          XX.X/////',
    '/////X.XX XXXXXXXX XX.X/////',
    'XXXXXX.XX X//////X XX.XXXXXX',
    '      .   X//////X   .      ',
    'XXXXXX.XX X//////X XX.XXXXXX',
    '/////X.XX XXXXXXXX XX.X/////',
    '/////X.XX          XX.X/////',
    '/////X.XX XXXXXXXX XX.X/////',
    'XXXXXX.XX XXXXXXXX XX.XXXXXX',
    'X............XX............X',
    'X.XXXX.XXXXX.XX.XXXXX.XXXX.X',
    'X.XXXX.XXXXX.XX.XXXXX.XXXX.X',
    'X...XX....... ...