<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tic Tac Toe</title>
<link rel="stylesheet" href="style.css">
<script>
window.console = window.console || function(t) {};
</script>
</head>
<body translate="no">
<div class="container">
<div class="game">
<div class="cell">
<input type="checkbox" data-cell="0" id="cell-1" />
<label for="cell-1"></label>
</div>
<div class="cell">
<input type="checkbox" data-cell="1" id="cell-2" />
<label for="cell-2"></label>
</div>
<div class="cell">
<input type="checkbox" data-cell="2" id="cell-3" />
<label for="cell-3"></label>
</div>
<div class="cell">
<input type="checkbox" data-cell="3" id="cell-4" />
<label for="cell-4"></label>
</div>
<div class="cell">
<input type="checkbox" data-cell="4" id="cell-5" />
<label for="cell-5"></label>
</div>
<div class="cell">
<input type="checkbox" data-cell="5" id="cell-6" />
<label for="cell-6"></label>
</div>
<div class="cell">
<input type="checkbox" data-cell="6" id="cell-7" />
<label for="cell-7"></label>
</div>
<div class="cell">
<input type="checkbox" data-cell="7" id="cell-8" />
<label for="cell-8"></label>
</div>
<div class="cell">
<input type="checkbox" data-cell="8" id="cell-9" />
<label for="cell-9"></label>
</div>
</div>
</div>
<div class="modal">
<div class="mod-container">
<div class="mod-header">
TicTacToe
</div>
<div class="mod-body">
Let's play
</div>
<div class="mod-footer">
<div class="mark-switch">
Choose your mark:
<div class="mark">
<input type="radio" value="tic" name="mark-switch" id="mark-x" checked />
<label id="lbl-x" class="btn" for="mark-x">✕</label>
</div>
<div class="mark">
<input type="radio" value="tac" name="mark-switch" id="mark-o" />
<label id="lbl-o" class="btn" for="mark-o">⚪</label>
</div>
</div>
<div class="play-order">
<div class="btn" id="btn-first">Start First</div>
<div class="btn" id="btn-second">Start Second</div>
</div>
</div>
</div>
</div>
<script src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script id="rendered-js" src="script.js"></script>
</body>
</html>
*,
*:before,
*:after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #eceff1;
font-family: Roboto, sans;
}
.container {
width: 100%;
}
.game {
width: 450px;
margin: 100px auto;
display: flex;
flex-wrap: wrap;
font-family: monospace;
}
.cell {
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.cell > label {
position: relative;
top: 0;
left: 0;
width: 140px;
height: 140px;
background-color: #455a64;
margin: 5px;
border: 10px solid #546e7a;
cursor: pointer;
transform-style: preserve-3d;
transition: all 350ms ease;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
}
.cell > label:hover {
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
}
.cell > input[type="checkbox"] {
display: none;
}
.cell > input[type="checkbox"]:checked ~ label {
transform: rotateY(180deg);
}
.cell > label:after {
content: "";
position: absolute;
top: -10px;
left: -10px;
width: 140px;
height: 140px;
transform: rotateY(180deg);
border: 10px solid transparent;
font-size: 80px;
line-height: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: -1;
transition: border-color, color 250ms ease;
}
.cell.tic > label:after {
content: "\2715";
border-color: #66bb6a;
color: #66bb6a;
}
.cell.tac > label:after {
content: "\26AA";
border-color: #81d4fa;
color: #81d4fa;
}
.win-line > label:after {
border-color: #ffab91 !important;
color: #ffab91 !important;
}
.modal {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: rgba(38, 50, 56, 0.7);
display: flex;
justify-content: center;
align-items: center;
transition: top 350ms ease;
}
.mod-container {
width: 60%;
max-width: 800px;
min-width: 600px;
background-color: #546e7a;
color: #fff;
display: flex;
flex-direction: column;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
}
.mod-header {
width: 100%;
background-color: #455a64;
font-size: 2em;
padding: 8px;
text-align: center;
}
.mod-body {
width: 100%;
padding: 20px;
text-align: center;
font-size: 1.6em;
}
.mod-footer {
min-height: 50px;
background-color: #455a64;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
}
.mark-switch {
display: flex;
margin-left: 5px;
}
.mark > label {
background-color: transparent;
}
.mark > input[type="radio"] {
display: none;
}
.mark > input[type="radio"]:checked ~ label {
border: 2px solid rgba(236, 239, 241, 0.7);
padding: 4px 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
.play-order {
display: flex;
}
.btn {
font-size: 1.2em;
background-color: #546e7a;
padding: 6px 10px;
margin-left: 4px;
cursor: pointer;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
.btn:hover {
background-color: #263238;
}
var modal;
var cells, playerClass, cpuClass, grid;
var lines = ["012", "345", "678", "036", "147", "258", "048", "246"];
var pw = ["0pp", "p0p", "pp0"];
var cw = ["0cc", "c0c", "cc0"];
var corners = [0, 2, 6, 8];
var sides = [1, 3, 5, 7];
var winObj = {
win: false,
player: "",
line: 0 };
$(document).ready(function () {
modal = new Modal();
cells = $(".cell>input:checkbox");
cells.click(function (e) {
playerMove(e.target);
});
$("#btn-first").click(function () {
init(false);
});
$("#btn-second").click(function () {
init(true);
});
});
function init(flag) {
winObj.win = false;
cells.each(function (c, e) {
e.checked = false;
e.disabled = false;
$(e).parent().removeClass("win-line tic tac");
});
grid = [0, 0, 0, 0, 0, 0, 0, 0, 0];
playerClass = $("input:radio[name ='mark-switch']:checked").val();
cpuClass = "tictac".replace(playerClass, "");
console.log(playerClass, cpuClass);
modal.hide();
if (flag) {
delay(myMove);
}
}
function delay(fnc, arg) {
window.setTimeout(fnc, 500, arg);
}
function playerMove(cell) {
cells.each(function (c, e) {
e.disabled = true;
});
var cId = $(cell).data("cell");
$(cell).parent().addClass(playerClass);
grid[cId] = "p";
delay(gameTest, true);
}
function myMove() {
//can we win
var move = canWin(cw);
if (move !== false) {
makeMove(move);
return;
}
//can player win - block him
move = canWin(pw);
if (move !== false) {
makeMove(move);
return;
}
//center cell
if (grid[4] === 0) {
makeMove(4);
return;
}
//try corners
move = randomEmptyCell(corners);
if (move !== false) {
makeMove(move);
return;
}
//try sides
move = randomEmptyCell(sides);
if (move !== false) {
makeMove(move);
return;
}
}
function makeMove(cell) {
cells[cell].checked = true;
$(cells[cell]).parent().addClass(cpuClass);
$(cells[cell]).disabled = true;
grid[cell] = "c";
gameTest(false);
}
function randomEmptyCell(range) {
var empty = range.filter(function (v) {
return grid[v] === 0;
});
if (empty.length > 0) {
return empty[Math.floor(Math.random() * empty.length)];
} else {
return false;
}
}
function canWin(wm) {
//var wm=["cc0","c0c","0cc"];
var m = lines.reduce(function (p, l, i) {
var a = l.split("").map(function (c) {
return grid[c];
}).join("");
var b = wm.indexOf(a);
if (b === -1) {
return p || false;
} else {
return p || l.charAt(b);
}
}, false);
return m;
}
function gameTest(isPlayer) {
if (isWin()) {
gameWon();
} else if (isEnd()) {
gameTie();
} else {
if (isPlayer) {
myMove();
} else {
cells.each(function (i, e) {
if (!e.checked) {
e.disabled = false;
}
});
}
}
}
function gameWon() {
lines[winObj.line].split("").forEach(function (v) {
$(cells[v]).parent().addClass("win-line");
});
if (winObj.player === "ppp") {
modal.message("You WON !!!");
} else if (winObj.player === "ccc") {
modal.message("You LOSE :-(");
}
delay(modal.show);
}
function gameTie() {
modal.message("It's TIE");
delay(modal.show);
}
function isWin() {
var res = lines.reduce(function (p, c, i) {
var lineRes = c.split("").map(function (a) {
return grid[a];
}).join("");
if (lineRes === "ppp" || lineRes === "ccc") {
winObj.line = i;
winObj.player = lineRes;
winObj.win = true;
}
return p || winObj.win;
}, false);
return res;
}
function isEnd() {
return grid.filter(function (a) {
return a != 0;
}).length === 9;
}
var Modal = function () {
var self = this;
this.el = document.querySelector(".modal");
var body = this.el.querySelector(".mod-body");
this.el.onclick = function () {
//self.hide();
};
this.show = function () {
self.el.style.top = 0;
};
this.hide = function () {
self.el.style.top = "-100%";
};
this.message = function (msg) {
body.innerHTML = msg;
};
};
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.