JSFiddle - React, Tailwind, and code Playground
HTML
<body>
<div class="game">
<!-- <h1 id="title"> Tic-Tac-Toe </h1> -->
<div id="grid">
<table>
<tr id="rowOne">
<td class="button" id="b1"></td>
<td class="button" id="b2"></td>
<td class="button" id="b3"></td>
</tr>
<tr id="rowTwo">
<td class="button" id="b4"></td>
<td class="button" id="b5"></td>
<td class="button" id="b6"></td>
</tr>
<tr id="rowThree">
<td class="button" id="b7"></td>
<td class="button" id="b8"></td>
<td class="button" id="b9"></td>
</tr>
</table>
</div>
</div>
</body>
CSS
#title {
font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
font-size: 27.7px;
}
#grid {
width: 175px;
height: 175px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin-top: auto;
margin-left: auto;
margin-right: auto;
margin-bottom: auto;
}
.button {
width: 50px;
height: 50px;
border: 2px solid #000000;
font-family: Arial, Helvetica, sans-serif;
font-size: 30px;
text-align: center;
}
.button:hover {
background-color: #f0f0f0;
cursor: pointer;
}
.button:active {
background-color: #dddddd;
}
.x {
color: #ffffff;
background-color: #42a1f4;
content: "X";
}
.x:hover {
background-color: #42a1f4;
cursor: default;
}
.x:after {
content: "X";
}
.o {
color: #ffffff;
background-color: #b73a43;
}
.o:hover {
background-color: #b73a43;
cursor: default;
}
.o:after {
content: "O";
}
JavaScript
player = true; //true = human, false = ai
toggleOnce = true; //default value, used in circumventing a pattern bug
_gameEnded = 0; //default to game running
result = 2; //default to placeholder value
count = 0; //default count of moves
maxMoves = 9; //amount of max moves used for draw check
$(".button").bind("click", function() { //add x or o to button clicked
if ($(this).hasClass("x") || $(this).hasClass("o") || _gameEnded)
return; //dont do anything if a button has x or o already or the game has ended
$(this).toggleClass("x"); //add x or o depending on current player
player = !player; //switch player
count++; //increase move count
checkGameEnd(); //check if game ended
computerMove(); //let the ai make a move
});
function computerMove() {
if (_gameEnded == 0 && !player) { //execute only when game is running (to prevent adding after win/loss alert)
var gameStatus = getGameStatus();
var field = getNextMove(gameStatus);
var btnId = "#b" + field;
$(btnId).toggleClass("o"); //add o the the randomly chosen button
player = !player; //switch player
count++; //increase move count
checkGameEnd(); //check if game ended
}
}
function getNextMove(gameStatus) {
if ((!$("#b5").hasClass("x")) && (!$(".button").hasClass("o"))){ //if the first x was not set in the middle,
$("#b5").toggleClass("o"); //set o in the middle (since it is the most optimal starting point)
return;
}
/*if (toggleOnce == true && ($("#b5").hasClass("x")) && ($("#b9").hasClass("x")) && (!$("#b7").hasClass("o"))) {
$("#b7").toggleClass("o"); //prevents a bug that happened when setting x at b5 b9 b3
toggleOnce = false;
return;
}*/
var bestZ, bestS; //values to assign best slot to later on
var bestValue = -2; //placeholder value to be replaced with result value
for (var z = 0; z < 3; z++) { //loop for row
for (var s = 0; s < 3; s++) { //loop for column
if (gameStatus[z][s]) //if current slot has an x or o,
continue;...