JSFiddle - React, Tailwind, and code Playground

by Danny Michaelis

CSS

table, th, td {
    border: 3px solid #ccc;
    border-spacing: 0;
}
table {
    border: 5px solid #969696;
    border-radius: 5px;
    width: 70vh;
    height: 70vh;
}
td > span {
    display: inline-block;
    width: 100%;
    height: 100%;
}
svg {
    display: inline-block;
}
td {
    box-sizing: border-box;
    width: 5%;
    height: 5%;
    padding: 0px;
}
.arrow_to_place_container {
    display: inline-block;
    border: 3px solid #aaa;
    width: 40px;
    height: 40px;
}
.win_position {
    background-color: #0000ff;
    border-color: #0000ff;
}

.arrow_to_place_container{
    display: inline-block;
}
.rotate_instructions{
    display: inline-block;
    font-family: "Franklin Gothic Medium", "Franklin Gothic", "ITC Franklin Gothic", Arial, sans-serif;
}
.rotation_container{
    margin: 5px;
}
.face{
    display: inline-block;
    width: 100px;
    height: 100px;
}
.selected_face{
    border: 5px solid red;
    border-radius: 5px;
}

@-webkit-keyframes player_1_pulse {
  0% { border-color: #ccc; -webkit-box-shadow: 0 0 9px #ccc; }
  50% { border-color: #ff1000; -webkit-box-shadow: 0 0 9px #cc5d62; }
  100% { border-color: #ccc; -webkit-box-shadow: 0 0 9px #ccc; }
}
@-webkit-keyframes player_2_pulse {
  0% { border-color: #ccc; -webkit-box-shadow: 0 0 9px #ccc; }
  50% { border-color: #14fe00; -webkit-box-shadow: 0 0 9px #cc5d62; }
  100% { border-color: #ccc; -webkit-box-shadow: 0 0 9px #ccc; }
}
@-webkit-keyframes player_3_pulse {
  0% { border-color: #ccc; -webkit-box-shadow: 0 0 9px #ccc; }
  50% { border-color: #b000ff; -webkit-box-shadow: 0 0 9px #cc5d62; }
  100% { border-color: #ccc; -webkit-box-shadow: 0 0 9px #ccc; }
}
@-webkit-keyframes player_4_pulse {
  0% { border-color: #ccc; -webkit-box-shadow: 0 0 9px #ccc; }
  50% { border-color: #ff7d2e; -webkit-box-shadow: 0 0 9px #cc5d62; }
  100% { border-color: #ccc; -webkit-box-shadow: 0 0 9px #ccc; }
}
@-webkit-keyframes player_5_pulse {
  0% { border-color: #ccc; -webkit-box-shadow: 0 0 9px #ccc;...

JavaScript

var UP_ANGLE = 0;
var RIGHT_ANGLE = 45;
var LEFT_ANGLE = 315;
var ROTATE_KEY = 82;

var NUMBER_OF_ROWS = 9;
var NUMBER_OF_COLUMNS = 9;
var NUMBER_OF_PLAYERS = 3;

/*function print(stuff) {
    console.log(stuff);
}*/
//arrow should technically be a part of Display, but it's just too cumbersome to put in with the rest of the code.
function arrow(direction) {
    return "<span class='" + direction + "'><svg 'version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 32 32' ><g transform='rotate(" + direction + " 15 15)'>	<path d='M27.414 12.586l-10-10c-0.781-0.781-2.047-0.781-2.828 0l-10 10c-0.781 0.781-0.781 2.047 0 2.828 0.781 0.781 2.047 0.781 2.828 0l6.586-6.586v19.172c0 1.105 0.895 2 2 2s2-0.895 2-2v-19.172l6.586 6.586c0.39 0.39 0.902 0.586 1.414 0.586s1.024-0.195 1.414-0.586c0.781-0.781 0.781-2.047 0-2.828z' fill='#000000' / ></g></svg></span>";
}
function game_rules_svg(){
    return "<div class='game_rules'><svg version='1.1' viewBox='0.0 0.0 1317.0 899.0' fill='none' stroke='none' stroke-linecap='square' stroke-miterlimit='10' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><clipPath id='p.0'><path d='m0 0l1317.0 0l0 899.0l-1317.0 0l0 -899.0z' clip-rule='nonzero'></path></clipPath><g clip-path='url(#p.0)'><path fill='#000000' fill-opacity='0.0' d='m0 0l1317.2179 0l0 899.4068l-1317.2179 0z' fill-rule='nonzero'></path><path fill='#ffffff' d='m28.598425 50.304462l83.90551 0l0 83.90552l-83.90551 0z' fill-rule='nonzero'></path><path stroke='#cccccc' stroke-width='4.0' stroke-linejoin='round' stroke-linecap='butt' d='m28.598425 50.304462l83.90551 0l0 83.90552l-83.90551 0z' fill-rule='nonzero'></path><path fill='#ffffff' d='m112.50394 50.304462l83.90552 0l0 83.90552l-83.90552 0z' fill-rule='nonzero'></path><path stroke='#cccccc' stroke-width='4.0' stroke-linejoin='round' stroke-linecap='butt' d='m112.50394 50.304462l83.90552 0l0 83.90552l-83.90552 0z' fill-rule='nonzero'></path><path...