JSFiddle - React, Tailwind, and code Playground

by Ivan Mishchenko

HTML

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<!-- Static navbar -->
<nav class="navbar navbar-default navbar-static-top" role="navigation">
    <div class="container-fluid">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand _actionMain" href="#">Reversi</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="#newGame" class="_actionNew">New Game</a></li>
                <li><a href="#rules" class="_actionRules">Rules</a></li>
            </ul>
        </div><!--/.nav-collapse -->
    </div>
</nav>

<div class="container" id="_mainContainer">
    <div id="_main">
        <div class="row">
            <div class="col-xs-4 col-sm-3"><img src="http://premium-api.com/jscourse/reversi_logo.jpg" alt="Reversi" class="img-thumbnail"/></div>
            <div class="col-xs-8 col-sm-9">
                <h1>Reversi</h1>
                <p>This is a strategy board game for two players, played on an 8×8 uncheckered board.</p>
                <a class="btn btn-primary _actionNew" href="#newGame">Start new game</a>
            </div>
        </div>    
    </div>
    
    <div id="_new">
        <h1>Start new game</h1>
        <form role="form" id="unForm">
            <div class="form-group">
                <label for="playerName">You name</label>
                <input type="text" class="form-control" id="playerName" placeholder="Enter your...

CSS

<style type="text/css">
.navbar-static-top {
    margin-bottom: 19px;
}
.board {
    border: 1px solid green;
    width: 362px;
    height: 362px;
}
.cell, .colName, .rowName, .corner {
    float: left;
}
.cell, .colName {
    width: 40px;
}
.rowName, .corner {
    width: 20px;
}
.cell, .rowName {
    height: 40px;
}
.colName, .corner {
    height: 20px;	
}
.cell {
    background-color: rgb(55, 147, 45);
}
.cell.light{
    background-color: rgb(163, 224, 156);
}
.cell.blackDisk {
    background-image: url(http://premium-api.com/jscourse/sprite_disks.png);
    background-position: 0px 0px;
}
.cell.blackDisk3 {
    background-image: url(http://premium-api.com/jscourse/sprite_disks.png);
    background-position: 0px -80px;
}
.cell.blackDisk2 {
    background-image: url(http://premium-api.com/jscourse/sprite_disks.png);
    background-position: 0px -120px;
}
.cell.blackDisk1 {
    background-image: url(http://premium-api.com/jscourse/sprite_disks.png);
    background-position: 0px -160px;
}
.cell.whiteDisk {
    background-image: url(http://premium-api.com/jscourse/sprite_disks.png);
    background-position: 0px -40px;
}
.cell.whiteDisk1 {
    background-image: url(http://premium-api.com/jscourse/sprite_disks.png);
    background-position: 0px -200px;
}
.cell.whiteDisk2 {
    background-image: url(http://premium-api.com/jscourse/sprite_disks.png);
    background-position: 0px -240px;
}
.cell.whiteDisk3 {
    background-image: url(http://premium-api.com/jscourse/sprite_disks.png);
    background-position: 0px -280px;
}
.colName {
    text-align: center;
}
.rowName {
    text-align: center;
}
.rowLabel {
    position: relative;
    top: 50%;
    transform: translateY(-50%);
}
div#_mainContainer > div {
   display: none; 
}
</style>

JavaScript

// global namespace
var Reversi = Reversi || {
    EMPTY_TYPE: 'e',
    BLACK_TYPE: 'b',
    WHITE_TYPE: 'w',
    BOARD_SIZE: 8,
    COMPUTER_NAME: 'JavaScript'
};

Reversi.Game = {
    blackPlayer: "John",
    whitePlayer: "James",
    isMoveBlack: true,
    userIsBlack: null,
    start: function(userName) {
        // draw board start position
        Reversi.Board.init();
        Reversi.Board.drawBoard();
        Reversi.Board.drawAllDisks();
        // choose who plays by black
        if ( Math.random() < 0.5 ) {
            this.userIsBlack = true;
            this.blackPlayer = userName;
            this.whitePlayer = Reversi.COMPUTER_NAME;
        } else {
            this.userIsBlack = false;
            this.blackPlayer = Reversi.COMPUTER_NAME;
            this.whitePlayer = userName;
        }
        console.log('Is black: ' + this.userIsBlack);
        this.updateIndicators();
        this.completeMove();
    },
    isUserMove: function() {
        return (this.isMoveBlack === this.userIsBlack);
    },
    completeMove: function() {
        // check if turn of computer
        if ( !this.isUserMove() )  {
            setTimeout(Reversi.Game.makeAIMove, 3000);
        }
    },
    makeAIMove: function() {
        var o = [];
        var cellNum = Reversi.BOARD_SIZE*Reversi.BOARD_SIZE;
        for (var i=0; i<cellNum; i++) {
            o.push(i);
        }
        // shuffle array
        for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
        // find correct move
        for (var i=0; i<cellNum; i++) {
            var cell = new Reversi.Cell(o[i], Reversi.EMPTY_TYPE);
            if ( Reversi.Game.moveCallback(cell.col, cell.row) ) {
                break;
            }
        }
    },
    getIndexesColRow: function(index) {
        return {
            iCol: index % Reversi.BOARD_SIZE,
            iRow: Math.floor(index / Reversi.BOARD_SIZE)
        }
    },
    findDiskToFlip:...