Skip to content

Instantly share code, notes, and snippets.

@paulinafischer
Created January 16, 2020 09:42
Show Gist options
  • Save paulinafischer/13d009b26621f7aa82e3093821ea895a to your computer and use it in GitHub Desktop.
Save paulinafischer/13d009b26621f7aa82e3093821ea895a to your computer and use it in GitHub Desktop.
Tic Tac Toe Game
<div class="container-fluid text-center" id="container">
<div class="row">
<div class="col-md-12">
<div class="container text-center">
<br>
<button type="button" class="btn btn-success btn-lg animated fadeIn" data-toggle="modal" data-target="#myModal"><span class="glyphicon glyphicon-play" aria-hidden="true"></span></button>
<div class="modal fade animated swing" id="myModal" role="dialog">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Selec your simbol!</h4>
</div>
<div class="modal-body">
<div class = "selectSym">
<button class="btn btn-danger animated rotateIn" onClick="selectSym('X')"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</button>
<button class="btn btn-danger animated bounce" onClick="selectSym('O')"><i class="fa fa-circle-o" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
</div>
<br>
<button class="btn btn-warning" onClick="startGame()"><span class="glyphicon glyphicon-repeat" aria-hidden="true"></span></button></button>
</div>
</div>
<br><br><br><br>
<div class="container-fluid">
<div class="row">
<div class="col-md-2"><div class="jumotron"><h1 id="ti"><strong>TIC TAC TOE</strong></h1></div></div><div class="col-md-2"></div>
<div class="col-md-4">
<table class="table animated fadeIn">
<tr class="default">
<td class="cell animated infinite pulse" id="0"></td>
<td class="cell animated infinite pulse" id="1"></td>
<td class="cell animated infinite pulse" id="2"></td>
</tr>
<tr class="default">
<td class="cell animated infinite pulse" id="3"></td>
<td class="cell animated infinite pulse" id="4"></td>
<td class="cell animated infinite pulse" id="5"></td>
</tr>
<tr class="default">
<td class="cell animated infinite pulse" id="6"></td>
<td class="cell animated infinite pulse" id="7"></td>
<td class="cell animated infinite pulse" id="8"></td>
</tr>
</table>
<div class="endgame well well-lg animated rubberBand">
<div class="text"></div>
</div>
<div class="col-md-2"></div>
<div class="col-md-2"></div>
</div>
<div class="row">
<div class="col-md-12 strong animated fadeIn"> <br><br><br> <p id ="yo">Created by: Paulina Fischer</p><br><p>Library from
<a href="https://www.youtube.com/watch?v=P2TcQ3h0ipQ&t=2699s" target="_blank">freeCodeCamp</a></p>
</div>
</div>
</div>
let origBoard;
let huPlayer ='O';
let aiPlayer = 'X';
const winCombos =[
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 4, 8],
[6, 4, 2],
[2, 5, 8],
[1, 4, 7],
[0, 3, 6]
];
const cells = document.querySelectorAll('.cell');
startGame();
function selectSym(sym){
huPlayer = sym;
aiPlayer = sym==='O' ? 'X' :'O';
origBoard = Array.from(Array(9).keys());
for (let i = 0; i < cells.length; i++) {
cells[i].addEventListener('click', turnClick, false);
}
if (aiPlayer === 'X') {
turn(bestSpot(),aiPlayer);
}
document.querySelector('.selectSym').style.display = "none";
}
function startGame() {
document.querySelector('.endgame').style.display = "none";
document.querySelector('.endgame .text').innerText ="";
document.querySelector('.selectSym').style.display = "block";
for (let i = 0; i < cells.length; i++) {
cells[i].innerText = '';
cells[i].style.removeProperty('background-color');
}
}
function turnClick(square) {
if (typeof origBoard[square.target.id] ==='number') {
turn(square.target.id, huPlayer);
if (!checkWin(origBoard, huPlayer) && !checkTie())
turn(bestSpot(), aiPlayer);
}
}
function turn(squareId, player) {
origBoard[squareId] = player;
document.getElementById(squareId).innerHTML = player;
let gameWon = checkWin(origBoard, player);
if (gameWon) gameOver(gameWon);
checkTie();
}
function checkWin(board, player) {
let plays = board.reduce((a, e, i) => (e === player) ? a.concat(i) : a, []);
let gameWon = null;
for (let [index, win] of winCombos.entries()) {
if (win.every(elem => plays.indexOf(elem) > -1)) {
gameWon = {index: index, player: player};
break;
}
}
return gameWon;
}
function gameOver(gameWon){
for (let index of winCombos[gameWon.index]) {
document.getElementById(index).style.backgroundColor =
gameWon.player === huPlayer ? "#00CC89" : "#6CDEB9";
}
for (let i=0; i < cells.length; i++) {
cells[i].removeEventListener('click', turnClick, false);
}
declareWinner(gameWon.player === huPlayer ? "You win!" : "You lose");
}
function declareWinner(who) {
document.querySelector(".endgame").style.display = "block";
document.querySelector(".endgame .text").innerText = who;
}
function emptySquares() {
return origBoard.filter((elm, i) => i===elm);
}
function bestSpot(){
return minimax(origBoard, aiPlayer).index;
}
function checkTie() {
if (emptySquares().length === 0){
for (cell of cells) {
cell.style.backgroundColor = "#FF5600";
cell.removeEventListener('click',turnClick, false);
}
declareWinner("Tie game");
return true;
}
return false;
}
function minimax(newBoard, player) {
var availSpots = emptySquares(newBoard);
if (checkWin(newBoard, huPlayer)) {
return {score: -10};
} else if (checkWin(newBoard, aiPlayer)) {
return {score: 10};
} else if (availSpots.length === 0) {
return {score: 0};
}
var moves = [];
for (let i = 0; i < availSpots.length; i ++) {
var move = {};
move.index = newBoard[availSpots[i]];
newBoard[availSpots[i]] = player;
if (player === aiPlayer)
move.score = minimax(newBoard, huPlayer).score;
else
move.score = minimax(newBoard, aiPlayer).score;
newBoard[availSpots[i]] = move.index;
if ((player === aiPlayer && move.score === 10) || (player === huPlayer && move.score === -10))
return move;
else
moves.push(move);
}
let bestMove, bestScore;
if (player === aiPlayer) {
bestScore = -1000;
for(let i = 0; i < moves.length; i++) {
if (moves[i].score > bestScore) {
bestScore = moves[i].score;
bestMove = i;
}
}
} else {
bestScore = 1000;
for(let i = 0; i < moves.length; i++) {
if (moves[i].score < bestScore) {
bestScore = moves[i].score;
bestMove = i;
}
}
}
return moves[bestMove];
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
#container{
background:#EE004C;
-webkit-animation-name:bgcolor;
-webkit-animation-duration:10s;
-webkit-animation-timing-function:linear;
-webkit-animation-delay:0s;
-webkit-animation-iteration-count:infinite;
-webkit-animation-direction:alternate;
-webkit-animation-play-state:running;
animation-name:bgcolor;
animation-duration:10s;
animation-timing-function:linear;
animation-delay:0s;
animation-iteration-count:infinite;
animation-direction:alternate;
animation-play-state:running;
}
@-webkit-keyframes bgcolor
{
0% {background: #EE004C; left:0px; top:0px;}
25% {background: #B2385F; left:0px; top:0px;}
50% {background: #9b59b6; left:0px; top:0px;}
75% {background: #C96E40; left:0px; top:0px;}
100% {background: #EE004C; left:0px; top:0px;}
}
@keyframes bgcolor
{
0% {background: #EE004C; left:0px; top:0px;}
25% {background: #B2385F; left:0px; top:0px;}
50% {background: #9b59b6; left:0px; top:0px;}
75% {background: #C96E40; left:0px; top:0px;}
100% {background: #EE004C; left:0px; top:0px;}
}
td {
border: 5px solid #6D0023;
width:100px;
height:100px;
text-align:center;
vertical-align:middle;
font-family: 'Finger Paint', cursive;
cursor: pointer;
font-size:50px;
color:#F4779F;
}
table tr:first-child td {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child {
border-left: 0;
}
table tr td:last-child {
border-right: 0;
}
.well{
position:relative;
top:-250px;
font-size:80px;
font-family: 'Finger Paint', cursive;
background-color:#B2F577;
color:#346E00;
border:none;
}
.jumbotron{
width: 100%;
margin:0px auto;
}
h1{
letter-spacing:5px;
font-size:65px;
color:#71EF00;
font-family: 'Finger Paint', cursive;
}
h4{font-family: 'Finger Paint', cursive;
color:#FFA97D;
}
.modal-content, .modal-body, .modal-header, .modal-title, .modal-footer {background-color:#FF5600;
border:none;}
#yo{color:whitesmoke;
font-family: 'Libre Franklin', sans-serif;}
.btn{
width:100px;
height:40px;
color:#005237;
background-color:#00CC89;
border: #005237;}
.btn-danger{
background-color:#7B2900;
color:#FFA97D;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment