This post contains a total of 24+ Hand-Picked JavaScript Tic Tac Toe Examples with Source Code. All the Tic Tac Toe programs are made using JavaScript and uses little bit of CSS for Styling.
You can use the source code of these examples for educational use with credits to the original owner.
Related Posts
Click a Code to Copy it.
1. By Augustas Macijauskas
Made by Augustas Macijauskas. A complete Tic Tac Toe game made using JavaScript. It has three modes you can play, these are Normal, Magic Board and Play with AI. Normal mode is for two players, magic board is for three players and the Play with AI is for playing with Artificial Intelligence aka Robot, this mode has three sub-modes, beginner, amateur and master. ( Source )
<!DOCTYPE html>
<!--
* Welcome to my tic tac toe game!!!
* Special thanks to Baptiste E. Prunier
for inspiration and help while coding
-->
<!--
# Title : Magic Tic Tac Toe
# Version : 3.0
# AI : 3 difficulties available: Beginner, Amateur and Master
# Magic board : A game mode for 3 players: X, O and M
# Last update : 01 August 2017
# Author : Augustas Macijauskas
# Language : HTML, CSS, Javascript
# Dependancy : Lodash and jQuery scripts added at the end
-->
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tic Tac Toe game!</title>
<link href="https://fonts.googleapis.com/css?family=Amatic+SC" rel="stylesheet">
<link rel="stylesheet" href="tictactoe.css">
</head>
<body>
<style>
/* CSS GRID IS AWESOME, CHECK OUT! */
@import url('https://fonts.googleapis.com/css?family=Amatic+SC');
body {
background-color: white;
}
/* Creating the layout for mobiles first*/
.grid_main {
display: grid;
max-width: 296px;
margin: auto;
margin-top: 10%;
grid-template-columns: 1fr;
grid-template-rows: auto auto auto auto;
grid-template-areas:
"header"
"normal"
"magic"
"AI";
background-color: white;
}
.grid_main .header {
grid-area: header;
justify-self: center;
}
.grid_main h1 {
margin: 0 auto;
margin-bottom: 2.5%;
border-bottom: 1px solid black;
text-align: center;
padding: 20px 0 20px 0;
font-family: 'Amatic SC', cursive;
color: black;
font-size: 30pt;
font-weight: 700;
}
.grid_main .normal {
grid-area: normal;
justify-self: center;
}
.grid_main .magicBoard {
grid-area: magic;
justify-self: center;
}
.grid_main .vsAI {
grid-area: AI;
justify-self: center;
}
.grid_main a {
text-decoration: none;
font-family: 'Amatic SC', cursive;
color: black;
margin: 2.5% auto;
font-size: 25pt;
font-weight: 400;
}
.grid_main a:hover {
font-weight: 700;
}
.grid_AI_setup {
display: none;
max-width: 296px;
margin: auto;
margin-top: 10%;
grid-template-columns: 1fr;
grid-template-rows: auto auto auto auto;
grid-template-areas:
"header"
"beginner"
"amateur"
"master";
background-color: white;
}
.grid_AI_setup .header {
grid-area: header;
justify-self: center;
}
.grid_AI_setup h1 {
margin: 0 auto;
margin-bottom: 2.5%;
border-bottom: 1px solid black;
text-align: center;
padding: 20px 0 20px 0;
font-family: 'Amatic SC', cursive;
color: black;
font-size: 30pt;
font-weight: 700;
}
.grid_AI_setup .beginner {
grid-area: beginner;
justify-self: center;
}
.grid_AI_setup .amateur {
grid-area: amateur;
justify-self: center;
}
.grid_AI_setup .master {
grid-area: master;
justify-self: center;
}
.grid_AI_setup a {
text-decoration: none;
font-family: 'Amatic SC', cursive;
color: black;
margin: 2.5% auto;
font-size: 25pt;
font-weight: 400;
}
.grid_AI_setup a:hover {
font-weight: 700;
}
.grid_normal {
max-width: 296px;
margin: auto;
display: none;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto auto auto;
grid-template-areas:
"heading heading"
"message message"
"table table"
"back startOver";
background-color: white;
}
.grid_AI {
max-width: 296px;
margin: auto;
display: none;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto auto auto;
grid-template-areas:
"heading heading"
"message message"
"table table"
"back startOver";
background-color: white;
}
.grid_magic {
max-width: 296px;
margin: auto;
display: none;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto auto auto;
grid-template-areas:
"heading heading"
"message message"
"table table"
"back startOver";
background-color: white;
}
.grid_normal .heading {
grid-area: heading;
justify-self: center;
}
.grid_AI .heading {
grid-area: heading;
justify-self: center;
}
.grid_magic .heading {
grid-area: heading;
justify-self: center;
}
.grid_normal .message {
grid-area: message;
margin-left: 1.5%;
}
.grid_AI .message {
grid-area: message;
margin-left: 1.5%;
}
.grid_magic .message {
grid-area: message;
margin-left: 2.5%;
}
.grid_normal .table {
grid-area: table;
justify-self: center;
}
.grid_AI .table {
grid-area: table;
justify-self: center;
}
.grid_magic .table {
grid-area: table;
justify-self: center;
}
.grid_normal .back {
grid-area: back;
justify-self: left;
margin-left: 2.5%;
}
.grid_AI .back {
grid-area: back;
justify-self: left;
margin-left: 2.5%;
}
.grid_magic .back {
grid-area: back;
justify-self: left;
margin-left: 3.5%;
}
.grid_normal .startOver {
grid-area: startOver;
justify-self: right;
margin-right: 2.5%;
}
.grid_AI .startOver {
grid-area: startOver;
justify-self: right;
margin-right: 2.5%;
}
.grid_magic .startOver {
grid-area: startOver;
justify-self: right;
margin-right: 3.5%;
}
.grid_normal .square {
width: 90px;
height: 90px;
font-family: 'Comfortaa', serif;
font-size: 40pt;
text-align: center;
}
.grid_AI .square {
width: 90px;
height: 90px;
font-family: 'Comfortaa', serif;
font-size: 40pt;
text-align: center;
}
.grid_normal .square {
width: 90px;
height: 90px;
font-family: 'Comfortaa', serif;
font-size: 40pt;
text-align: center;
}
.grid_magic .square {
width: 65px;
height: 65px;
font-family: 'Comfortaa', serif;
font-size: 30pt;
text-align: center;
}
/* Styling elements */
.grid_normal h1 {
margin: 0 auto;
margin-bottom: 2.5%;
text-align: center;
padding: 20px 0 20px 0;
font-family: 'Amatic SC', cursive;
color: black;
font-size: 20pt;
font-weight: 400;
}
.grid_normal h1 span {
font-weight: 700;
}
.grid_normal h2{
font-family: 'Amatic SC', cursive;
color: black;
font-size: 20pt;
font-weight: 400;
margin-top: 0;
margin-bottom: 0;
}
.grid_normal a {
text-decoration: none;
font-family: 'Amatic SC', cursive;
color: black;
margin-top: 5%;
font-size: 20pt;
}
.grid_normal a:hover {
text-decoration: underline;
}
.grid_AI h1 {
margin: 0 auto;
margin-bottom: 2.5%;
text-align: center;
padding: 20px 0 20px 0;
font-family: 'Amatic SC', cursive;
color: black;
font-size: 20pt;
font-weight: 400;
}
.grid_AI h1 span {
font-weight: 700;
}
.grid_AI h2{
font-family: 'Amatic SC', cursive;
color: black;
font-size: 20pt;
font-weight: 400;
margin-top: 0;
margin-bottom: 0;
}
.grid_AI a {
text-decoration: none;
font-family: 'Amatic SC', cursive;
color: black;
margin-top: 5%;
font-size: 20pt;
}
.grid_AI a:hover {
text-decoration: underline;
}
.grid_magic h1 {
margin: 0 auto;
margin-bottom: 2.5%;
text-align: center;
padding: 20px 0 20px 0;
font-family: 'Amatic SC', cursive;
color: black;
font-size: 18pt;
font-weight: 400;
}
.grid_magic h1 span {
font-weight: 700;
}
.grid_magic h2{
font-family: 'Amatic SC', cursive;
color: black;
font-size: 20pt;
font-weight: 400;
margin-top: 0;
margin-bottom: 0;
}
.grid_magic a {
text-decoration: none;
font-family: 'Amatic SC', cursive;
color: black;
margin-top: 5%;
font-size: 20pt;
}
.grid_magic a:hover {
text-decoration: underline;
}
</style>
<div class="grid_main" id="grid_main">
<h1 class="header">LET'S PLAY!</h1>
<a href="javascript: P1vsP2();" id="normal" class="normal">NORMAL</a>
<a href="javascript: magicBoard();" id="magicBoard" class="magicBoard">MAGIC BOARD</a>
<a href="javascript: selectDifficulty();" id="vsAI" class="vsAI">PLAY VS AI</a>
</div>
<div class="grid_AI_setup" id="grid_AI_setup">
<h1 class="header">SELECT DIFFICULTY</h1>
<a href="javascript: vsAInoob();" id="beginner" class="beginner">BEGINNER</a>
<a href="javascript: vsAImiddle();" id="amatuer" class="amateur">AMATEUR</a>
<a href="javascript: vsAI();" id="master" class="master">MASTER</a>
</div>
<div class="grid_normal" id="grid_normal">
<h1 class="heading"><span id="player1">Player1</span> vs <span id="player2">Player2</span></h1>
<h2 class="message" id="message"></h2>
<table class="table" border="1">
<tr>
<td class="square" id="tile1" onClick="update(this)"></td>
<td class="square" id="tile2" onClick="update(this)"></td>
<td class="square" id="tile3" onClick="update(this)"></td>
</tr>
<tr>
<td class="square" id="tile4" onClick="update(this)"></td>
<td class="square" id="tile5" onClick="update(this)"></td>
<td class="square" id="tile6" onClick="update(this)"></td>
</tr>
<tr>
<td class="square" id="tile7" onClick="update(this)"></td>
<td class="square" id="tile8" onClick="update(this)"></td>
<td class="square" id="tile9" onClick="update(this)"></td>
</tr>
</table>
<a href="javascript: back();" id="back" class="back">Back</a>
<a href="javascript: startGame();" id="start_over" class="startOver">Start over!</a>
</div>
<div class="grid_AI" id="grid_AI">
<h1 class="heading"><span id="player_name">Player1</span> vs <span>Computer</span></h1>
<h2 class="message" id="messageAI"></h2>
<table class="table" border="1">
<tr>
<td class="square" id="tileAI0-0" onClick="updateAI(this, 0, 0)"></td>
<td class="square" id="tileAI0-1" onClick="updateAI(this, 0, 1)"></td>
<td class="square" id="tileAI0-2" onClick="updateAI(this, 0, 2)"></td>
</tr>
<tr>
<td class="square" id="tileAI1-0" onClick="updateAI(this, 1, 0)"></td>
<td class="square" id="tileAI1-1" onClick="updateAI(this, 1, 1)"></td>
<td class="square" id="tileAI1-2" onClick="updateAI(this, 1, 2)"></td>
</tr>
<tr>
<td class="square" id="tileAI2-0" onClick="updateAI(this, 2, 0)"></td>
<td class="square" id="tileAI2-1" onClick="updateAI(this, 2, 1)"></td>
<td class="square" id="tileAI2-2" onClick="updateAI(this, 2, 2)"></td>
</tr>
</table>
<a href="javascript: backAI()" id="backAI" class="back">Back</a>
<a href="javascript: startGameAI();" id="start_overAI" class="startOver">Start over!</a>
</div>
<div class="grid_magic" id="grid_magic">
<h1 class="heading"><span id="magic1">Player1</span> vs <span id="magic2">Player2</span> vs <span id="magic3">Player3</span></h1>
<h2 class="message" id="magicMessage"></h2>
<table class="table" border="1">
<tr>
<td class="square" id="magictile1" onClick="updateMagic(this)"></td>
<td class="square" id="magictile2" onClick="updateMagic(this)"></td>
<td class="square" id="magictile3" onClick="updateMagic(this)"></td>
<td class="square" id="magictile4" onClick="updateMagic(this)"></td>
</tr>
<tr>
<td class="square" id="magictile5" onClick="updateMagic(this)"></td>
<td class="square" id="magictile6" onClick="updateMagic(this)"></td>
<td class="square" id="magictile7" onClick="updateMagic(this)"></td>
<td class="square" id="magictile8" onClick="updateMagic(this)"></td>
</tr>
<tr>
<td class="square" id="magictile9" onClick="updateMagic(this)"></td>
<td class="square" id="magictile10" onClick="updateMagic(this)"></td>
<td class="square" id="magictile11" onClick="updateMagic(this)"></td>
<td class="square" id="magictile12" onClick="updateMagic(this)"></td>
</tr>
<tr>
<td class="square" id="magictile13" onClick="updateMagic(this)"></td>
<td class="square" id="magictile14" onClick="updateMagic(this)"></td>
<td class="square" id="magictile15" onClick="updateMagic(this)"></td>
<td class="square" id="magictile16" onClick="updateMagic(this)"></td>
</tr>
</table>
<a href="javascript: backMagic();" id="back" class="back">Back</a>
<a href="javascript: magicStartGame();" id="start_over" class="startOver">Start over!</a>
</div>
<!-- <div class="grid_noob" id="grid_noob">
<h1 class="heading"><span id="player_name_noob"></span> vs <span>Computer</span></h1>
<h2 class="message" id="messageAInoob"></h2>
<table class="table" border="1">
<tr>
<td class="square" id="tileAI1" onClick="updateAI(this, 0)"></td>
<td class="square" id="tileAI2" onClick="updateAI(this, 1)"></td>
<td class="square" id="tileAI3" onClick="updateAI(this, 2)"></td>
</tr>
<tr>
<td class="square" id="tileAI4" onClick="updateAI(this, 3)"></td>
<td class="square" id="tileAI5" onClick="updateAI(this, 4)"></td>
<td class="square" id="tileAI6" onClick="updateAI(this, 5)"></td>
</tr>
<tr>
<td class="square" id="tileAI7" onClick="updateAI(this, 6)"></td>
<td class="square" id="tileAI8" onClick="updateAI(this, 7)"></td>
<td class="square" id="tileAI9" onClick="updateAI(this, 8)"></td>
</tr>
</table>
<a href="javascript: backAInoob();" id="backAInoob" class="back">Back</a>
<a href="javascript: startGameAInoob();" id="start_overAInoob" class="startOver">Start over!</a>
</div> -->
<script>
function P1vsP2(){
//Function to set up the game for Player1 vs Player2 mode
var nope = document.getElementById('grid_main');
var element = document.getElementById('grid_normal');
nope.style.display = "none";
element.style.display = "grid";
var name1 = "Player1";
var name2 = "Player2";
name1 = prompt("Enter first player's name: ");
name2 = prompt("Enter second player's name: ");
document.getElementById('player1').innerHTML = name1;
document.getElementById('player2').innerHTML = name2;
startGame();
}
function back(){
//Function to go back to the main screen when playing P1 vs P2 mode
var nope = document.getElementById('grid_main');
var element = document.getElementById('grid_normal');
nope.style.display = "grid";
element.style.display = "none";
}
function startGame(){
for(var i = 1; i <= 9; i++){
document.getElementById("tile" + i).innerText = "";
document.getElementById("tile" + i).style.color = "black";
}
document.turn = "X";
document.winner = null;
document.countTiles = 0;
setMessage(document.turn + " gets to start");
}
function update(square){
if(document.winner === true){
setMessage(document.turn + " already won");
}
else if(document.countTiles == 9){
setMessage("It's a draw");
}
else if(square.innerText == "X" || square.innerText == "O"){
setMessage("Pick an empty tile");
}else{
square.innerText = document.turn;
switchTurn(document.turn);
}
}
function switchTurn(turn){
//Function that switches turns
document.countTiles++;
if(checkForWinner(document.turn)){
setMessage("Congrats " + document.turn + " you won!");
}
else if (turn == "X"){
document.turn = "O";
if(document.countTiles == 9){
setMessage("It's a draw");
}
else{
setMessage(document.turn + "'s turn");
}
}
else{
document.turn = "X";
if(document.countTiles == 9){
setMessage("It's a draw");
}
else{
setMessage(document.turn + "'s turn");
}
}
}
function setMessage(msg){
//Function to set the message
document.getElementById('message').innerHTML = msg;
}
function returnBox(index){
//Function to return a selected tile
return document.getElementById("tile" + index).innerText;
}
function isRowFilled(tile1, tile2, tile3, move){
//Function to check if any row is filled
//At first, the value is false
var isFilled = false;
if(returnBox(tile1) == move && returnBox(tile2) == move && returnBox(tile3) == move){
isFilled = true;
document.getElementById("tile" + tile1).style.color = "red";
document.getElementById("tile" + tile2).style.color = "red";
document.getElementById("tile" + tile3).style.color = "red";
}
return isFilled;
}
function checkForWinner(move){
//Function to check if there is a winner
var isThereAWinner = false;
if(isRowFilled (1, 2, 3, move) ||
isRowFilled (4, 5, 6, move) ||
isRowFilled (7, 8, 9, move) ||
isRowFilled (1, 4, 7, move) ||
isRowFilled (2, 5, 8, move) ||
isRowFilled (3, 6, 9, move) ||
isRowFilled (1, 5, 9, move) ||
isRowFilled (3, 5, 7, move)
){
isThereAWinner = true;
document.winner = true;
}
return isThereAWinner;
}
//Code for the AI game mode
function selectDifficulty() {
//Function so set up the game for P1 vs AI mode
var nope = document.getElementById('grid_main');
var element = document.getElementById('grid_AI_setup');
nope.style.display = "none";
element.style.display = "grid";
}
document.difficulty; //Defines difficulty;
function vsAI(){
//Function so set up the game for P1 vs AI mode
alert("Whoever goes first is selected randomly \n\nMaster level AI is impossible to beat \n\nIMPORTANT NOTE: If computers gets to start, give him some time to work out the move");
var nope = document.getElementById('grid_AI_setup');
var element = document.getElementById('grid_AI');
nope.style.display = "none";
element.style.display = "grid";
document.playerName = "Player1";
document.playerName = prompt("Enter your name: ");
document.getElementById('player_name').innerHTML = document.playerName;
document.difficulty = 3;
startGameAI();
}
function vsAInoob(){
//Function so set up the game for P1 vs AI mode
alert("Whoever goes first is selected randomly \n\nBeginner level AI is really simple, so it is pretty easy to win\n\nIMPORTANT NOTE: If computers gets to start, give him some time to work out the move");
var nope = document.getElementById('grid_AI_setup');
var element = document.getElementById('grid_AI');
nope.style.display = "none";
element.style.display = "grid";
document.playerName = "Player1";
document.playerName = prompt("Enter your name: ");
document.getElementById('player_name').innerHTML = document.playerName;
document.difficulty = 1;
startGameAI();
}
function vsAImiddle(){
//Function so set up the game for P1 vs AI mode
alert("Whoever goes first is selected randomly \n\nAmateur level AI plays different each turn, it might play very good or like a complete beginner \n\nIMPORTANT NOTE: If computers gets to start, give him some time to work out the move");
var nope = document.getElementById('grid_AI_setup');
var element = document.getElementById('grid_AI');
nope.style.display = "none";
element.style.display = "grid";
document.playerName = "Player1";
document.playerName = prompt("Enter your name: ");
document.getElementById('player_name').innerHTML = document.playerName;
document.difficulty = 2;
startGameAI();
}
function backAI(){
//Function to go back to the main screen when playing P1 vs P2 mode
var nope = document.getElementById('grid_main');
var element = document.getElementById('grid_AI');
nope.style.display = "grid";
element.style.display = "none";
}
function setMessageAI(msg){
//Function to set the message
document.getElementById('messageAI').innerHTML = msg;
}
/*
Board state array - contains 9 integers, each one representing one tile of the game board
* 0 means empty(free, available)
* 1 means taken by human
* -1 means taken by AI
*/
document.boardState = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
];
const HUMANVALUE = 1;
const COMPUTERVALUE = -1;
document.player;
document.countTilesAI;
//Function to start the game / restart the game
function startGameAI(){
for (var a = 0; a < 3; a++){
for(var b = 0; b < 3; b++){
document.getElementById("tileAI" + a + "-" + b).innerText = "";
document.getElementById("tileAI" + a + "-" + b).style.color = "black";
}
}
for (var j = 0; j < 3; j++){
for(var k = 0; k < 3; k++){
document.boardState[j][k] = 0;
}
}
document.AIturn = "X";
document.countTilesAI = 0;
//The player who starts the game is decided randomly;
if (Math.floor(Math.random() * 2) === 0){
document.player = "HUMAN";
}
else{
document.player = "COMPUTER";
}
if(document.player === "HUMAN"){
setMessageAI(document.playerName + ", you get to start");
}
else{
setMessageAI("Computer gets to start");
//Uncomment the line below if you want the AI to be called with a timer
//But don't forget to comment the other line!
// No timer --> moveAI();
// With timer --> BELOW
setTimeout(moveAI, 500);
}
}
function checkForWinnerAI(board){
//Function to check if there is a winner
//Check horizontal
for (var i = 0; i < 3; i++){
if (board[i][0] !== 0 &&
board[i][0] === board [i][1] &&
board[i][0] === board [i][2]){
return board[i][0];
}
}
//Check vertical
for (var j = 0; j < 3; j++){
if (board[0][j] !== 0 &&
board[0][j] === board [1][j] &&
board[0][j] === board [2][j]){
return board[0][j];
}
}
//Check diagonal: Top left - bottom right;
if (board[0][0] !== 0 &&
board[0][0] === board [1][1] &&
board[0][0] === board [2][2]){
return board[0][0];
}
//Check diagonal: Top left - bottom right;
if (board[2][0] !== 0 &&
board[2][0] === board [1][1] &&
board[2][0] === board [0][2]){
return board[2][0];
}
for (var i = 0; i < 3; i++){
for (var j = 0; j < 3; j++){
if (board[i][j] === 0){
return false;
}
}
}
return null;
}
function checkFull(board){
for(var x = 0; x < 3; x++){
for(var y = 0; y < 3; y++)
if(board[x][y] === 0) return false;
}
return true;
}
function updateAI(square, row, column){
let gameState = checkForWinnerAI(document.boardState);
if(document.player != "HUMAN"){
return;
}
if(gameState !== null && gameState !== false){
if(gameState === HUMANVALUE){
setMessageAI(document.playerName + ", you already won!");
}
else{
setMessageAI("Computer already won");
}
}
else if(checkFull(document.boardState)){
setMessageAI("It's a draw. Start over!");
}
else if(document.boardState[row][column] !== 0){
setMessageAI("Pick an empty tile");
}
else{
square.innerText = document.AIturn;
document.boardState[row][column] = HUMANVALUE;
switchTurnAI(document.AIturn, document.player);
//Uncomment the line below if you want the AI to be called with a timer
//But don't forget to comment the other line!
// No timer --> moveAI();
// With timer --> BELOW
setTimeout(moveAI, 500);
}
}
//Function to switch the turn
function switchTurnAI(turn, currentPlayer){
document.countTilesAI++;
let gameState = checkForWinnerAI(document.boardState);
if(gameState !== null && gameState !== false){
if(gameState === HUMANVALUE){
//Check horizontal
for (var i = 0; i < 3; i++){
if (document.boardState[i][0] !== 0 &&
document.boardState[i][0] === document.boardState [i][1] &&
document.boardState[i][0] === document.boardState [i][2]){
document.getElementById("tileAI" + i + "-" + 0).style.color = "red";
document.getElementById("tileAI" + i + "-" + 1).style.color = "red";
document.getElementById("tileAI" + i + "-" + 2).style.color = "red";
}
}
//Check vertical
for (var j = 0; j < 3; j++){
if (document.boardState[0][j] !== 0 &&
document.boardState[0][j] === document.boardState [1][j] &&
document.boardState[0][j] === document.boardState [2][j]){
document.getElementById("tileAI" + 0 + "-" + j).style.color = "red";
document.getElementById("tileAI" + 1 + "-" + j).style.color = "red";
document.getElementById("tileAI" + 2 + "-" + j).style.color = "red";
}
}
//Check diagonal: Top left - bottom right;
if (document.boardState[0][0] !== 0 &&
document.boardState[0][0] === document.boardState [1][1] &&
document.boardState[0][0] === document.boardState [2][2]){
document.getElementById("tileAI" + 0 + "-" + 0).style.color = "red";
document.getElementById("tileAI" + 1 + "-" + 1).style.color = "red";
document.getElementById("tileAI" + 2 + "-" + 2).style.color = "red";
}
//Check diagonal: Top left - bottom right;
if (document.boardState[2][0] !== 0 &&
document.boardState[2][0] === document.boardState [1][1] &&
document.boardState[2][0] === document.boardState [0][2]){
document.getElementById("tileAI" + 2 + "-" + 0).style.color = "red";
document.getElementById("tileAI" + 1 + "-" + 1).style.color = "red";
document.getElementById("tileAI" + 0 + "-" + 2).style.color = "red";
}
setMessageAI("Congrats " + document.playerName + " you won!");
return;
} else{
//Check horizontal
for (var i = 0; i < 3; i++){
if (document.boardState[i][0] !== 0 &&
document.boardState[i][0] === document.boardState [i][1] &&
document.boardState[i][0] === document.boardState [i][2]){
document.getElementById("tileAI" + i + "-" + 0).style.color = "red";
document.getElementById("tileAI" + i + "-" + 1).style.color = "red";
document.getElementById("tileAI" + i + "-" + 2).style.color = "red";
}
}
//Check vertical
for (var j = 0; j < 3; j++){
if (document.boardState[0][j] !== 0 &&
document.boardState[0][j] === document.boardState [1][j] &&
document.boardState[0][j] === document.boardState [2][j]){
document.getElementById("tileAI" + 0 + "-" + j).style.color = "red";
document.getElementById("tileAI" + 1 + "-" + j).style.color = "red";
document.getElementById("tileAI" + 2 + "-" + j).style.color = "red";
}
}
//Check diagonal: Top left - bottom right;
if (document.boardState[0][0] !== 0 &&
document.boardState[0][0] === document.boardState [1][1] &&
document.boardState[0][0] === document.boardState [2][2]){
document.getElementById("tileAI" + 0 + "-" + 0).style.color = "red";
document.getElementById("tileAI" + 1 + "-" + 1).style.color = "red";
document.getElementById("tileAI" + 2 + "-" + 2).style.color = "red";
}
//Check diagonal: Top left - bottom right;
if (document.boardState[2][0] !== 0 &&
document.boardState[2][0] === document.boardState [1][1] &&
document.boardState[2][0] === document.boardState [0][2]){
document.getElementById("tileAI" + 2 + "-" + 0).style.color = "red";
document.getElementById("tileAI" + 1 + "-" + 1).style.color = "red";
document.getElementById("tileAI" + 0 + "-" + 2).style.color = "red";
}
setMessageAI("You were defeated. Start over!");
return;
}
}
else if(turn == "X"){
document.AIturn = "O";
if(checkFull(document.boardState)){ //Check if it is a draw
setMessageAI("It's a draw. Start over!");
}
else{
if(currentPlayer === "HUMAN"){
document.player = "COMPUTER";
setMessageAI("It's computer's turn");
}
else{
document.player = "HUMAN";
setMessageAI("It's your turn, " + document.playerName + "!");
}
}
}
else if (turn == "O"){
document.AIturn = "X";
if(checkFull(document.boardState)){ //Check if it is a draw
setMessageAI("It's a draw. Start over!");
}
else{
if(currentPlayer === "HUMAN"){
document.player = "COMPUTER";
setMessageAI("It's computer's turn");
}
else{
document.player = "HUMAN";
setMessageAI("It's your turn, " + document.playerName + "!");
}
}
}
}
function minmax(newGrid, depth, player){
const gameState = checkForWinnerAI(newGrid);
if(gameState === false){
const values = [];
for(var i = 0; i < 3; i++){
for(var j = 0; j < 3; j++){
const gridCopy = _.cloneDeep(newGrid);
if (gridCopy[i][j] !== 0) continue;
gridCopy[i][j] = player;
const value = minmax(gridCopy, depth + 1, (player === HUMANVALUE) ? COMPUTERVALUE : HUMANVALUE);
values.push({
cost: value,
cell: {
i: i,
j: j
}
});
}
}
if (player === COMPUTERVALUE){
const max = _.maxBy(values, (v) => {
return v.cost;
});
if (depth === 0) {
return max.cell;
} else {
return max.cost;
}
} else {
const min = _.minBy(values, (v) => {
return v.cost;
});
if (depth === 0) {
return min.cell;
} else {
return min.cost;
}
}
} else if (gameState === null) {
return 0;
} else if (gameState === HUMANVALUE) {
return depth - 10;
} else {
return 10 - depth;
}
}
function minmaxnoob(newGrid, depth, player){
const gameState = checkForWinnerAI(newGrid);
if(gameState === false){
const values = [];
for(var i = 0; i < 3; i++){
for(var j = 0; j < 3; j++){
const gridCopy = _.cloneDeep(newGrid);
if (gridCopy[i][j] !== 0) continue;
gridCopy[i][j] = player;
const value = minmaxnoob(gridCopy, depth + 1, (player === HUMANVALUE) ? COMPUTERVALUE : HUMANVALUE);
values.push({
cost: value,
cell: {
i: i,
j: j
}
});
}
}
if (player === HUMANVALUE){
const max = _.maxBy(values, (v) => {
return v.cost;
});
if (depth === 0) {
return max.cell;
} else {
return max.cost;
}
} else {
const min = _.minBy(values, (v) => {
return v.cost;
});
if (depth === 0) {
return min.cell;
} else {
return min.cost;
}
}
} else if (gameState === null) {
return 0;
} else if (gameState === HUMANVALUE) {
return depth - 10;
} else {
return 10 - depth;
}
}
function callAI(){
return minmax(document.boardState, 0, COMPUTERVALUE);
}
function callAInoob(){
return minmaxnoob(document.boardState, 0, COMPUTERVALUE);
}
//Function for the AI move;
function moveAI(){
let gameState = checkForWinnerAI(document.boardState);
if(document.player != "COMPUTER"){
return;
} else if (gameState !== null && gameState !== false){
if(gameState === HUMANVALUE){
setMessageAI(document.playerName + ", you already won!");
} else{
setMessageAI("Computer already won");
}
} else{
if (document.difficulty === 1) {
if (document.countTilesAI === 0){
let startMove1 = Math.floor((Math.random() * 4) + 1);
if (startMove1 === 1) {
document.boardState[0][0] = COMPUTERVALUE;
document.getElementById("tileAI" + 0 + "-" + 0).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
} else if (startMove1 === 2) {
document.boardState[0][2] = COMPUTERVALUE;
document.getElementById("tileAI" + 0 + "-" + 2).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
} else if (startMove1 === 3) {
document.boardState[2][0] = COMPUTERVALUE;
document.getElementById("tileAI" + 2 + "-" + 0).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
} else if (startMove1 === 4) {
document.boardState[2][2] = COMPUTERVALUE;
document.getElementById("tileAI" + 2 + "-" + 2).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
}
} else {
const noob = callAInoob();
document.boardState[noob.i][noob.j] = COMPUTERVALUE;
document.getElementById("tileAI" + noob.i + "-" + noob.j).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
}
} else if (document.difficulty === 2) {
if (document.countTilesAI === 0){
let startMove2 = Math.floor((Math.random() * 4) + 1);
if (startMove2 === 1) {
document.boardState[0][0] = COMPUTERVALUE;
document.getElementById("tileAI" + 0 + "-" + 0).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
} else if (startMove2 === 2) {
document.boardState[0][2] = COMPUTERVALUE;
document.getElementById("tileAI" + 0 + "-" + 2).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
} else if (startMove2 === 3) {
document.boardState[2][0] = COMPUTERVALUE;
document.getElementById("tileAI" + 2 + "-" + 0).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
} else if (startMove2 === 4) {
document.boardState[2][2] = COMPUTERVALUE;
document.getElementById("tileAI" + 2 + "-" + 2).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
}
} else {
let whatMove = Math.floor((Math.random() * 100) + 1);
if (whatMove > 40) {
const move2 = callAI();
document.boardState[move2.i][move2.j] = COMPUTERVALUE;
document.getElementById("tileAI" + move2.i + "-" + move2.j).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
} else {
const movenoob2 = callAInoob();
document.boardState[movenoob2.i][movenoob2.j] = COMPUTERVALUE;
document.getElementById("tileAI" + movenoob2.i + "-" + movenoob2.j).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
}
}
} else if (document.difficulty === 3) {
if (document.countTilesAI === 0){
let startMove3 = Math.floor((Math.random() * 4) + 1);
if (startMove3 === 1) {
document.boardState[0][0] = COMPUTERVALUE;
document.getElementById("tileAI" + 0 + "-" + 0).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
} else if (startMove3 === 2) {
document.boardState[0][2] = COMPUTERVALUE;
document.getElementById("tileAI" + 0 + "-" + 2).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
} else if (startMove3 === 3) {
document.boardState[2][0] = COMPUTERVALUE;
document.getElementById("tileAI" + 2 + "-" + 0).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
} else if (startMove3 === 4) {
document.boardState[2][2] = COMPUTERVALUE;
document.getElementById("tileAI" + 2 + "-" + 2).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
}
} else {
const move = callAI();
document.boardState[move.i][move.j] = COMPUTERVALUE;
document.getElementById("tileAI" + move.i + "-" + move.j).innerText = document.AIturn;
switchTurnAI(document.AIturn, document.player);
}
}
}
}
//Javascript for magic board game
function magicBoard(){
//Function to set up the game for Player1 vs Player2 mode
var nope = document.getElementById('grid_main');
var element = document.getElementById('grid_magic');
nope.style.display = "none";
element.style.display = "grid";
var name1 = "Player1";
var name2 = "Player2";
var name3 = "Player3";
name1 = prompt("Enter first player's name: ");
name2 = prompt("Enter second player's name: ");
name3 = prompt("Enter third player's name: ");
document.getElementById('magic1').innerHTML = name1;
document.getElementById('magic2').innerHTML = name2;
document.getElementById('magic3').innerHTML = name3;
magicStartGame();
}
function backMagic(){
//Function to go back to the main screen when playing P1 vs P2 mode
var nope = document.getElementById('grid_main');
var element = document.getElementById('grid_magic');
nope.style.display = "grid";
element.style.display = "none";
}
function magicStartGame(){
for(var i = 1; i <= 16; i++){
document.getElementById("magictile" + i).innerText = "";
document.getElementById("magictile" + i).style.color = "black";
}
document.turn = "X";
document.winner = null;
document.countTiles = 0;
setMessageMagic(document.turn + " gets to start");
}
function updateMagic(square){
if(document.winner === true){
setMessageMagic(document.turn + " already won");
}
else if(document.countTiles == 16){
setMessageMagic("It's a draw");
}
else if(square.innerText === "X" || square.innerText === "O" || square.innerText === "M"){
setMessageMagic("Pick an empty tile");
}else{
square.innerText = document.turn;
switchTurnMagic(document.turn);
}
}
function switchTurnMagic(turn){
//Function that switches turns
document.countTiles++;
if(checkForWinnerMagic(document.turn)){
setMessageMagic("Congrats " + document.turn + " you won!");
}
else if (turn == "X"){
document.turn = "O";
if(document.countTiles == 16){
setMessageMagic("It's a draw");
}
else{
setMessageMagic(document.turn + "'s turn");
}
}
else if (turn == "O"){
document.turn = "M";
if(document.countTiles == 16){
setMessageMagic("It's a draw");
}
else{
setMessageMagic(document.turn + "'s turn");
}
}
else{
document.turn = "X";
if(document.countTiles == 16){
setMessageMagic("It's a draw");
}
else{
setMessageMagic(document.turn + "'s turn");
}
}
}
function setMessageMagic(msg){
//Function to set the message
document.getElementById('magicMessage').innerHTML = msg;
}
function returnBoxMagic(index){
//Function to return a selected tile
return document.getElementById("magictile" + index).innerText;
}
function isRowFilledMagic(tile1, tile2, tile3, move){
//Function to check if any row is filled
//At first, the value is false
var isFilled = false;
if(returnBoxMagic(tile1) == move && returnBoxMagic(tile2) == move && returnBoxMagic(tile3) == move){
isFilled = true;
document.getElementById("magictile" + tile1).style.color = "red";
document.getElementById("magictile" + tile2).style.color = "red";
document.getElementById("magictile" + tile3).style.color = "red";
}
return isFilled;
}
function checkForWinnerMagic(move){
//Function to check if there is a winner
var isThereAWinner = false;
if(isRowFilledMagic (1, 2, 3, move) ||
isRowFilledMagic (5, 6, 7, move) ||
isRowFilledMagic (9, 10, 11, move) ||
isRowFilledMagic (13, 14, 15, move) ||
isRowFilledMagic (2, 3, 4, move) ||
isRowFilledMagic (6, 7, 8, move) ||
isRowFilledMagic (10, 11, 12, move) ||
isRowFilledMagic (14, 15, 16, move) ||
isRowFilledMagic (1, 5, 9, move) ||
isRowFilledMagic (2, 6, 10, move) ||
isRowFilledMagic (3, 7, 11, move) ||
isRowFilledMagic (4, 8, 12, move) ||
isRowFilledMagic (5, 9, 13, move) ||
isRowFilledMagic (6, 10, 14, move) ||
isRowFilledMagic (7, 11, 15, move) ||
isRowFilledMagic (8, 12, 16, move) ||
isRowFilledMagic (5, 10, 15, move) ||
isRowFilledMagic (1, 6, 11, move) ||
isRowFilledMagic (6, 11, 16, move) ||
isRowFilledMagic (2, 7, 12, move) ||
isRowFilledMagic (3, 6, 9, move) ||
isRowFilledMagic (4, 7, 10, move) ||
isRowFilledMagic (7, 10, 13, move) ||
isRowFilledMagic (8, 11, 14, move)
){
isThereAWinner = true;
document.winner = true;
}
return isThereAWinner;
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<script src="tictactoe.js"></script>
</body>
</html>
2. By dρlυѕρlυѕ
Made by dρlυѕρlυѕ. A very simple tic tac toe game. You can click the switch button at the bottom to select a different symbol, you can also reset the game by clicking the reset button. The game also keeps history of the wins, lose and draws. ( Source )
<!DOCTYPE html>
<!--
Created: 26.10.2017.
Original design: https://dribbble.com/shots/3402966-Tic-Tac-Toe
To choose the symbol specifically, use the switch each time.
-->
<html>
<head>
<title>Tic tac toe</title>
<meta charset="utf-8">
<meta name="author" content="dplusplus" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"> </script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<style>
@import url('https://fonts.googleapis.com/css?family=Nunito');
*{
font-family: "Nunito", sans-serif;
}
body{
margin: 0;
padding: 0;
box-sizing: border-box;
overflow: hidden;
}
.wrap{
position: absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
height: 440px;
max-height: 440px;
width: 340px;
border: solid thin #01bbc2;
border-image: -webkit-linear-gradient(to top, #01bbc2, #3150ce);
border-image-slice: 1;
box-shadow: 0 15px 25px rgba(1, 118, 122, 0.2);
}
table {
margin: 0px;
border-collapse: collapse;
border-style: hidden;
position: absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
height:200px;
max-height: 200px;
width: 200px;
table-layout: fixed;
/*box-shadow: 0 2px 8px rgba(0,0,0,0.3);*/
}
table td {
padding: 0px;
border: 5px solid #ddd;
}
.cell {
text-align: center;
font-family: "Nunito", sans-serif;
font-weight: 900;
margin: 0px;
white-space: nowrap;
height: 80px;
max-height: 80px;
width: 90px;
position: relative;
display: table-cell;
color: #01bbc2;
}
span.fa-4x{
font-size: 57px ;
}
span.fa-times{
font-size: 62px;
}
header {
height: 10%;
width: 100%;
margin: 0;
position: absolute;
top: 0%;
padding: 20px;
display: inline-block;
/*background-color: yellow;*/
}
/*#o_win, #draws{
padding-left: 50px;
}*/
#x_win{
color: #547cd8;
top: 13px; left: 35px;
position: absolute;
}
#o_win{
color: #01bbc2;
top: 18px; left: 150px;
position: absolute;
}
#draws{
color: #888;
top: 19px; left: 270px;
position: absolute;
}
#ooo,#xx,#draws0 {
font-variant-numeric:tabular-nums;
}
.fa-times{
font-size: 34px;
}
.fa-circle-o{
font-size: 27px;
}
.fa-balance-scale{
font-size: 23px;
}
/*footer*/
#result {
color: #01bbc2;
font-size: 20px;
font-family: "Nunito";
position: relative;
bottom: 40px; left: 130px;
}
footer{
width: 100%;
height: 15%;
position: absolute;
bottom: 0px;
display: inline-flex;
}
/*switch*/
.toggleXO{
position: absolute;
bottom: 15px; left: 250px;
width: 60px;
height: 30px;
display: inline;
}
.toggleXO input{
display: none;
}
.slider::before{
content:"✖";
color: #547cd8;
position: absolute;
cursor: pointer;
top: 0px; left: 10px;
font-weight: 500;
font-size:20px;
}
.slider{
position: absolute;
cursor: pointer;
top: 0; left: 0;
bottom:0; right: 0;
/*border: 1px solid red;*/
background: rgba(0, 0, 0, 0.2);
background-color: #fff;
box-shadow: inset 0 0 2px 2px rgba(0, 0, 0, 0.2), inset 0 0 3px 3px rgba(0, 0, 0, 0.1), 0 0 1px 1px rgba(255, 255, 255, 0.1);
border-radius: 25px;
-webkit-transition: .25s;
transition: .25s;
}
.slider::after {
content: " ◯ ";
padding-top: 6px;
padding-left: 7px;
position: absolute;
height: 34px;
width: 34px;
left: 0px; bottom: -2px;
-webkit-transition: .3s;
transition: .3s;
border-radius: 50%;
background-color: #01bbc2;
color: #fff;
font-weight: 900;
/* box-shadow: 0 2px 5px rgba(85, 85, 85, 0.7)*/;
}
input:checked + .slider::after {
transform: translateX(35px);
}
.fa-refresh {
font-size: 20px;
}
#butt_reset{
width: 34px;
height: 34px;
border-radius: 100%;
border: none;
outline: none;
position: relative;
color: #fff;
background-color: #bbb;
bottom: -1px;
}
#butt_reset.active{
background-color: #999;
bottom: -2px;
transition: background-color .25s ease;
outline: none;
}
#around {
border: 1px solid #ddd;
position: absolute;
left: 30px; bottom: 13px;
width: 45px;
height: 45px;
border-radius: 100%;
padding: 3px 8px 4px 4px;
}
</style>
<div class="wrap">
<header>
<div id="x_win"> <i class="fa fa-times" aria-hidden="true"> </i> <div id="xx"> wins </div></div>
<div id="o_win"> <i class="fa fa-circle-o" aria-hidden="true"></i><div id="ooo"> wins </div> </div>
<div id="draws"> <i class="fa fa-balance-scale" aria-hidden="true"></i> <div id="draw0"> draws</div></div>
</header>
<table id="board">
<tr>
<td class="cell" id="cell_1" onclick="cell_click('cell_1');"></td>
<td class="cell" id="cell_2" onclick="cell_click('cell_2');"></td>
<td class="cell" id="cell_3" onclick="cell_click('cell_3');"></td>
</tr>
<tr>
<td class="cell" id="cell_4" onclick="cell_click('cell_4');"></td>
<td class="cell" id="cell_5" onclick="cell_click('cell_5');"></td>
<td class="cell" id="cell_6" onclick="cell_click('cell_6');"></td>
</tr>
<tr>
<td class="cell" id="cell_7" onclick="cell_click('cell_7');"></td>
<td class="cell" id="cell_8" onclick="cell_click('cell_8');"></td>
<td class="cell" id="cell_9" onclick="cell_click('cell_9');"></td>
</tr>
</table>
<footer>
<label class="toggleXO">
<input id="myCheckBox" type="checkbox" onclick="switchxo();">
<span class="slider"></span>
</label>
<div id="around">
<button id="butt_reset" onclick="reset(), button();" value="RESET"> <i class="fa fa-refresh " aria-hidden="true"></i> </button>
</div>
<h3 id="result"> # result </h3>
</footer>
</div>
<script>
//there's still a bug in cwitch
// work in progress
window.onload = function(){
};
var countx= 0;
var count=0;
var counto=0;
var count_draws=0;
var player = 0;
var checkcheck= false;
var x= '<span class="fa fa-times"></span>';
var o= '<span class="fa fa-circle-o fa-4x"></span>';
function cell_click(cell){
document.getElementById("result").innerHTML= "# result";
var element= document.getElementById(cell);
if(element.innerHTML != "") return;
if(player == 1) {
element.innerHTML = x;
element.style.color= "#547cd8";
player -= 1;
++count;
winner ();
} else {
element.innerHTML = o;
element.style.color= "#01bbc2";
player += 1;
++count;
winner ();
}
}
function winner(){
if(
//horizontal X
document.getElementById("cell_1").innerHTML == x && document.getElementById("cell_2").innerHTML == x && document.getElementById("cell_3").innerHTML == x || document.getElementById("cell_4").innerHTML == x && document.getElementById("cell_5").innerHTML == x && document.getElementById("cell_6").innerHTML == x || document.getElementById("cell_7").innerHTML == x && document.getElementById("cell_8").innerHTML == x && document.getElementById("cell_9").innerHTML == x ||
//vertical X
document.getElementById("cell_1").innerHTML == x && document.getElementById("cell_4").innerHTML == x && document.getElementById("cell_7").innerHTML == x || document.getElementById("cell_2").innerHTML == x && document.getElementById("cell_5").innerHTML == x && document.getElementById("cell_8").innerHTML == x || document.getElementById("cell_3").innerHTML == x && document.getElementById("cell_6").innerHTML == x && document.getElementById("cell_9").innerHTML == x ||
//diagonal X
document.getElementById("cell_1").innerHTML == x && document.getElementById("cell_5").innerHTML == x && document.getElementById("cell_9").innerHTML == x || document.getElementById("cell_3").innerHTML == x && document.getElementById("cell_5").innerHTML == x && document.getElementById("cell_7").innerHTML == x
){
document.getElementById("result").innerHTML= "# X won";
++countx;
document.getElementById("xx").innerHTML= countx +" " + "wins";
reset();
count= 0;
// document.getElementById("result").innerHTML= "result";
} else if (
//horizontal O
document.getElementById("cell_1").innerHTML == o && document.getElementById("cell_2").innerHTML == o && document.getElementById("cell_3").innerHTML == o || document.getElementById("cell_4").innerHTML == o && document.getElementById("cell_5").innerHTML == o && document.getElementById("cell_6").innerHTML == o || document.getElementById("cell_7").innerHTML == o && document.getElementById("cell_8").innerHTML == o && document.getElementById("cell_9").innerHTML == o ||
//vertical O
document.getElementById("cell_1").innerHTML == o && document.getElementById("cell_4").innerHTML == o && document.getElementById("cell_7").innerHTML == o || document.getElementById("cell_2").innerHTML == o && document.getElementById("cell_5").innerHTML == o && document.getElementById("cell_8").innerHTML == o || document.getElementById("cell_3").innerHTML == o && document.getElementById("cell_6").innerHTML == o && document.getElementById("cell_9").innerHTML == o ||
//diagonal O
document.getElementById("cell_1").innerHTML == o && document.getElementById("cell_5").innerHTML == o && document.getElementById("cell_9").innerHTML == o || document.getElementById("cell_3").innerHTML == o && document.getElementById("cell_5").innerHTML == o && document.getElementById("cell_7").innerHTML == o
){
document.getElementById("result").innerHTML= "# O won";
++counto;
document.getElementById("ooo").innerHTML= counto +" " + "wins";
reset();
count=0;
//document.getElementById("result").innerHTML= "result";
}
else if (count == 9){
++count_draws;
document.getElementById("draw0").innerHTML= count_draws +" " + "draws";
document.getElementById("result").innerHTML= "# draw";
reset();
count = 0;
// document.getElementById("result").innerHTML= "result";
}
}
function reset (){
//reset buttons to empty
document.getElementById("cell_1").innerHTML = "";
document.getElementById("cell_2").innerHTML = "";
document.getElementById("cell_3").innerHTML = "";
document.getElementById("cell_4").innerHTML = "";
document.getElementById("cell_5").innerHTML = "";
document.getElementById("cell_6").innerHTML = "";
document.getElementById("cell_7").innerHTML = "";
document.getElementById("cell_8").innerHTML = "";
document.getElementById("cell_9").innerHTML = "";
count=0;
};
function switchxo(){
reset();
var check= document.getElementById("myCheckBox").checked;
if(!checkcheck){
player = 1;
} else {
player = 0;
}
checkcheck = !checkcheck;
};
function button(){
var b= document.getElementById("butt_reset");
b.classList.toggle("active", 200);
}
</script>
</body>
</html>
3. By Madhav
Made by Madhav. A Tic Tac Toe JavaScript App. By default the game mode is set to medium, and you play with a AI. To change that click the menu icon and after that go to settings, in settings select the options you want to enable, like two player mode, or a difficult AI Mode. ( Source )
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Merienda|Montserrat|EB+Garamond|Raleway" rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
<title>Tic Tac Toe | [ Game ]</title>
</head>
<body>
<style>
body {
margin:0; padding:0;
background-color:#262626;
user-select:none;
color:white;
font-family: 'EB Garamond', serif;
}
i {
margin:3px;
}
img{
width:80%; max-width:500px;
margin:auto;
border-radius:5px;
}
header {
display:block;
top:0; margin:0;
text-align:center;
background-color:#00C4C4;
width:100%;
color:#262626;
height:58px;
z-index:10;
}
h1 {
text-align:center;
margin:0;
padding:7px; color:#262626;
z-index:12;
}
#openMenu,#closeMenu {
position:absolute ;
display:block;
top:10px; left:10px;
background-color:transparent ;
height:40px; width:60px;
}
#openMenu > span {
position:relative ;
display:block ;
height:4px; width:36px;
margin:6px;
background-color:#262626;
transition-duration:0.5s;
}
#closeMenu {
z-index:-1;
}
#menuHolder {
display:block;
position:absolute;
width:100%;
background-color:#00C4C4;
top:60px; left:-100%;
height:calc(100% - 60px);
transition-duration:0.55s;
z-index:10;
}
nav {
position:relative;
display:block ;
width:48%; max-width:380px;
padding:15px;
margin:40px auto 40px auto;
text-align:center;
font-size:20px;
color:white;
border-radius:5px;
font-weight:bold;
font-family: 'Merienda', cursive;
}
#sett {
background-color:#1C252E;
}
.tab {
position:absolute ;
display:block ;
top:70px; width:100%;
visibility:hidden;
}
#HOME {
padding-top:20px;
font-family: 'Raleway', sans-serif;
}
#ABOUT > p {
text-align:left;
margin:50px;
font-size:19px;
font-family: 'Merienda', cursive;
}
span {
font-family: 'EB Garamond', serif;
font-size:22px;
font-weight:bold ;
}
#INST > p > span {
color:#00C4C4;
margin:10px;
}
#INST > p {
text-align:left;
margin:10px;
font-size:16px;
font-family: 'Merienda', cursive;
}
table {
display:block ;
position:relative ;
margin:auto;
margin-top:10px;
color:#FF0066;
text-align:center;
font-weight:bolder;
font-size:42px;
border-collapse:collapse;
width:312px;
}
td{
height:100px; width:100px;
background-color:#353F4A;
border-radius:4px;
border:3px solid #E90663;
}
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;
}
.pad,.block {
height:60px; width:60px;
margin:10px; padding:10px;
background-color:#00C4C4;
border-radius:4px;
transition-duration:.18s;
}
#level,#player {
display:block ;
position:relative ;
margin:auto; margin-top:10px;
outline:none;
border-radius:30px;
border:none;
width:75%; max-width:380px;
padding:15px 25px 15px 35px;
background-color:white;
box-shadow:0 1px 3px rgba(0,0,0,0.12), 0 3px 5px rgba(0,0,0,0.3);
font-size:16px;
font-family: 'Merienda', cursive;
}
#SETT {
text-align:center;
padding-top:10px;
visibility:visible;
}
#SETT > span {
color:#00C4C4;
margin:10px;
}
.block {
display:inline-block ;
position:relative ;
height:50px; width:50px;
margin:20px; margin-bottom:0px;
color:#FF0066;
text-align:center;
font-weight:bolder;
font-size:40px;
font-family: 'Raleway', sans-serif;
background-color:#fff;
transition-duration:0s;
}
button {
display:block ;
position:relative;
background-image:-webkit-linear-gradient(-45deg,#13547a,#80d0c7);
color:white; margin:auto;
border:none; outline:none;
border-radius:10px;
height:54px; width:34%;
margin-top:30px;
max-width:200px;
font-size:20px;
font-weight:bold;
box-shadow:0 1px 3px rgba(0,0,0,0.12), 0 3px 5px rgba(0,0,0,0.3);
cursor:pointer;
font-family: 'EB Garamond', serif;
}
button:active
{
box-shadow:0 0 black;
transform:scale(0.84);
}
#x {
color:white;
background-color:#00C4C4;
}
#result {
margin:0; padding:0;
display:block ;
position:relative ;
margin:auto;
text-align:center;
}
#result > div {
display:inline-block;
font-family: 'Raleway', sans-serif;
}
#res2{
margin-left:65px;
}
#sym1 { color:lightgreen;
font-family: 'Raleway', sans-serif;
}
#sym2 { color:#FF0066;
font-family: 'Raleway', sans-serif;
}
#resultBoard {
display:block ;
position:absolute ;
top:100px; left:0; right:0;
margin:auto; text-align:center;
width:290px; padding:15px;
background-color:#1C252E;
font-size:30px;
border:3px solid white;
border-radius:8px;
visibility:hidden ;
font-family: 'Merienda', cursive;
}
#resultBoard > button {
display:inline-block ;
font-size:18px;
width:40%;
margin:20px 10px 5px 10px;
}
#reset {
background-color:tomato;
background-image:none;
}
@keyframes pop
{
0%
{ transform:scale(0.6); }
34%
{ transform:scale(1); }
66%
{ transform:scale(0.84); }
100%
{ transform:scale(1); }
}
#levelView {
width:100%; text-align:center;
margin-top:10px;
}
</style>
<!-- Header -->
<header>
<h1>Tic Tac Toe</h1>
<div id="closeMenu" onclick="closeMenu()"></div>
<div id="openMenu" onclick="openMenu()" >
<span></span>
<span></span>
<span></span>
</div></header>
<div id="menuHolder">
<nav id='home'><i class="fas fa-home"></i> HOME</nav>
<nav id = 'inst' onclick='inst()'><i class="fas fa-book"></i> GUIDE</nav>
<nav id="sett"><i class="fas fa-cog"></i> SETTING</nav>
<nav id='about' onclick='about()'><i class="fas fa-info-circle"></i> ABOUT</nav>
</div>
<div id="HOME" class="tab">
<!-- table for tic tac toe -->
<div id="result">
<div><span>You</span>(<span id="sym1">X</span>) : <span id="res1">0</span></div>
<div><span id="res2">0</span> : <span id="user">AI</span>(<span id="sym2">O</span>)</div>
</div>
<table>
<tr>
<td>
<div class="pad" id="0"></div>
</td>
<td>
<div class="pad" id="1"></div>
<td>
<div class="pad" id="2"></div>
</td>
</tr>
<tr>
<td>
<div class="pad" id="3"></div>
</td>
<td>
<div class="pad" id="4"></div>
<td>
<div class="pad" id="5"></div>
</td>
</tr>
<tr>
<td>
<div class="pad" id="6"></div>
</td>
<td>
<div class="pad" id="7"></div>
<td>
<div class="pad" id="8"></div>
</td>
</tr>
</table>
<div id="levelView">Level : Medium</div>
<!-- Result board -->
<div id="resultBoard" >
<div id="finalResult">None</div>
<button id="tryAgain" onclick="playAgain() ">Try Again</button>
<button id="reset" onclick="startGame() " >RESET</button>
</div>
</div>
<div id="INST" class="tab">
<center> <img src="https://dl.dropbox.com/s/92s8cl0ioijfrz0/TicTacToe.jpg?dl=0" alt="gameImage" /></center>
<p> <span>Step 1 :</span>
In Tic-Tac-Toe, two players try to line up three symbols in a vertical, horizontal or diagonal row.
<br><br>
<span>Step 2 : </span> You have the first turn to play i.e you are either (X or O) then the bot will play. <br><br>
<span>Step 3 : </span> Hit RESET to play again. <br><br>
<span>Step 4 :</span> In two player mode, after either win,lose or draw the first will vary alternately.
<br><br> <span>NOTE : </span> check <i>settings</i> in the menu, to play two player or change your playing symbol .
</p>
</div>
<div id="SETT" class="tab">
<span>1. Choose your symbol :</span><br>
<div id="opt" >
<div id="x" class="block" onclick='setPlayer("X")'>X</div>
<div id="o" class="block" onclick="setPlayer('O')">O</div>
</div>
<br>
<span>2. Choose player : </span>
<Select id="player" oninput="setType()">
<span></span>
<Option value="AI">AI</Option>
<Option value="twoPlayer">Two Player</option>
</select> <br>
<span id="level0">3. Choose Difficulty : </span>
<Select id="level" oninput="startGame()">
<Option value="easy">EASY</Option>
<Option value="medium" selected>MEDIUM</option>
<Option value="hard">HARD</option>
</select>
<button onclick="settGame()">Play</button>
</div>
<div id="ABOUT" class="tab">
<p>
<span>Name :</span> Tic Tac Toe <br>
<span>Author: </span>Madhav <br />
<span>Version : </span>2.5.0 <br />
<span>Created on:</span> 5<sup>th</sup>,March;2019
<br /><br>
<span><u>Version Update :</u></span> <br><span>1.3.0</span><br>
--A simple AI added to play with<br><br>
<span>2.2.1</span><br>
--A complex Ai i.e MinMax feature added<br><br>
<span>2.5.0</span><br>
--setting tab and option for two player game added.<br>
--some minor bugs fixed and UI changes.<br>
--Score board tan added to popUp on win,lose or draw .<br>
--Medium level introduced .<br>
--Game made public.<br>
</p>
</div>
<script>
//some variables
var cell,originalBoard;
var playerType = "AI";
var level = "easy";
const winCombos = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[6, 4, 2]
]
var player2 = "X";
var player1 = (player2=="X")?"O":"X";
var user,sym1,res1,sym2,res2;
var temp = player2 ;
var resultBoard ;
//Main function that will start the game
function startGame() {
//initializing level
level = document.getElementById("level").value;
document.getElementById("levelView").innerHTML = "Level : " + level;
res1 = 0; res2 = 0; sym1 = player2 ;
sym2 = player1 ;
user = (playerType == "AI")?"AI":"Friend";
//Initializing the array
originalBoard = [0,1,2,3,4,5,6,7,8];
//each box
cell = document.getElementsByClassName("pad");
//event for on click
for(let i=0;i<cell.length;i++) {
cell[i].innerText = "";
cell[i].style.backgroundColor = "#00C4C4"; cell[i].addEventListener("click",turnClick,false);
} updateScore();
resultBoard = document.getElementById("resultBoard");
resultBoard.style.visibility = "hidden";
resultBoard.style.animation = "";
}
//to fill the the boxes
function turnClick(box) {
if(typeof(originalBoard [box.target.id])=="number") {
turn(box.target.id,temp);
//to give Turn to the AI as per level
if(playerType == "AI") {
if(isWinning(originalBoard,player2)===false) {
if(level=="easy") {
simpleAi();
} else if(level=="hard") {
complexAi();
} else if(level=="medium"){
mediumAi();
}
}} else {
swapPlayer() ;
}
}
}
//function to change color of cells and simple number
function turn(num,val) {
if(num!=undefined) {
originalBoard[num] = val;
cell[num].innerText = val;
cell[num].style.backgroundColor = "#1C252E";
}
//to check if player is wininning
var isWon = isWinning(originalBoard,val);
if(isWon != false) {
if(val==player1) {
res2++; updateScore();
}else {
res1++; updateScore();
}
endGame(val,isWon);
}
//in case if draw
if(emptySquares(originalBoard).length==0&&!isWon) {
endGame("none",null);
}
}
//A simple AI to play with
function simpleAi() {
let empty = emptySquares(originalBoard) ;
let ran = Math.floor(Math.random()*(empty.length-1));
turn(empty[ran],player1);
}
//medium Ai
function mediumAi() {
let check,num;
for(var i=0;i<winCombos.length;i++) { let check,num;
check = 0 ;
for(var j=0;j<3;j++) {
if(originalBoard [winCombos[i][j]]==player1){
check++;
} else {
num = j;
}
}
if(check==2&&typeof(originalBoard [winCombos[i][num]])=="number"){
turn(winCombos[i][num],player1);
return null;
}
}
for(var i=0;i<winCombos.length;i++) { let check,num;
check = 0 ;
for(var j=0;j<3;j++) {
if(originalBoard [winCombos[i][j]]==player2){
check++;
} else {
num = j;
}
}
if(check==2&&typeof(originalBoard [winCombos[i][num]])=="number"){
turn(winCombos[i][num],player1);
return null;
}
} simpleAi() ;
}
//compled AI i.e minmax method
function complexAi() {
turn(minimax(originalBoard, player1).index,player1);
}
//to check if any box is empty
function emptySquares(board) {
let emptySquares = [] ;
for(let i=0;i<board.length;i++) {
if(typeof(board[i])=="number"){
emptySquares.push(i);
}
}
return emptySquares;
}
//check win combos
function isWinning (board,player) {
var check;
for(let i=0;i<winCombos.length;i++) { check = 0 ;
for(let j=0;j<3;j++) {
if(board[winCombos[i][j]]==player){
check++;
}
}
if(check==3){
return winCombos[i];
}
} return false;
}
//ending the game
function endGame (val,isWon) {
let finalResult = document.getElementById("finalResult");
//removing eventlistener from cells
for(let i=0;i<cell.length;i++) {
cell[i].removeEventListener("click",turnClick,false);
}
if(val == player2 ) {
finalResult.innerText = "You Won !";
finalResult.style.color ="lime";
resultBoard.style.visibility = "visible";
resultBoard.style.animation = "pop .7s linear";
} else if(val == player1 ) {
finalResult.innerText = "You Lost !";
finalResult.style.color ="tomato";
resultBoard.style.visibility = "visible";
resultBoard.style.animation = "pop .7s linear";
} else if(isWon == null ) {
finalResult.innerText = "Draw !!";
finalResult.style.color ="cyan";
resultBoard.style.visibility = "visible";
resultBoard.style.animation = "pop .7s linear";
}
//coloring winning combo cell
let color = (val==player2)?"lightgreen":"white";
if(isWon != null) {
for(let i=0;i<isWon.length;i++)
{
cell[isWon[i]].style.backgroundColor =color;
}
}
}
function minimax(newBoard, player) {
var availSpots = emptySquares(originalBoard);
if (isWinning(newBoard,player2)!=false){
return {score: -10};
} else if (isWinning(newBoard, player1)!=false) {
return {score: 10};
} else if (availSpots.length === 0) {
return {score: 0}; }
var moves = [];
for (var i = 0; i < availSpots.length; i++) {
var move = {};
move.index = newBoard[availSpots[i]];
newBoard[availSpots[i]] = player;
if (player == player1) {
var result = minimax(newBoard, player2);
move.score = result.score;
} else {
var result = minimax(newBoard, player1);
move.score = result.score;
}
newBoard[availSpots[i]] = move.index;
moves.push(move);
}
var bestMove;
if(player === player1) {
var bestScore = -10000;
for(var i = 0; i < moves.length; i++) {
if (moves[i].score > bestScore) {
bestScore = moves[i].score;
bestMove = i;
}
}
} else {
var bestScore = 10000;
for(var i = 0; i < moves.length; i++) {
if (moves[i].score < bestScore) {
bestScore = moves[i].score;
bestMove = i;
}
}
}
return moves[bestMove];
}
function swapPlayer() {
if(temp==player1) {
temp = player2 ;
} else {
temp = player1 ;
}
}
//to update score
function updateScore() {
document.getElementById("res1").innerText = res1; document.getElementById("res2").innerText = res2; document.getElementById("sym1").innerText = sym1;
document.getElementById("sym2").innerText = sym2; document.getElementById("user").innerText = user;
}
//for playing again
function playAgain() {
resultBoard.style.visibility = "hidden";
resultBoard.style.animation = "";
//Initializing the array
originalBoard = [0,1,2,3,4,5,6,7,8];
//each box
cell = document.getElementsByClassName("pad");
//event for on click
for(let i=0;i<cell.length;i++) {
cell[i].innerText = "";
cell[i].style.backgroundColor = "#00C4C4"; cell[i].addEventListener("click",turnClick,false);
} updateScore();
}
/*
Every thing related to setting and stuff below
*/
function setPlayer(a) {
player2 = a;
temp = a;
player1 = (player2=="X")?"O":"X";
let x = document.getElementById("x");
let o = document.getElementById("o");
if(a=="X") {
x.style.backgroundColor = "#00C4C4";
x.style.color = "white";
o.style.backgroundColor = "white";
o.style.color = "#FF0066";
} else {
o.style.backgroundColor = "#00C4C4";
o.style.color = "white";
x.style.backgroundColor = "white";
x.style.color = "#FF0066";
} startGame(); updateScore();
}
function setType() {
playerType = document.getElementById("player").value;
let a = document.getElementById("level") ;
let b = document.getElementById("level0") ;
if(playerType =="AI") {
a.style.display = "block";
b.style.display = "block";
}else {
a.style.display = "none";
b.style.display = "none";
}
startGame(); updateScore();
}
function settGame() {
var HOME = document.getElementById("HOME");
fillColor(home,HOME);
document.getElementsByTagName("h1")[0]
.innerHTML = 'Tic Tac Toe';
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
startGame();
}
/*
Every thing related to menu and animation stuff below
*/
var span,close,holder,home,inst,about,sett;
var tab;
window.onload = function() {
//for menu bar
span = document.getElementsByTagName("span");
close = document.getElementById("closeMenu");
holder = document.getElementById("menuHolder");
home = document.getElementById("home");
inst = document.getElementById("inst");
about = document.getElementById("about");
sett = document.getElementById("sett");
home.onclick = function () {
var HOME = document.getElementById("HOME");
fillColor(home,HOME);
document.getElementsByTagName("h1")[0]
.innerHTML = 'Tic Tac Toe';
if( emptySquares(originalBoard).length < 8 ) {
resultBoard.style.visibility = "visible";
}
closeMenu();
}
inst.onclick = function (){
var INST = document.getElementById("INST");
fillColor(inst,INST);
document.getElementsByTagName("h1")[0]
.innerHTML = 'Guide <i class="fas fa-book"></i>';
closeMenu();
}
about.onclick = function (){
var ABOUT = document.getElementById("ABOUT");
fillColor(about,ABOUT);
document.getElementsByTagName("h1")[0]
.innerHTML = 'About <i class="fas fa-info-circle"></i>';
closeMenu();
}
sett.onclick = function (){
var SETT = document.getElementById("SETT");
fillColor(sett,SETT);
document.getElementsByTagName("h1")[0]
.innerHTML = 'Setting <i class="fas fa-cog"></i>';
closeMenu();
}
//To start the Game onload
startGame() ;
}
/* function to control menu bar */
function openMenu() {
//to control animation span[0].style.transformOrigin="18px";
span[0].style.transform = "translateY(10px)rotate(-45deg)";
span[1].style.transformOrigin="18px";
span[1].style.transform = "rotate(45deg)";
span[2].style.opacity = "0";
span[2].style.transform = "translateY(10px)";
close.style.zIndex= "1";
holder.style.left = "0";
}
function closeMenu() {
//to control animation
span[0].style.transformOrigin="18px";
span[0].style.transform = "translateY(0)rotate(0)";
span[1].style.transformOrigin="18px";
span[1].style.transform = "rotate(0)";
span[2].style.opacity = "1";
span[2].style.transform = "translateY(0)";
close.style.zIndex= "-1";
holder.style.left = "-100%";
}
function fillColor(a,b) {
home.style.backgroundColor = "transparent";
inst.style.backgroundColor = "transparent";
about.style.backgroundColor = "transparent";
sett.style.backgroundColor = "transparent";
HOME.style.visibility= "hidden";
INST.style.visibility= "hidden";
ABOUT.style.visibility= "hidden";
SETT.style.visibility= "hidden";
b.style.visibility= "visible";
a.style.backgroundColor = "#1C252E";
resultBoard.style.visibility = "hidden";
resultBoard.style.animation = "";
}
//for swiping actions
window.addEventListener('touchstart', handleTouchStart, false);
window.addEventListener('touchmove', handleTouchMove, false);
var xDown = null, yDown = null;
function getTouches(evt) {
return evt.touches ||
evt.originalEvent.touches;
}
function handleTouchStart(evt) {
const firstTouch = getTouches(evt)[0];
xDown = firstTouch.clientX;
yDown = firstTouch.clientY;
}
function handleTouchMove(evt) {
if ( ! xDown || ! yDown )
{ return; }
var xUp = evt.touches[0].clientX;
var yUp = evt.touches[0].clientY;
var xDiff = xDown - xUp;
var yDiff = yDown - yUp;
if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {
/*Response part*/
if ( xDiff>0) {
/* left swipe */
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
closeMenu();
} else if ( xDiff<0) {
/* right swipe */
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
openMenu();
}
}
/* reset values */
xDown = null; yDown = null;
}
</script>
</body>
</html>
4. By GamerB
Made by GamerB. A simple Tic Tac Toe game that uses AI and keeps track of all the wins and loses. ( Source )
<html>
<head>
<title>Tic Tac Toe</title>
</head>
<body>
<style>
body{
background-color: #1D1D1D;
}
.L1,.L2,.L3
{
background-color:#1D1D1D;
border:none;
height:50px;
width: 70px;
font-size: 40;
text-align: center;
color: white;
font-family:Forte,Stencil Std,Calibri;
position: relative;
top:20%;
left:15%;
}
.L1:focus,.L2:focus,.L3:focus
{
outline: none;
}
#d
{
border-top: 1px solid white;
border-bottom: 1px solid white;
}
#b
{
border-bottom: 1px solid white;
border-left: 1px solid white;
border-right: 1px solid white;
}
#c,#f
{
border-bottom: 1px solid white;
}
#e
{
border-left: 1px solid white;
border-right: 1px solid white;
border-bottom: 1px solid white;
}
#h
{
border-left: 1px solid white;
border-right: 1px solid white;
}
#Res
{
margin: 0 40px;
height: 35px;
line-height: 17px;
width: 150px;
font-family:'Luckiest Guy', Arial, Helvetica, sans-serif;
font-size: 12;
color: #05750A;;
background-color:#F6FAF1;
border: 2px solid #9CC784;
position: fixed;
top: -10%;
left: 0%;
right:0%;
margin:auto;
text-align: center;
box-shadow: 5px 7px 35px 10px black;
}
#Score
{
height: 30px;
line-height: 30px;
width: 300px;
font-family:'Luckiest Guy', Arial, Helvetica, sans-serif;
font-size: 18;
color: #05750A;;
background-color:#F6FAF1;
border: 2px solid #9CC784;
position: fixed;
bottom: 2%;
left: 0%;
right: 0%;
margin: auto;
text-align: center;
box-shadow: 5px 7px 35px 10px black;
}
</style>
<div id="Res" align="center">Congratulations!<br/>You Won!</div>
<div id="Score" align="center">WON- 0 : 0 -LOST</div>
<input class="L1" id="a" type="Button" value=" " onclick="ClickOnButton('L1',0)"/>
<input class="L1" id="b" type="Button" value=" " onclick="ClickOnButton('L1',1)"/>
<input class="L1" id="c" type="Button" value=" " onclick="ClickOnButton('L1',2)"/>
<br/>
<input class="L2" id="d" type="Button" value=" " onclick="ClickOnButton('L2',0)" />
<input class="L2" id="e" type="Button" value=" " onclick="ClickOnButton('L2',1)"/>
<input class="L2" id="f" type="Button" value=" " onclick="ClickOnButton('L2',2)"/>
<br/>
<input class="L3" id="g" type="Button" value=" " onclick="ClickOnButton('L3',0)" />
<input class="L3" id="h" type="Button" value=" " onclick="ClickOnButton('L3',1)"/>
<input class="L3" id="i" type="Button" value=" " onclick="ClickOnButton('L3',2)"/>
<script>
var Won=0,Lost=0;
var GameOver=false;
var U=document.getElementsByClassName("L1");
var M=document.getElementsByClassName("L2");
var L=document.getElementsByClassName("L3");
var ReachedPos=-10;
var Reached=false;
var ReachedEver=false;
var n=0;
function ClickOnButton(ClassName,Index)
{
var Button=document.getElementsByClassName(ClassName);
if(Button[Index].value==" " &&!GameOver)
{
Button[Index].value="O";
Result();
if(GameOver==false)
{
ComputerPlays();
}
}
}
function ComputerPlays()
{
if(U[0].value=="X" && U[1].value=="X" && U[2].value==" ")
{
U[2].value="X";
}
else if(U[0].value=="X" && U[2].value=="X" && U[1].value==" ")
{
U[1].value="X";
}
else if(U[1].value=="X" && U[2].value=="X" && U[0].value==" ")
{
U[0].value="X";
}
//Second Line
else if(M[0].value=="X" && M[1].value=="X" && M[2].value==" ")
{
M[2].value="X";
}
else if(M[0].value=="X" && M[2].value=="X" && M[1].value==" ")
{
M[1].value="X";
}
else if(M[1].value=="X" && M[2].value=="X" && M[0].value==" ")
{
M[0].value="X";
}
//third line
else if(L[0].value=="X" && L[1].value=="X" && L[2].value==" ")
{
L[2].value="X";
}
else if(L[0].value=="X" && L[2].value=="X" && L[1].value==" ")
{
L[1].value="X";
}
else if(L[1].value=="X" && L[2].value=="X" && L[0].value==" ")
{
L[0].value="X";
}
//vertically First Line
else if(U[0].value=="X" && M[0].value=="X" && L[0].value==" ")
{
L[0].value="X";
}
else if(L[0].value=="X" && M[0].value=="X" && U[0].value==" ")
{
U[0].value="X";
}
else if(U[0].value=="X" && L[0].value=="X" && M[0].value==" ")
{
M[0].value="X";
}
//vertically Second Line
else if(U[1].value=="X" && M[1].value=="X" && L[1].value==" ")
{
L[1].value="X";
}
else if(L[1].value=="X" && M[1].value=="X" && U[1].value==" ")
{
U[1].value="X";
}
else if(U[1].value=="X" && L[1].value=="X" && M[1].value==" ")
{
M[1].value="X";
}
//vertically Third Line
else if(U[2].value=="X" && M[2].value=="X" && L[2].value==" ")
{
L[2].value="X";
}
else if(L[2].value=="X" && M[2].value=="X" && U[2].value==" ")
{
U[2].value="X";
}
else if(U[2].value=="X" && L[2].value=="X" && M[2].value==" ")
{
M[2].value="X";
}
else if(U[0].value=="X" && M[1].value=="X" && L[2].value==" ")
{
L[2].value="X";
}
else if(L[2].value=="X" && M[1].value=="X" && U[0].value==" ")
{
U[0].value="X";
}
else if(U[0].value=="X" && L[2].value=="X" && M[1].value==" ")
{
M[1].value="X";
}
else if(U[2].value=="X" && M[1].value=="X" && L[0].value==" ")
{
L[0].value="X";
}
else if(L[0].value=="X" && M[1].value=="X" && U[2].value==" ")
{
U[2].value="X";
}
else if(U[2].value=="X" && L[0].value=="X" && M[1].value==" ")
{
M[1].value="X";
}
//Codes to Defend
else if(U[0].value=="O" && U[1].value==" "&&U[2].value==" "&&M[0].value==" "&&M[1].value==" "&&M[2].value==" "&&L[0].value==" "&&L[1].value==" "&&L[2].value==" ")
{
M[1].value="X";
}
else if(U[2].value=="O" && U[1].value==" "&&U[0].value==" "&&M[0].value==" "&&M[1].value==" "&&M[2].value==" "&&L[0].value==" "&&L[1].value==" "&&L[2].value==" ")
{
M[1].value="X";
}
else if(L[0].value=="O" && U[0].value==" "&& U[1].value==" "&&U[2].value==" "&&M[0].value==" "&&M[1].value==" "&&M[2].value==" "&&L[1].value==" "&&L[2].value==" ")
{
M[1].value="X";
}
else if(L[2].value=="O" && U[0].value==" "&&U[1].value==" " && U[2].value==" "&&M[0].value==" "&&M[1].value==" "&&M[2].value==" "&&L[0].value==" "&&L[1].value==" ")
{
M[1].value="X";
}
else if(M[1].value=="O" && U[0].value==" "&&U[1].value==" " && U[2].value==" "&&M[0].value==" "&&M[2].value==" "&&L[0].value==" "&&L[1].value==" " &&L[2].value==" " )
{
var Number= RandomWithRange(0,3);
if(Number==0)
{
U[0].value="X";
}
else if(Number==1)
{
U[2].value="X";
}
else if(Number==2)
{
L[0].value="X";
}
else if(Number==3)
{
L[2].value="X";
}
}
else if(U[1].value=="O" && U[0].value==" " && U[2].value==" "&&M[0].value==" "&&M[1].value==" "&&M[2].value==" "&&L[0].value==" "&&L[1].value==" "&&L[2].value==" " )
{
M[1].value="X";
}
else if(L[1].value=="O" && U[0].value==" " && U[1].value==" " && U[2].value==" "&&M[0].value==" "&&M[1].value==" "&&M[2].value==" "&&L[0].value==" " &&L[2].value==" " )
{
M[1].value="X";
}
//First Line
else if(U[0].value=="O" && U[1].value=="O" && U[2].value==" ")
{
U[2].value="X";
}
else if(U[0].value=="O" && U[2].value=="O" && U[1].value==" ")
{
U[1].value="X";
}
else if(U[1].value=="O" && U[2].value=="O" && U[0].value==" ")
{
U[0].value="X";
}
//Second Line
else if(M[0].value=="O" && M[1].value=="O" && M[2].value==" ")
{
M[2].value="X";
}
else if(M[0].value=="O" && M[2].value=="O" && M[1].value==" ")
{
M[1].value="X";
}
else if(M[1].value=="O" && M[2].value=="O" && M[0].value==" ")
{
M[0].value="X";
}
//third line
else if(L[0].value=="O" && L[1].value=="O" && L[2].value==" ")
{
L[2].value="X";
}
else if(L[0].value=="O" && L[2].value=="O" && L[1].value==" ")
{
L[1].value="X";
}
else if(L[1].value=="O" && L[2].value=="O" && L[0].value==" ")
{
L[0].value="X";
}
//vertically First Line
else if(U[0].value=="O" && M[0].value=="O" && L[0].value==" ")
{
L[0].value="X";
}
else if(L[0].value=="O" && M[0].value=="O" && U[0].value==" ")
{
U[0].value="X";
}
else if(U[0].value=="O" && L[0].value=="O" && M[0].value==" ")
{
M[0].value="X";
}
//vertically Second Line
else if(U[1].value=="O" && M[1].value=="O" && L[1].value==" ")
{
L[1].value="X";
}
else if(L[1].value=="O" && M[1].value=="O" && U[1].value==" ")
{
U[1].value="X";
}
else if(U[1].value=="O" && L[1].value=="O" && M[1].value==" ")
{
M[1].value="X";
}
//vertically Third Line
else if(U[2].value=="O" && M[2].value=="O" && L[2].value==" ")
{
L[2].value="X";
}
else if(L[2].value=="O" && M[2].value=="O" && U[2].value==" ")
{
U[2].value="X";
}
else if(U[2].value=="O" && L[2].value=="O" && M[2].value==" ")
{
M[2].value="X";
}
else if(U[0].value=="O" && M[1].value=="O" && L[2].value==" ")
{
L[2].value="X";
}
else if(L[2].value=="O" && M[1].value=="O" && U[0].value==" ")
{
U[0].value="X";
}
else if(U[0].value=="O" && L[2].value=="O" && M[1].value==" ")
{
M[1].value="X";
}
else if(U[2].value=="O" && M[1].value=="O" && L[0].value==" ")
{
L[0].value="X";
}
else if(L[0].value=="O" && M[1].value=="O" && U[2].value==" ")
{
U[2].value="X";
}
else if(U[2].value=="O" && L[0].value=="O" && M[1].value==" ")
{
M[1].value="X";
}
else if(M[2].value==" " && M[1].value=="X" && M[0].value==" ")
{
M[2].value="X";
}
else if(M[0].value=="X" && M[1].value==" " && M[2].value==" ")
{
M[2].value="X";
}
else if(M[2].value=="X" && M[1].value==" " && M[0].value==" ")
{
M[0].value="X";
}
else if(U[2].value==" " && U[1].value=="X" && U[0].value==" ")
{
U[2].value="X";
}
else if(U[0].value=="X" && U[1].value==" " && U[2].value==" ")
{
U[2].value="X";
}
else if(U[2].value=="X" && U[1].value==" " && U[0].value==" ")
{
U[0].value="X";
}
else if(L[2].value==" " && L[1].value=="X" && L[0].value==" ")
{
L[2].value="X";
}
else if(L[0].value=="X" && L[1].value==" " && L[2].value==" ")
{
L[2].value="X";
}
else if(L[2].value=="X" && L[1].value==" " && L[0].value==" ")
{
L[0].value="X";
}
else if(M[0].value=="O" && U[0].value==" " && U[1].value==" " && U[2].value==" " && M[2].value==" " && M[1].value==" " && L[0].value==" " && L[1].value==" " && L[2].value==" ")
{
U[0].value="X";
}
else if(M[2].value=="O" && U[0].value==" " && U[1].value==" " && U[2].value==" " && M[0].value==" " && M[1].value==" " && L[0].value==" " && L[1].value==" " && L[2].value==" ")
{
U[2].value="X";
}
else
{
var Num=RandomWithRange(0,8)
if(Num==0 &&U[0].value==" ")
{
U[0].value="X";
}
else if(Num==1 &&U[1].value==" ")
{
U[1].value="X";
}
else if(Num==2 && U[2].value==" ")
{
U[2].value="X";
}
else if(Num==3 && M[0].value==" ")
{
M[0].value="X";
}
else if(Num==4 && M[1].value==" ")
{
M[1].value="X";
}
else if(Num==5 && M[2].value==" ")
{
M[2].value="X";
}
else if(Num==6 && L[0].value==" ")
{
L[0].value="X";
}
else if(Num==7 && L[1].value==" ")
{
L[1].value="X";
}
else if(Num==8 && L[2].value==" ")
{
L[2].value="X";
}
else
{
if(U[0].value==" ")
{
U[0].value="X";
}
else if(U[1].value==" ")
{
U[1].value="X";
}
else if(U[2].value==" ")
{
U[2].value="X";
}
else if(M[0].value==" ")
{
M[0].value="X";
}
else if(M[1].value==" ")
{
M[1].value="X";
}
else if(M[2].value==" ")
{
M[2].value="X";
}
else if(L[0].value==" ")
{
L[0].value="X";
}
else if(L[1].value==" ")
{
L[1].value="X";
}
else if(L[2].value==" ")
{
L[2].value="X";
}
}
}
Result();
}
function RandomWithRange(Min,Max)
{
return parseInt(Math.random()*(Max-Min)+Min)
}
function Result()
{
if(U[0].value=="X" && U[1].value=="X" && U[2].value=="X")
{
U[0].style.color="#24B73D";
U[1].style.color="#24B73D";
U[2].style.color="#24B73D";
Lose();
}
else if(U[0].value=="O" && U[1].value=="O" && U[2].value=="O")
{
U[0].style.color="#24B73D";
U[1].style.color="#24B73D";
U[2].style.color="#24B73D";
Win();
}
else if(M[0].value=="X" && M[1].value=="X" && M[2].value=="X")
{
M[0].style.color="#24B73D";
M[1].style.color="#24B73D";
M[2].style.color="#24B73D";
Lose();
}
else if(M[0].value=="O" && M[1].value=="O" && M[2].value=="O")
{
M[0].style.color="#24B73D";
M[1].style.color="#24B73D";
M[2].style.color="#24B73D";
Win();
}
else if(L[0].value=="X" && L[1].value=="X" && L[2].value=="X")
{
L[0].style.color="#24B73D";
L[1].style.color="#24B73D";
L[2].style.color="#24B73D";
Lose();
}
else if(L[0].value=="O" && L[1].value=="O" && L[2].value=="O")
{
L[0].style.color="#24B73D";
L[1].style.color="#24B73D";
L[2].style.color="#24B73D";
Win();
}
else if(U[0].value=="X" && M[0].value=="X" && L[0].value=="X")
{
U[0].style.color="#24B73D";
M[0].style.color="#24B73D";
L[0].style.color="#24B73D";
Lose();
}
else if(U[0].value=="O" && M[0].value=="O" && L[0].value=="O")
{
U[0].style.color="#24B73D";
M[0].style.color="#24B73D";
L[0].style.color="#24B73D";
Win();
}
else if(U[1].value=="X" && M[1].value=="X" && L[1].value=="X")
{
U[1].style.color="#24B73D";
M[1].style.color="#24B73D";
L[1].style.color="#24B73D";
Lose();
}
else if(U[1].value=="O" && M[1].value=="O" && L[1].value=="O")
{
U[1].style.color="#24B73D";
M[1].style.color="#24B73D";
L[1].style.color="#24B73D";
Win();
}
else if(U[2].value=="X" && M[2].value=="X" && L[2].value=="X")
{
U[2].style.color="#24B73D";
M[2].style.color="#24B73D";
L[2].style.color="#24B73D";
Lose();
}
else if(U[2].value=="O" && M[2].value=="O" && L[2].value=="O")
{
U[2].style.color="#24B73D";
M[2].style.color="#24B73D";
L[2].style.color="#24B73D";
Win();
}
else if(U[0].value=="X" && M[1].value=="X" && L[2].value=="X")
{
U[0].style.color="#24B73D";
M[1].style.color="#24B73D";
L[2].style.color="#24B73D";
Lose();
}
else if(U[0].value=="O" && M[1].value=="O" && L[2].value=="O")
{
U[0].style.color="#24B73D";
M[1].style.color="#24B73D";
L[2].style.color="#24B73D";
Win();
}
else if(U[2].value=="X" && M[1].value=="X" && L[0].value=="X")
{
U[2].style.color="#24B73D";
M[1].style.color="#24B73D";
L[0].style.color="#24B73D";
Lose();
}
else if(U[2].value=="O" && M[1].value=="O" && L[0].value=="O")
{
U[2].style.color="#24B73D";
M[1].style.color="#24B73D";
L[0].style.color="#24B73D";
Win();
}
else if(!GameOver && U[0].value!=" " && U[1].value!=" " && U[2].value!=" "&& M[0].value!=" " && M[1].value!=" " && M[2].value!=" " && L[0].value!=" " && L[1].value!=" " && L[2].value!=" " )
{
GameOver=true;
document.getElementById("Res").style="color:#05750A;background-color:#F6FAF1;"
document.getElementById("Res").innerHTML="Well tried!<br/>It's a draw!";
Reached=true;
}
}
function Win()
{
GameOver=true;
document.getElementById("Res").innerHTML="Congratulations!<br/>You Won!";
document.getElementById("Res").style="color:#05750A;background-color:#F6FAF1;"
Won++;
Reached=true;
UpdateScore();
}
function Lose()
{
GameOver=true;
document.getElementById("Res").innerHTML="Ooops, Bad Luck!<br/>You Lost!";
document.getElementById("Res").style="background-color:#BF5B5B;color:black;"
Lost++;
Reached=true;
UpdateScore();
}
function Reset()
{
U[0].value=" ";
U[1].value=" ";
U[2].value=" ";
M[0].value=" ";
M[1].value=" ";
M[2].value=" ";
L[0].value=" ";
L[1].value=" ";
L[2].value=" ";
for(var i=0;i<=2;i++)
{
U[i].style.color="white";
M[i].style.color="white";
L[i].style.color="white";
}
GameOver=false;
}
function AnimateReached()
{
if(Reached)
{
var i= document.getElementById("Res");
if(ReachedPos<2 &&!ReachedEver )
{
ReachedPos++;
}
else if(!ReachedEver)
{
n++;
if(n>=80)
{
ReachedEver=true;
}
}
if(ReachedEver)
{
ReachedPos--;
if(ReachedPos==-10)
{
Reached=false;
ReachedEver=false;
n=0;
Reset();
}
}
i.style.top=ReachedPos+'%';
}
}
function UpdateScore()
{
document.getElementById("Score").innerHTML="WON- "+Won+" : " +Lost+" -LOST";
}
setInterval(AnimateReached,20);
</script>
</body>
</html>
5. By Mitali
Made by Mitali. A two player tic tac toe game with restart button. ( Source )
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tic Tac Toe</title>
<link
href="https://fonts.googleapis.com/css2?family=Poppins:[email protected]&family=Raleway:[email protected]&display=swap"
rel="stylesheet"
/>
</head>
<body>
<style>
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
padding: 0;
margin: 0;
font-family: "Raleway", sans-serif;
}
body {
height: 100vh;
background: -o-linear-gradient(315deg, #8052ec, #d161ff);
background: linear-gradient(135deg, #8052ec, #d161ff);
}
html {
font-size: 16px;
}
.box {
padding: 1.5em 0;
position: absolute;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
left: 50%;
top: 50%;
}
.wrapper {
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
.container {
width: 80vmin;
height: 80vmin;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
gap: 2vmin;
}
.button-option {
background-color: #ffffff;
height: 25vmin;
width: 25vmin;
font-size: 12vmin;
border: none;
-webkit-box-shadow: 0 0 15px rgba(0, 0, 0, 0.1);
box-shadow: 0 0 15px rgba(0, 0, 0, 0.1);
border-radius: 8px;
color: #d161ff;
}
#restart {
margin-top: 1em;
padding: 0.7em 0;
background-color: #0a0027;
color: #ffffff;
font-size: 1.3em;
border-radius: 5px;
border: none;
}
.popup.hide {
display: none;
}
.popup {
height: 100vh;
width: 100vw;
position: absolute;
background: -o-linear-gradient(315deg, #8052ec, #d161ff);
background: linear-gradient(135deg, #8052ec, #d161ff);
z-index: 2;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
gap: 1em;
font-size: 12vmin;
}
#new-game {
padding: 0.5em 1em;
background-color: #0a0027;
color: #ffffff;
font-size: 0.6em;
border-radius: 0.2em;
border: none;
}
#message {
color: #ffffff;
text-align: center;
font-size: 1em;
}
a {
font-size: 1.3em;
background-color: #ffffff;
display: block;
text-align: center;
text-decoration: none;
padding: 0.6em 0;
border-radius: 5px;
color: #d161ff;
letter-spacing: 0.05em;
margin-top: 1em;
}
</style>
<div class="box">
<div class="wrapper">
<div class="container">
<button class="button-option"></button>
<button class="button-option"></button>
<button class="button-option"></button>
<button class="button-option"></button>
<button class="button-option"></button>
<button class="button-option"></button>
<button class="button-option"></button>
<button class="button-option"></button>
<button class="button-option"></button>
</div>
<button id="restart">Restart</button>
</div>
<a href="https://youtu.be/al_AgC2NSCo" target="_blank"
>My Youtube Channel</a
>
</div>
<div class="popup hide">
<p id="message"></p>
<button id="new-game">New Game</button>
</div>
<script>
let btnRef = document.querySelectorAll(".button-option");
let popupRef = document.querySelector(".popup");
let newgameBtn = document.getElementById("new-game");
let restartBtn = document.getElementById("restart");
let msgRef = document.getElementById("message");
//Winning Pattern Array
let winningPattern = [
[0, 1, 2],
[0, 3, 6],
[2, 5, 8],
[6, 7, 8],
[3, 4, 5],
[1, 4, 7],
[0, 4, 8],
[2, 4, 6],
];
//Player 'X' plays first
let xTurn = true;
let count = 0;
//Disable All Buttons
const disableButtons = () => {
btnRef.forEach((element) => (element.disabled = true));
//enable popup
popupRef.classList.remove("hide");
};
//Enable all buttons (For New Game and Restart)
const enableButtons = () => {
btnRef.forEach((element) => {
element.innerText = "";
element.disabled = false;
});
//disable popup
popupRef.classList.add("hide");
};
//This function is executed when a player wins
const winFunction = (letter) => {
disableButtons();
if (letter == "X") {
msgRef.innerHTML = "🎉 <br> 'X' Wins";
} else {
msgRef.innerHTML = "🎉 <br> 'O' Wins";
}
};
//Function for draw
const drawFunction = () => {
disableButtons();
msgRef.innerHTML = "😎 <br> It's a Draw";
};
//New Game
newgameBtn.addEventListener("click", () => {
count = 0;
enableButtons();
});
restartBtn.addEventListener("click", () => {
count = 0;
enableButtons();
});
//Win Logic
const winChecker = () => {
//Loop through all win patterns
for (let i of winningPattern) {
let [element1, element2, element3] = [
btnRef[i[0]].innerText,
btnRef[i[1]].innerText,
btnRef[i[2]].innerText,
];
//Check if elements are filled
//If 3 empty elements are same and would give win as would
if (element1 != "" && (element2 != "") & (element3 != "")) {
if (element1 == element2 && element2 == element3) {
//If all 3 buttons have same values then pass the value to winFunction
winFunction(element1);
}
}
}
};
//Display X/O on click
btnRef.forEach((element) => {
element.addEventListener("click", () => {
if (xTurn) {
xTurn = false;
//Display X
element.innerText = "X";
element.disabled = true;
} else {
xTurn = true;
//Display Y
element.innerText = "O";
element.disabled = true;
}
//Increment count on each click
count += 1;
if (count == 9) {
drawFunction();
}
//Check for win on every click
winChecker();
});
});
//Enable Buttons and disable popup on page load
window.onload = enableButtons;
</script>
</body>
</html>
6. By 👑 Prometheus 🇸🇬
Made by 👑 Prometheus 🇸🇬. ( Source )
<!DOCTYPE html>
<html>
<head>
<title>Tic Tac Toe</title>
</head>
<body style="background:linear-gradient(100deg,black,grey,white)">
<style>
#board{
position:absolute;
height:256px;
width:250px;
top:20px;
left:40px;
border:2px solid;
background-color:#e3e3e3;
}
.cell{
position:absolute;
height:70px;
width:70px;
background-color:white;
border:4px solid;
}
.row{
position:relative;
height:70px;
width:70px;
margin-top:10px;
}
.c1{
left:6px;
}
.c2{
left:86px;
}
.c3{
left:166px;
}
#c3{
background-color:blue;
}
button{
background:linear-gradient(135deg, red,orange,yellow);
color:grey;
}
</style>
<div id="board">
<div class="row">
<div onclick="tap(this)" class="cell c1" id="c1"></div>
<div onclick="tap(this)" class="cell c2" id="c2"></div>
<div onclick="tap(this)" class="cell c3" id="c3"></div>
</div>
<div class="row">
<div onclick="tap(this)" class="cell c1" id="c4"></div>
<div onclick="tap(this)" class="cell c2" id="c5"></div>
<div onclick="tap(this)" class="cell c3" id="c6"></div>
</div>
<div class="row">
<div onclick="tap(this)" class="cell c1" id="c7"></div>
<div onclick="tap(this)" class="cell c2" id="c8"></div>
<div onclick="tap(this)" class="cell c3" id="c9"></div>
</div>
</div>
<button style="position:absolute;top:300px;left:128px;font-size:20px" onclick="startagain()">Restart</button>
<button style="position:absolute;top:330px;left:128px;font-size:21px;" onclick="inform()">Details</button>
<script>
var aiselected=[3];
var plselected=new Array();
var wins=[[1,2,3],[4,5,6],[7,8,9],[1,4,7],[2,5,8],[3,6,9],[1,5,9],[3,5,7]];
function startagain(){
for (let m of document.getElementsByClassName("cell")){
if (m.id!='c3'){
m.style.backgroundColor='white';
}
}
aiselected=[3]
plselected=[];
}
function inform(){
alert("This is my first ever attempt at making a web game. I made this tic-tac-toe game with a lot of fixed variables, mainly the AI always starts and is always choosing the top right corner square.")
}
function add(no){
aiselected.push(no);
return no;
}
function won(arr){
for (let x of wins){
if (x.every(p=>arr.includes(p))){
return true;
}
}
return false;
}
function tap(a){
if ((aiselected+plselected).includes(+a.id[1])){
return;
}
a.style.backgroundColor='red';
plselected+=+(a.id[1]);
let res=ai();
document.getElementById('c'+res).style.backgroundColor='blue';
if (won(aiselected)){
alert("The AI won!");
}
else if (won(plselected)){
alert("It can't be... You won my AI!");
}
else if((aiselected.length+ plselected.length)==9){
alert("Good game! It was a draw!");
}
}
function ai(){
used=aiselected+plselected;
if (aiselected.toString()=="3"){
move1=plselected[0]
if (move1==6 || move1==9){
return add(1);
}
return add(9);
}
if (aiselected.toString()=="3,1"){
if (!plselected.includes(2)){
return add(2);
}
else if (!plselected.includes(7)){
return add(7);
}
}
else if (aiselected.toString()== "3,1,7"){
if (!plselected.includes(4)){
return add(4);
}
if (!plselected.includes(5)){
return add(5);
}
}
if (aiselected.toString()=="3,9"){
if (!plselected.includes(6)){
return add(6);
}
if (plselected.includes(1)){
return add(7);
}
if (plselected.includes(7)){
return add(1);
}
if (plselected.toString()=="46"){
return add(5);
}
if (plselected.toString()=="56"){
return add(4);
}
if (plselected.includes(2)||plselected.includes(8)){
return add(5);
}
}
if (aiselected.toString()=="3,9,5"){
if (!plselected.includes(1)){
return add(1);
}
return add(7);
}
if (aiselected.toString()=="3,9,4"){
if (plselected.includes(2)){
return add(8);
}
return add(2);
}
if (aiselected.toString()=="3,9,4,2"){
if (plselected.includes(1)){
return add(7);
}
return add(1);
}
if (aiselected.toString()=="3,9,4,8"){
if (plselected.includes(7)){
return add(1);
}
return add(7);
}
if (aiselected.toString()=="3,9,7"){
if (plselected.includes(8)){
return add(5);
}
return add(8);
}
if (aiselected.toString()=="3,9,1"){
if (plselected.includes(2)){
return add(5);
}
return add(2);
}
}
function type(a){
//-1 if edge
//0 if centre
//1 if corner
if (+(a)==5)return 0;
if (+(a)%2==1)return 1;
return -1
}
</script>
</body>
</html>
7. By Anuran Pal
Made by Anuran Pal. The game lets you choose whether you want to use the first move or let the AI do it, and also lets you choose the symbol you want. It also uses a little bit of animation. ( Source )
<!DOCTYPE html>
<html>
<head>
<title>Tic Tac Toe in htmlcanvas</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" type="text/javascript"></script>
</head>
<body>
<style>
@import url('https://fonts.googleapis.com/css2?family=Balsamiq+Sans:[email protected]&family=Potta+One&display=swap');
html{
font-family: 'Balsamiq Sans', cursive;
font-weight: 800;
}
h1, h2{
text-transform: uppercase;
background: -webkit-linear-gradient(#e60000, #ff0000,#ff6600);;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
h1{
line-height: 40px;
font-size:40px;
}
h2 {
line-height: 25px;
font-size:25px;
}
.width-medium{
max-width:250px;
}
.align-center {
text-align: center;
}
.flex-center{
display:flex;
justify-content:center;
align-items: center;
}
.flex-space-around{
justify-content:space-around!important;
}
.flex-column{
flex-direction:column;
}
.margin {
margin: 20px;
}
.margin-small{
margin:12px;
}
.margin-left-small{
margin-left:2px;
}
.no-margin-bottom{
margin-bottom:0px!important
}
.no-margin-horizontal{
margin-left:0px!important;
margin-right:0px!important;
}
.margin-auto {
margin: auto;
}
button {
display:flex;
align-items:center;
justify-content:center;
font-family: inherit;
box-shadow:1px 2px #919191;
background-image: linear-gradient(to right, #a6a6a6, #c7c3c3, #e0dcdc, #ebe8e8);
font-weight: 800;
border: 0px;
height: 40px;
width:115px;
padding: 5px;
border-radius: 20px;
letter-spacing: 1.5px;
font-size: 18px;
text-align: center;
cursor: pointer;
outline: none;
text-transform: uppercase;
}
button:hover{
background-image: linear-gradient(to right, #a6a6a6, #c7c3c3, #e0dcdc, #cccccc);
}
button:hover > svg circle{
stroke: blue;
}
button:hover > svg path{
fill: red;
}
button svg{
margin-right:5px;
}
.symbol{
cursor: pointer;
}
.symbol:hover{
background-color:#F0F0F0;
border-radius:6px;
}
.symbol.active{
background-color:#cccccc;
border-radius:6px;
}
.checkbox{
-webkit-appearance: none;
-moz-appearance: none;
display: inline-block;
height:16px;
width:16px;
margin-bottom:-1px;
background: white;
border: 2px solid red;
border-radius: 4px;
cursor: pointer;
outline: 0;
}
.checkbox:checked{
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='15' width='15'%3E%3Cpath d='M2 5 L5 10 L10 3' stroke='blue' stroke-width='2' stroke-linecap='round' fill='none' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
}
</style>
<div id="divUserInputs" class="align-center">
<div class="align-center width-medium margin-auto">
<h1>Choose</h1>
<div class="flex-center flex-space-around">
<svg id="1" height="70" width="70" class="symbol active">
<circle cx="35" cy="35" r="24" stroke="blue" stroke-width="10" fill="none" />
</svg>
<h2> OR </h2>
<svg id="2" height="70" width="70" class="symbol">
<line x1="13" y1="13" x2="57" y2="57" stroke="blue" stroke-width="10" stroke-linecap="round" />
<line x1="57" y1="13" x2="13" y2="57" stroke="blue" stroke-width="10" stroke-linecap="round" />
</svg>
</div>
<div class="flex-center flex-column">
<div class="margin no-margin-horizontal no-margin-bottom">
<input id="checkFirstMove" type="checkbox" class="checkbox" checked /><span class="margin-left-small">Check to make the first move</span>
</div>
<button id="btnPlay" class="margin-small">
<svg height="24" width="24">
<circle cx="12" cy="12" r="10" stroke-width="3" fill="none" stroke="red" />
<path d="M8 6 L19 12 L8 18 Z" fill="blue" />
</svg>
Play
</button>
</div>
</div>
</div>
<div id="tic-tac-toe-board" class="align-center">
</div>
<div id="win" class="align-center" style="position:relative;display:none;">
<canvas id="burst" height="300" width="300"></canvas>
<div style="background-color:rgba(255,255,255,0.7);position:absolute;top:50%;left:50%;transform: translate(-50%,-50%);padding:5px;">
<h1>You won..</h1>
</div>
</div>
<div id="loss" class="align-center" style="position:relative;display:none;">
<div style="background-color:rgba(255,255,255,0.7);">
<h1>Better luck next time..</h1>
</div>
</div>
<div id="draw" class="align-center" style="position:relative;display:none;">
<div style="background-color:rgba(255,255,255,0.7);">
<h1>Well tried! It's a draw..</h1>
</div>
</div>
<script>
const SYMBOL = {
CIRCLE: 1,
CROSS: 2
};
var Symbol = (function () {
var _default = {
size: 24,
color: "blue",
strokeWidth: 4
};
var _symbol = function (type, options) {
if (!type) throw new Error("type of Symbol must be defined.");
this.type = type;
this.options = $.extend({}, _default, options);
};
_symbol.prototype.getSize = function () {
return this.options.size;
};
_symbol.prototype.create = function () {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var size = this.options.size,
color = this.options.color,
lineWidth = this.options.strokeWidth;
// Set actual size in memory (scaled to account for extra pixel density).
var scale = window.devicePixelRatio; // <--- Change to 1 on retina screens to see blurry canvas.
canvas.width = size * scale;
canvas.height = size * scale;
canvas.height = canvas.width = size;
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
switch (this.type) {
case SYMBOL.CIRCLE:
var offset = 4;
center = [size / 2, size / 2],
radius = size / 2 - lineWidth / 2 - offset;
console.log(center + "," + radius);
ctx.beginPath();
ctx.arc(center[0], center[1], radius, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
break;
case SYMBOL.CROSS:
var offset = 12;
ctx.lineCap = "round";
ctx.beginPath();
ctx.moveTo(offset, offset);
ctx.lineTo(size - offset, size - offset);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.moveTo(size - offset, offset);
ctx.lineTo(offset, size - offset);
ctx.stroke();
ctx.closePath();
break;
}
return canvas;
};
return _symbol;
})();
var Evented = {
on: function (eventName, callback, domElement) {
$(domElement || this).on(eventName, callback);
},
off: function (eventName, callback, domElement) {
$(domElement || this).off(eventName, callback);
},
trigger: function (eventName, params, domElement) {
$(domElement || this).trigger(eventName, params);
}
}
var Cell = (function () {
var id = 0;
var _cell = function (options, playBoard) {
if (!(playBoard instanceof PlayBoard)) {
throw new Error("PlayBoard must be initialized.");
}
var startPos = this.startPos = options.startPos; // top-left corner
var size = this.size = options.size;
var strokeWidth = this.strokeWidth = options.strokeWidth;
var endPos = [startPos[0] + size[0], startPos[1] + size[1]]; // bottom-right corner
this.id = ++id;
this.playBoard = playBoard;
this.isEmpty = true;
var playBoardSize = playBoard.getSize();
this._bounds = {
topLeft: startPos,
bottomRight: endPos
};
var drawBounds = this._drawBounds = {
topLeft: [(startPos[0] !== 0 ? (startPos[0] + strokeWidth / 2) : startPos[0]), (startPos[1] !== 0 ? (startPos[1] + strokeWidth / 2) : startPos[1])],
bottomRight: [(Math.floor(playBoardSize[0] - endPos[0]) !== 0 ? (endPos[0] - strokeWidth / 2) : endPos[0]), (Math.floor(playBoardSize[1] - endPos[1]) !== 0 ? (endPos[1] - strokeWidth / 2) : endPos[1])]
};
this.center = [(drawBounds.topLeft[0] + drawBounds.bottomRight[0]) / 2, (drawBounds.topLeft[1] + drawBounds.bottomRight[1]) / 2];
};
$.extend(_cell.prototype, Evented);
var _onMouseOver = function () {
var canvas = this.playBoard.getContainer();
var ctx = this.playBoard.getCtx();
canvas.style.cursor = "pointer";
var startPos = this._drawBounds.topLeft;
var width = this._drawBounds.bottomRight[0] - startPos[0];
var height = this._drawBounds.bottomRight[1] - startPos[1];
ctx.fillStyle = "#F0F0F0";
ctx.fillRect(startPos[0], startPos[1], width, height);
};
var _onMouseOut = function () {
var canvas = this.playBoard.getContainer();
var ctx = this.playBoard.getCtx();
canvas.style.cursor = "default";
var startPos = this._drawBounds.topLeft;
var width = this._drawBounds.bottomRight[0] - startPos[0];
var height = this._drawBounds.bottomRight[1] - startPos[1];
ctx.clearRect(startPos[0], startPos[1], width, height);
};
_cell.prototype.contains = function (point) {
var topLeft = this._drawBounds.topLeft;
var bottomRight = this._drawBounds.bottomRight;
var containsAlongX = point[0] >= topLeft[0] && point[0] <= bottomRight[0];
var containsAlongY = point[1] >= topLeft[1] && point[1] <= bottomRight[1];
return containsAlongX && containsAlongY;
};
_cell.prototype.attachListeners = function () {
this.on("mouseover", _onMouseOver.bind(this));
this.on("mouseout", _onMouseOut.bind(this));
};
_cell.prototype.removeListeners = function () {
this.off("mouseover");
this.off("mouseout");
};
_cell.prototype.drawSymbol = function (type) {
if (!this.isEmpty)
return;
var bounds = this._drawBounds;
var symbol = new Symbol(type, {
size: Math.min(bounds.bottomRight[0] - bounds.topLeft[0], bounds.bottomRight[1] - bounds.topLeft[1]),
strokeWidth: 8
});
var image = symbol.create();
var ctx = this.playBoard.getCtx();
ctx.clearRect(bounds.topLeft[0], bounds.topLeft[1], bounds.bottomRight[0] - bounds.topLeft[0], bounds.bottomRight[1] - bounds.topLeft[1]);
ctx.drawImage(image, bounds.topLeft[0], bounds.topLeft[1], image.width, image.height);
this.isEmpty = false;
this.symbol = symbol;
if (this.playBoard.lastHoveredCell === this)
this.playBoard.lastHoveredCell = null;
}
return _cell;
}());
var PlayBoard = (function () {
var _defaultOptions = {
width: 300,
height: 300,
style: {
color: "red",
strokeWidth: 8
}
};
var _playBoard = function (options) {
this._cells = [];
this.options = $.extend({}, _defaultOptions, options);
this._container = document.createElement("canvas");
this._container.height = this.options.height;
this._container.width = this.options.width;
this._ctx = this._container.getContext("2d");
this.style = this.options.style;
this._interactiveLayer = this._container;
_buildReferences.call(this);
this.attachListeners();
};
$.extend(_playBoard.prototype, Evented);
var _buildReferences = function () {
var rows = this.rows = [];
var columns = this.columns = [];
var diagonals = this.diagonals = [[], []];
var cellWidth = this.options.width / 3;
var cellHeight = this.options.height / 3;
for (var i = 0, i1=0; i < this._container.height; i += cellHeight, i1++) {
row = rows[rows.length] = [];
for (var j = 0, j1=0 ; j < this._container.width; j += cellWidth, j1++) {
if (i1 === 0) {
columns[j1] = [];
}
var options = {
startPos: [j, i],
size: [cellWidth, cellHeight],
strokeWidth: this.style.strokeWidth
};
cell = new Cell(options, this)
this._cells.push(cell);
row.push(cell);
columns[j1].push(cell);
if (i1 === j1) {
diagonals[0].push(cell);
}
if (i1 + j1 == 2)
diagonals[1].push(cell);
}
}
};
var _onMouseMove = function (event) {
var dimension = this._container.getBoundingClientRect();
var pos = [event.clientX - dimension.left, event.clientY - dimension.top];
var cell = null;
for (var i = 0, iL = this._cells.length; i < iL; i++) {
if (this._cells[i].contains(pos)) {
cell = this._cells[i];
break;
}
}
if (cell) {
if (!cell.isEmpty) {
this.lastHoveredCell = null;
return;
}
if (this.lastHoveredCell == cell)
return;
else {
if (this.lastHoveredCell)
this.lastHoveredCell.trigger("mouseout");
this.lastHoveredCell = cell;
cell.trigger("mouseover");
}
} else {
if (this.lastHoveredCell)
this.lastHoveredCell.trigger("mouseout");
this.lastHoveredCell = null;
}
return cell;
};
var _onClick = function (event) {
var dimension = this._container.getBoundingClientRect();
var pos = [event.clientX - dimension.left, event.clientY - dimension.top];
var cell = null;
for (var i = 0, iL = this._cells.length; i < iL; i++) {
if (this._cells[i].contains(pos)) {
cell = this._cells[i];
break;
}
}
if (cell) {
if (!cell.isEmpty)
return;
else
this.trigger("click", [cell]);
}
};
_playBoard.prototype.draw = function (container) {
var d = $.Deferred();
var _draw = function () {
var canvas = this._container;
var ctx = this._ctx;
var cellWidth = this.options.width / 3;
var cellHeight = this.options.height / 3;
var h = canvas.height,
w = canvas.width;
// draw squared blocks
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = this.style.color;
ctx.lineWidth = this.style.strokeWidth;
ctx.lineCap = "round";
for (var i = cellWidth, j = cellHeight; i < canvas.width && j < canvas.height; i += cellWidth, j += cellHeight) {
// draw vertical line
ctx.beginPath();
ctx.moveTo(i, 0);
ctx.lineTo(i, h);
ctx.stroke();
ctx.closePath();
// draw horizontal line
ctx.beginPath();
ctx.moveTo(0, j);
ctx.lineTo(w, j);
ctx.stroke();
ctx.closePath();
}
$(container).append(canvas);
d.resolve();
}.bind(this);
setTimeout(_draw, 0);
return d.promise();
};
_playBoard.prototype.getSize = function () {
return [this.options.width, this.options.height];
};
_playBoard.prototype.getContainer = function () {
return this._container;
}
_playBoard.prototype.getCtx = function () {
return this._ctx;
}
_playBoard.prototype.attachListeners = function () {
this._cells.forEach(function (cell) {
cell.attachListeners();
});
this.on("mousemove", _onMouseMove.bind(this), this._interactiveLayer);
this.on("click", _onClick.bind(this), this._interactiveLayer);
};
_playBoard.prototype.removeListeners = function () {
this._cells.forEach(function (cell) {
cell.removeListeners();
});
this.off("mousemove");
this.off("click");
};
_playBoard.prototype.getEmptyCells = function () {
return this._cells.filter(function (cell) { return cell.isEmpty; })
}
return _playBoard;
}())
var User = (function () {
var _user = function (chosenSymbolType, playboard, userName, autoPlay) {
if (!chosenSymbolType)
throw new Error("User must have a symbol.");
if (!playboard)
throw new Error("User needs a playboard.")
this.chosenSymbolType = chosenSymbolType;
this.playBoard = playboard;
this.autoPlay = !!autoPlay;
this.userName = userName || 'User';
this.cellsVisited = [];
};
var _getRandomInt = function (min, max) {
return min + Math.floor((max - min) * Math.random());
}
var _animate = function (cells) {
var d = $.Deferred();
var x1 = cells[0].center[0],
y1 = cells[0].center[1],
x0 = x1,
y0= y1,
x2 = cells[cells.length - 1].center[0],
y2 = cells[cells.length - 1].center[1];
var ctx = this.playBoard.getCtx();
var gradient = ctx.createLinearGradient(0, 0, 300, 0);
var _self = this;
// Add three color stops
gradient.addColorStop(0, 'red');
gradient.addColorStop(0.5, 'orange');
gradient.addColorStop(1, 'blue');
var fragmentSizeX = (x2 - x1) / 100;
var fragmentSizeY = (y2 - y1) / 100;
x2 = fragmentSizeX * 100 + x1;
y2 = fragmentSizeY * 100 + y1;
ctx.lineWidth = 10;
ctx.strokeStyle = gradient;
ctx.lineCap = "round";
ctx.globalAlpha = 0.5;
var _draw = function () {
var x3 = x1 + fragmentSizeX;
var y3 = y1 + fragmentSizeY;
ctx.moveTo(x1, y1);
ctx.beginPath();
ctx.lineTo(x3, y3);
ctx.stroke();
x1 = x3;
y1 = y3;
if (Math.abs(x1 - x2) > Math.abs(fragmentSizeX) || Math.abs(y1 - y2) > Math.abs(fragmentSizeY))
requestAnimationFrame(_draw);
else {
d.resolve();
}
}
requestAnimationFrame(_draw);
return d.promise();
};
_user.prototype.getSuggestion = function () {
var rows = this.playBoard.rows,
columns = this.playBoard.columns,
diagonals = this.playBoard.diagonals,
symbol = this.chosenSymbolType,
matched = [],
attentionRequired = [];
alternateSuggestions=[];
// Check for row match
for (var i = 0, iL = rows.length, row, opponentSymbols; i < iL; i++) {
row = rows[i];
matched = [];
emptyCells = [];
opponentSymbols = [];
for (var c = 0, cL = row.length; c < cL; c++) {
if (row[c].symbol) {
if (row[c].symbol.type == symbol)
matched.push(row[c]);
else
opponentSymbols.push(row[c]);
}
if (row[c].isEmpty)
emptyCells.push(row[c]);
}
if (matched.length === 2 && emptyCells.length == 1) {
return row.find(function (cell) { return cell.isEmpty; });
}
if (matched.length == 1 && emptyCells.length == 2) {
emptyCells.forEach(function (cell) { alternateSuggestions.push(cell); });
}
if (opponentSymbols.length == 2 && emptyCells.length == 1) {
attentionRequired.push(emptyCells[0]);
}
}
// Check for column match
for (var j = 0, jL = columns.length, column, opponentSymbols; j < jL; j++) {
column = columns[j];
matched = [];
emptyCells = [];
opponentSymbols = [];
for (var c = 0, cL = column.length; c < cL; c++) {
if (column[c].symbol) {
if (column[c].symbol.type == symbol)
matched.push(column[c]);
else
opponentSymbols.push(column[c]);
}
if (column[c].isEmpty)
emptyCells.push(column[c]);
}
if (matched.length === 2 && emptyCells.length == 1) {
return column.find(function (cell) { return cell.isEmpty; });
}
if (matched.length == 1 && emptyCells.length == 2) {
emptyCells.forEach(function (cell) { alternateSuggestions.push(cell); });
}
if (opponentSymbols.length == 2 && emptyCells.length == 1) {
attentionRequired.push(emptyCells[0]);
}
}
// Check for diagonal match
for (var k = 0, kL = diagonals.length, diagonal, opponentSymbols; k < kL; k++) {
diagonal = diagonals[k];
matched = [];
emptyCells = [];
opponentSymbols = [];
for (var c = 0, cL = diagonal.length; c < cL; c++) {
if (diagonal[c].symbol) {
if (diagonal[c].symbol.type == symbol)
matched.push(diagonal[c]);
else
opponentSymbols.push(diagonal[c]);
}
if (diagonal[c].isEmpty)
emptyCells.push(diagonal[c]);
}
if (matched.length === 2 && emptyCells.length == 1)
return diagonal.find(function (cell) { return cell.isEmpty; });
if (matched.length == 1 && emptyCells.length == 2) {
emptyCells.forEach(function (cell) { alternateSuggestions.push(cell); });
}
if (opponentSymbols.length == 2 && emptyCells.length == 1) {
attentionRequired.push(emptyCells[0]);
}
}
var hardLevel = 0.96;
if (attentionRequired.length == 2) {
return attentionRequired[_getRandomInt(0, attentionRequired.length - 1)];
}
var random = Math.random();
if (attentionRequired.length && random < hardLevel) {
return attentionRequired[_getRandomInt(0, attentionRequired.length - 1)];
}
if (alternateSuggestions.length)
return alternateSuggestions[_getRandomInt(0, alternateSuggestions.length - 1)];
return null;
};
_user.prototype.playMove = function (event, cell) {
if (this.autoPlay) {
var emptyCells = this.playBoard.getEmptyCells();
if (emptyCells.length) {
if (this.cellsVisited.length >= 1)
cell = this.getSuggestion();
if (!cell) {
var nextMove = _getRandomInt(0, emptyCells.length - 1);
cell = emptyCells[nextMove];
}
}
}
if (cell) {
this.playBoard.off("click");
this.playBoard.removeListeners();
cell.drawSymbol(this.chosenSymbolType);
this.cellsVisited.push(cell);
var _rs = this.getResult();
if (_rs) {
var _reset = function () {
$("#tic-tac-toe-board").empty();
$("#loss,#win,#draw").hide();
$("#divUserInputs").show();
};
if (_rs.result === "win") {
_animate.call(this, _rs.pattern).done(function () {
var _self = this;
if (_self.userName == "You") {
$("#tic-tac-toe-board").empty();
$("#win").show();
setTimeout(_reset, 3000);
} else {
$("#loss").show();
setTimeout(_reset, 1000);
}
}.bind(this));
}
else {
$("#draw").show();
setTimeout(_reset, 1000);
}
return;
}
var opponent = this.opponent;
if (opponent) {
if (opponent.autoPlay) {
setTimeout(function () {
opponent.playMove();
}, 300);
} else {
this.playBoard.attachListeners();
this.playBoard.on("click", opponent.playMove.bind(opponent));
}
}
}
};
_user.prototype.getResult = function () {
var rows = this.playBoard.rows,
columns = this.playBoard.columns,
diagonals = this.playBoard.diagonals,
symbol = this.chosenSymbolType,
matched = false;
var emptyCells = this.playBoard.getEmptyCells();
if (emptyCells.length === 0) {
return {
result: "draw",
};
}
// Check for row match
for (var i = 0, iL = rows.length, row; i < iL; i++) {
row = rows[i];
matched = true;
for (var c = 0, cL = row.length; c < cL; c++) {
if ((!row[c].symbol) || (row[c].symbol.type !== symbol)) {
matched = false;
break;
}
}
if (matched === true) {
return {
result: "win",
pattern: row
};
}
}
// Check for column match
for (var j = 0, jL = columns.length, column; j < jL; j++) {
column = columns[j];
matched = true;
for (var c = 0, cL = column.length; c < cL; c++) {
if ((!column[c].symbol) || (column[c].symbol.type !== symbol)) {
matched = false;
break;
}
}
if (matched === true) {
return {
result: "win",
pattern: column
};
}
}
// Check for diagonal match
for (var k = 0, kL = diagonals.length, diagonal; k < kL; k++) {
diagonal = diagonals[k];
matched = true;
for (var c = 0, cL = diagonal.length; c < cL; c++) {
if ((!diagonal[c].symbol) || (diagonal[c].symbol.type !== symbol)) {
matched = false;
break;
}
}
if (matched === true) {
return {
result: "win",
pattern: diagonal
};
}
}
return null;
};
_user.prototype.setOpponent = function (opponent) {
if (!(opponent instanceof User)) {
throw new Error("Opponent must be a instance of User Class");
}
this.opponent = opponent;
};
return _user;
}())
$(function () {
var $divUserInputs = $("#divUserInputs");
var symbols = $(".symbol");
symbols.click(function () {
if (!$(this).hasClass("active")) {
symbols.removeClass("active");
$(this).addClass("active");
}
});
var playButton = $("#btnPlay");
var $playboardContainer = $("#tic-tac-toe-board");
var $checkFirstMove = $("#checkFirstMove");
playButton.click(function () {
var chosenSymbol = symbols.filter(function () {
return $(this).hasClass("active");
}).attr("id");
var hasCheckedFirstMove = $checkFirstMove.is(":checked");
$divUserInputs.hide();
var playBoard = new PlayBoard();
var user = new User(+chosenSymbol, playBoard, "You");
var computer = new User((chosenSymbol % 2) + 1, playBoard, "computer", true);
user.setOpponent(computer);
computer.setOpponent(user);
playBoard.draw($playboardContainer).done(function () {
if (!hasCheckedFirstMove)
setTimeout(computer.playMove.bind(computer), 500);
else
playBoard.on("click", user.playMove.bind(user));
});
});
function getColor() {
var colors = ["red", "green", "blue", "yellow", "chartreuse", "CornflowerBlue", "Crimson", "DarkMagenta", "ForestGreen", "Gold", "LawnGreen", "OrangeRed", "Turquoise", "Violet"];
var idx = Math.random() * (colors.length - 1);
return colors[Math.floor(idx)];
}
var canvas = document.getElementById("burst");
var ctx = canvas.getContext("2d");
var Circle = function (cx, cy, r, color, life) {
this.cx = cx;
this.cy = cy;
this.radius = r;
this.color = color || getColor();
this.life = life || 100;
this.update = function () {
if (this.life > 0) {
this.life -= 10;
} else {
this.cx = Math.random() * canvas.width;
this.cy = Math.random() * canvas.height;
this.life = 100;
this.color = getColor();
}
}
this.draw = function () {
ctx.fillStyle = this.color;
ctx.globalAlpha = this.life / 100;
ctx.beginPath();
ctx.arc(this.cx, this.cy, this.radius, 0, 2 * Math.PI);
ctx.fill();
ctx.globalAlpha = 1;
}
}
var circles = [];
for (var i = 0; i < 500; i++) {
var posX = Math.random() * canvas.width;
var posY = Math.random() * canvas.height;
var radius = Math.random() * 5;
var color = getColor();
var life = Math.random() * 100;
circles.push(new Circle(posX, posY, radius, color, life));
}
var _burst = function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0, iL = circles.length; i < iL; i++) {
circles[i].draw();
circles[i].update();
}
requestAnimationFrame(_burst);
}
requestAnimationFrame(_burst);
});
</script>
</body>
</html>
8. By Dapper Mink
Made by Dapper Mink. This is a JavaScript Tic Tac Toe game made using the minimax algorithm. The AI automatically checks all the possibilities of the game and, therefore cannot loose! Good luck :^. ( Source )
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-color: #333;
font-size: 40px;
color: #FFF;
}
table {
border-collapse: collapse;
}
td {
border: 1px solid #000;
width: 100px;
height: 100px;
background-color: #FFF;
font-size: 40px;
font-family: Monospace;
text-align: center;
color: #000;
}
button {
padding: 5px 15px;
background: #0C9;
color: #FFF;
border: 0px none;
-webkit-border-radius: 5px;
border-radius: 5px;
margin: 5px;
font-family: Arial;
}
</style>
<title>Tic Tac Toe</title>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>
</head>
<body>
<script>
alert("This is a Tic Tac Toe game using the minimax algorithm.\nThe AI automatically checks all the possibilities of the game and, therefore cannot loose!\n\nGood luck :^)");
$(function(){
var game, gameEnd;
var win = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]];
var startGame = function(){
game = [];
gameEnd = false;
document.body.innerHTML = '';
var table = $('<table>');
for(var i = 0; i < 3; i++){
var tr = $('<tr>');
for(var j = 0; j < 3; j++){
game.push('');
var td = $('<td>').click(function(){
if(this.innerHTML == '' && !gameEnd){
play($('td').index(this),'o');
}
});
$(tr).append(td);
}
$(table).append(tr);
}
$('body').append(table);
}
var play = function(which,what){
$($('td')[which]).text(what);
game[which] = what;
if(checkEnd(game)[0]){
var p = $('<p>').text((checkEnd(game)[1] == 1) ? 'Tie! ' : 'You lost! ');
var but = $('<button>').text('Restart');
$(but).click(startGame);
$('body').append(p.append(but));
gameEnd = true;
}
if(what == 'o' && !gameEnd){
var allCases = minimax(game,0);
play(allCases.indexOf(allCases.filter(function(n){return n != undefined;}).reduce(function(a,b){return Math.max(a,b);})),'x');
}
}
var checkEnd = function(a){
var signs = ['o','x'];
for(var j in signs){
for(var i in win){
if(a[win[i][0]] == signs[j] && a[win[i][1]] == signs[j] && a[win[i][2]] == signs[j]){
return [true,2*j];
}
}
}
return [a.every(function(e){return e != ''}),1];
}
var minimax = function(g,turn){
var arr = [];
for(var k in g){
if(new Set(arr).has([2,0][turn])){
break;
}else if(g[k] == ''){
var g2 = g.slice();
g2[k] = ['x','o'][turn];
if(checkEnd(g2)[0]){
arr.push(checkEnd(g2)[1]);
}else{
arr.push(minimax(g2,[1,0][turn]).filter(function(n){return n != undefined;}).reduce(function(a,b){return ([1,0][turn]) ? Math.min(a,b) : Math.max(a,b);}));
}
continue;
}
arr.push(undefined);
}
return arr;
}
startGame();
});
</script>
</body>
</html>
9. By Richard Myatt
Made by Richard Myatt. A game of tic tac toe. The main web application uses Vue.js and the game logic is a combination of strategy
presented in the Wikipedia article https://en.wikipedia.org/wiki/Tic-tac-toe and an implementation of the minimax algorithm. ( Source )
<!--
Made: 9 April 2018
Revised: 5 July 2018
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Tic Tac Toe</title>
<style>
@import url('https://fonts.googleapis.com/css?family=Indie+Flower');
@import url('https://fonts.googleapis.com/css?family=Indie+Flower');
* {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
background-color: #eee;
}
.title {
font-family: 'Indie Flower', cursive;
font-size: 1.5vw;
text-align: center;
width: 28vw;
padding: 0.1vw;
color: #6b6d85;
margin: 2vw auto;
}
#app {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
width: 28vw;
height: 30vw;
background-color: lightyellow;
border-radius: 1vw;
margin: 2.5vw auto;
-webkit-box-shadow: -5px -5px 10px rgba(0, 0, 0, 0.4) inset,
5px 5px 10px rgba(0, 0, 0, 0.1) inset,
5px 5px 20px rgba(0, 0, 0, 0.7);
box-shadow: -5px -5px 10px rgba(0, 0, 0, 0.4) inset,
5px 5px 10px rgba(0, 0, 0, 0.1) inset,
5px 5px 20px rgba(0, 0, 0, 0.7);
}
.top-panel {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
font-size: 1vw;
}
.bottom-panel {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
font-size: 1em;
}
.player-one, .player-two {
padding-bottom: 0.5em;
}
.player-one {
margin-left: 20px;
}
.player-two {
margin-right: 20px;
}
.green-one, .green-two {
border-bottom: 4px solid green;
}
.top-panel, .bottom-panel {
width: 24vw;
height: 3vw;
}
.game {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
width: 24vw;
height: 24vw;
color: #fff;
font-family: 'Indie Flower', cursive;
background: -webkit-radial-gradient(#6b6d85, #373d2d);
background: -o-radial-gradient(#6b6d85, #373d2d);
background: radial-gradient(#6b6d85, #373d2d);
-webkit-box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.7) inset;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.7) inset;
}
.board {
display: -ms-grid;
display: grid;
-ms-grid-columns: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
-ms-grid-rows: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
width:inherit;
height: inherit;
}
.square {
font-size: 4vw;
font-weight: bold;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
border: 2px solid #fff;
}
.green {
color: green;
}
.game h2 {
font-size: 2vw;
}
.game p {
font-size: 1vw;
}
.wording {
text-align: center;
padding: 2vw;
}
.btns {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-pack:distribute;
justify-content:space-around;
padding: 1.5vw 3vw 0 3vw;
}
button {
background-color: orange;
border-radius: 50%;
color: #fff;
font-size: 1.2em;
padding: 0.5em;
border-radius: 50%;
}
.reset, .again {
width: 7.8vw;
font-size: 1vw;
padding: 0.3em;
color: #000;
background-color: lightblue;
}
.reset {
margin-right: 20px;
}
.again {
margin-left: 20px;
}
/* custom alert box */
.alert-container {
position: fixed;
top: 40%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;
font-size: 20px;
width: 320px;
height: auto;
margin: 0px auto;
padding: 10px 20px 5px 20px;
-webkit-box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
-webkit-transition: all .3s ease;
-o-transition: all .3s ease;
transition: all .3s ease;
border-radius: 20px;
background-color: lightyellow;
border: 2px solid black;
}
.alert-footer {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: end;
-ms-flex-pack: end;
justify-content: flex-end;
}
.alert-default-button {
font-size: 0.8em;
color: #000;
background-color: lightblue;
border-radius: 50%;
padding: 10px;
margin: 10px;
}
#show-alert {
font-size: 20px;
padding: 10px;
border-radius: 10px;
background-color: orange;
}
.alert-header {
font-size: 20px;
font-family: 'Indie Flower', cursive;
color: #6b6d85;
}
@media only screen and (max-width:1400px) {
/* For mobile phones: (x1.5)*/
.title {
font-size: 2.25vw;
width: 42vw;
}
#app {
width: 42vw;
height: 45vw;
}
.game {
width: 36vw;
height: 36vw;
}
.game h2 {
font-size: 3vw;
}
.game p {
font-size: 1.5vw;
}
.square {
font-size: 6vw;
}
.top-panel {
font-size: 1.5vw;
}
.top-panel, .bottom-panel {
width: 36vw;
height: 4.5vw;
}
.btns {
padding: 2.25vw;
}
button {
font-size: 2.1vw;
}
.reset, .again {
width: 11.7vw;
font-size: 1.5vw;
}
}
@media only screen and (max-width:620px) {
/* For mobile phones: (x2.8)*/
.title {
font-size: 4.2vw;
width: 67vw;
}
#app {
width: 78vw;
height: 84vw;
}
.game {
width: 67vw;
height: 67vw;
}
.game h2 {
font-size: 5.6vw;
}
.game p {
font-size: 2.8vw;
}
.square {
font-size: 11.2vw;
}
.top-panel {
font-size: 2.8vw;
}
.top-panel, .bottom-panel {
width: 67vw;
height: 8.4vw;
}
.btns {
padding: 4.2vw;
}
button {
font-size: 3.9vw;
}
.reset, .again {
width: 21.8vw;
font-size: 2.8vw;
}
}
</style>
</head>
<body>
<div class="title">
<h1>Tic Tac Toe</h1>
</div>
<div id="app">
<div class="outer">
<div class="top-panel">
<div v-show="showPlayers" class="player-one" :class="{ 'green-one': oneIsActive }">({{ tokenone }}) {{ playerone }} | {{ scoreone }}</div>
<div v-show="showPlayers" class="player-two" :class="{ 'green-two': twoIsActive }">({{ tokentwo }}) {{ playertwo }} | {{ scoretwo }}</div>
</div>
<div class="game">
<component :is="component"
:board="board"
:win="win"
@play="playNext"
@player="setPlayer"
@token="setTokens"
></component>
</div>
<div class="bottom-panel">
<button class="again" @click="again" v-show="false">Play again</button>
<button class="reset" @click="reset">Reset</button>
</div>
</div>
<customalert v-if="showAlert"
@close="close"
:msg="message"></customalert>
</div>
<template id="screen1">
<div>
<div class="wording">
<h2>How do you want to play?</h2>
</div>
<div class="btns">
<button class="one-player" @click="$emit('player', 1)">One Player</button>
<button class="two-players" @click="$emit('player', 2)">Two Players</button>
</div>
</div>
</template>
<template id="screen2">
<div>
<div class="wording">
<h2>Would you like to be X or O?</h2>
<p>(X plays first)</p>
</div>
<div class="btns">
<button class="token-x" @click="$emit('token', 'X')">X</button>
<button class="token-o" @click="$emit('token', 'O')">O</button>
</div>
</div>
</template>
<template id="screen3">
<div>
<div class="wording">
<h2>Would you like to be X or O?</h2>
<p>(X plays first)</p>
</div>
<div class="btns">
<button class="token-x" @click="$emit('token', 'X')">X</button>
<button class="token-o" @click="$emit('token', 'O')">O</button>
</div>
</div>
</template>
<template id="screen4">
<div class="board">
<div class="square" :class="{ green: win[0] }" @click="$emit('play', 0)">{{ board[0] }}</div>
<div class="square" :class="{ green: win[1] }" @click="$emit('play', 1)">{{ board[1] }}</div>
<div class="square" :class="{ green: win[2] }" @click="$emit('play', 2)">{{ board[2] }}</div>
<div class="square" :class="{ green: win[3] }" @click="$emit('play', 3)">{{ board[3] }}</div>
<div class="square" :class="{ green: win[4] }" @click="$emit('play', 4)">{{ board[4] }}</div>
<div class="square" :class="{ green: win[5] }" @click="$emit('play', 5)">{{ board[5] }}</div>
<div class="square" :class="{ green: win[6] }" @click="$emit('play', 6)">{{ board[6] }}</div>
<div class="square" :class="{ green: win[7] }" @click="$emit('play', 7)">{{ board[7] }}</div>
<div class="square" :class="{ green: win[8] }" @click="$emit('play', 8)">{{ board[8] }}</div>
</div>
</template>
<template id="alert-template">
<div class="alert-container">
<div class="alert-header">
<h3>Tic Tac Toe</h3>
</div>
<div class="alert-body">
<p>{{ msg }}</p>
</div>
<div class="alert-footer">
<button class="alert-default-button" @click="$emit('close')">
OK
</button>
</div>
</div>
</template>
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<script>
/* Author: Richard Myatt
Date: 9 April 2018
A game of tic tac toe being a challenge set by freecodecamp. The main web
application uses Vue.js and the game logic is a combination of strategy
presented in the wikipedia article https://en.wikipedia.org/wiki/Tic-tac-toe
and an implementation of the minimax algorithm.
*/
Vue.component("screen-one", {
template: "#screen1"
});
Vue.component("screen-two", {
template: "#screen2"
});
Vue.component("screen-three", {
template: "#screen3"
});
Vue.component("screen-four", {
template: "#screen4",
props: ["board", "win"]
});
Vue.component('customalert', {
props: ["msg"],
template: '#alert-template'
});
var main = new Vue({
el: "#app",
data: {
autoPlayAgain: true,
playAgainEnabled: false,
resetEnabled: true,
singlePlayer: true,
playerone: "Player 1",
playertwo: "",
tokenone: "",
tokentwo: "",
scoreone: 0,
scoretwo: 0,
oneIsActive: false,
twoIsActive: false,
showPlayers: false,
board: ["", "", "", "", "", "", "", "", ""],
win: [false, false, false, false, false, false, false, false, false],
component: "screen-one",
message: "",
showAlert: false
},
methods: {
reset: function() {
if(this.resetEnabled === true) {
this.playAgainEnabled = false;
this.resetEnabled = true;
this.singlePlayer = true;
this.playertwo = "";
this.tokenone = "";
this.tokentwo = "";
this.scoreone = 0;
this.scoretwo = 0;
this.oneIsActive = false;
this.twoIsActive = false;
this.showPlayers = false;
this.board = ["", "", "", "", "", "", "", "", ""];
this.win = [false, false, false, false, false, false, false, false, false];
this.component = "screen-one";
}
},
again: function() {
if(this.playAgainEnabled) {
for(var i = 0; i < 9; i++) {
this.$set(this.board, i, "");
this.$set(this.win, i, false);
}
if(this.tokenone === "X") {
this.oneIsActive = true;
this.playAgainEnabled = false;
} else if(this.tokenone === "O" && this.playertwo === "Computer") {
this.twoIsActive = true;
this.playAgainEnabled = false;
setTimeout(function() { playComputer(); }, 1000);
} else {
this.twoIsActive = true;
this.playAgainEnabled = false;
}
}
},
setPlayer: function(arg) {
if(arg === 1) {
this.singlePlayer = true;
this.playertwo = "Computer";
this.component = "screen-two";
} else if(arg === 2) {
this.singlePlayer = false;
this.playertwo = "Player 2";
this.component = "screen-three";
}
},
setTokens: function(token) {
if(token === "X") {
this.tokenone = "X";
this.tokentwo = "O";
this.oneIsActive = true;
} else if(token === "O") {
this.tokenone = "O";
this.tokentwo = "X";
this.twoIsActive = true;
}
this.component = "screen-four";
this.showPlayers = true;
if(this.singlePlayer && this.twoIsActive) {
setTimeout(function() { playComputer(); }, 1000);
}
},
playNext: function(i) {
var tempBoard = new Board(brd=this.board);
if(this.singlePlayer && tempBoard.isAvailable(i + 1) && this.playAgainEnabled === false) {
if(this.oneIsActive === true) {
var token = this.tokenone;
this.$set(this.board, i, token);
var temp = new Board(brd = this.board);
if(temp.isWin() || temp.isDraw()) {
handleWinOrDraw(temp);
toggleActivePlayer();
return;
}
toggleActivePlayer();
setTimeout(function() { playComputer(); }, 1000);
}
} else if(!this.singlePlayer) { // two individual players
// check that square is available
//var tempBoard = new Board(brd=this.board);
if(tempBoard.isAvailable(i + 1) && this.playAgainEnabled === false) {
// get next move number
var nextMoveNum = tempBoard.getNextMoveNum();
if(nextMoveNum % 2 === 0) {
this.$set(this.board, i, "O");
checkBoardState();
} else {
this.$set(this.board, i, "X");
checkBoardState();
}
}
}
},
close: function() {
this.message = "";
this.showAlert = false;
this.playAgainEnabled = true;
this.resetEnabled = true;
this.again();
}
}
});
// function to handle computers moves
function playComputer() {
if(main.twoIsActive === true) {
var tempBoard = new Board(brd=main.board);
var nextMove = tempBoard.getNextMoveNum();
switch(nextMove) {
case 1:
main.$set(main.board, 4, "X");
break;
case 2:
if(tempBoard.isAvailable(5)) {
main.$set(main.board, 4, "O");
} else {
main.$set(main.board, randCornerIndex(), "O");
}
break;
case 3:
var result = cornerContains(tempBoard.board, "O");
if(nextMove === 3 && result !== -1) {
switch(result) {
case 0:
main.$set(main.board, 8, "X");
break;
case 2:
main.$set(main.board, 6, "X");
break;
case 6:
main.$set(main.board, 2, "X");
break;
case 8:
main.$set(main.board, 0, "X");
break;
}
break;
} else if (nextMove === 3 && result === -1) {
main.$set(main.board, randCornerIndex(), "X");
break;
}
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
var move = tempBoard.selectBestMove();
main.$set(main.board, move, main.tokentwo);
if(tempBoard.isWin() || tempBoard.isDraw()) {
handleWinOrDraw(tempBoard);
} else {
}
break;
}
}
toggleActivePlayer();
}
// helper method to return a random corner index
function randCornerIndex() {
var corner = [0, 2, 6, 8];
var choice = Math.floor(Math.random() * 4);
return corner[choice];
}
// helper function to determine if the corner of the board is occupied
function cornerContains(brd, token) {
var corner = [0, 2, 6, 8];
for(var i = 0; i < corner.length; i++) {
if(token === brd[corner[i]]) {
return corner[i];
}
}
return -1;
}
// function to check the state of the board and prepare for the next move
function checkBoardState() {
var tempBoard = new Board(brd=main.board);
if(tempBoard.isWin() || tempBoard.isDraw()) {
handleWinOrDraw(tempBoard);
toggleActivePlayer();
} else {
toggleActivePlayer();
}
}
// function to handle a win or draw
function handleWinOrDraw(brd) {
// identify current player
var currentPlayer;
if(main.oneIsActive === true) {
currentPlayer = main.playerone;
} else {
currentPlayer = main.playertwo;
}
// check for win or draw
if(brd.isWin()) {
var row = brd.getWinningRow();
for(var i = 0; i < row.length; i++) {
main.$set(main.win, row[i], true);
}
// increment score
if(currentPlayer === main.playerone) {
main.scoreone += 1;
} else {
main.scoretwo += 1;
}
if(currentPlayer === "Computer") {
var str = "Ooops.. " + currentPlayer + " wins!!!";
main.message = str;
callCustomAlert();
} else {
var str = "Congratulations " + currentPlayer + " you win!";
main.message = str;
callCustomAlert();
}
} else if(brd.isDraw()) {
var str = "A Draw";
main.message = str;
callCustomAlert();
}
// remove the status bar
main.oneIsActive = true;
main.twoIsActive = true;
}
// function to introduce a delay into the calling of the final custom alert
function callCustomAlert() {
setTimeout(function() {
main.showAlert = true;
main.resetEnabled = false;
}, 1300);
}
// function to toggle active player status
function toggleActivePlayer() {
main.oneIsActive = !main.oneIsActive;
main.twoIsActive = !main.twoIsActive;
}
/* Author: Richard Myatt
Date: 9 April 2018
A game of tic tac toe being a challenge set by freecodecamp. The main web
application uses Vue.js and the game logic is a combination of strategy
presented in the wikipedia article https://en.wikipedia.org/wiki/Tic-tac-toe
and an implementation of the minimax algorithm.
*/
// constructor for the board
function Board(arr) {
if(arr === undefined) {
this.board = ["", "", "", "", "", "", "", "", ""];
}else {
this.board = arr;
}
}
// method returns the array of rows for the board
Board.prototype.getRows = function() {
this.row1 = [this.board[0], this.board[1], this.board[2]];
this.row2 = [this.board[3], this.board[4], this.board[5]];
this.row3 = [this.board[6], this.board[7], this.board[8]];
this.col1 = [this.board[0], this.board[3], this.board[6]];
this.col2 = [this.board[1], this.board[4], this.board[7]];
this.col3 = [this.board[2], this.board[5], this.board[8]];
this.diag1 = [this.board[0], this.board[4], this.board[8]];
this.diag2 = [this.board[2], this.board[4], this.board[6]];
this.rows = [this.row1, this.row2, this.row3, this.col1, this.col2,
this.col3, this.diag1, this.diag2];
return this.rows;
};
// method that returns the rows for a given index - no tests
Board.prototype.getRowsForIndex = function(index) {
this.getRows();
switch(index) {
case 0:
return [this.row1, this.col1, this.diag1];
case 1:
return [this.row1, this.col2];
case 2:
return [this.row1, this.col3, this.diag2];
case 3:
return [this.row2, this.col1];
case 4:
return [this.row2, this.col2, this.diag1, this.diag2];
case 5:
return [this.row2, this.col3];
case 6:
return [this.row3, this.col1, this.diag2];
case 7:
return [this.row3, this.col2];
case 8:
return [this.row3, this.col3, this.diag1];
}
};
// method to return the cross row which applies when an edge is played
Board.prototype.getCrossRow = function(index) {
this.getRows();
switch(index) {
case 1:
return this.col2;
case 3:
return this.row2;
case 5:
return this.row2;
case 7:
return this.col2;
}
};
// method checks if the current board position is a win. Returns true or false
Board.prototype.isWin = function() {
this.getRows();
for(var i = 0; i < 8; i++) {
if(arraysEqual(this.rows[i], ["X", "X", "X"]) || arraysEqual(this.rows[i], ["O", "O", "O"])) {
return true;
}
}
return false;
};
// method returns an array of indecies for the winning row. If there is no winning
// row -1 is returned
Board.prototype.getWinningRow = function() {
this.getRows();
if(this.isWin()) {
for(var i = 0; i < 8; i++) {
if(arraysEqual(this.rows[i], ["X", "X", "X"]) || arraysEqual(this.rows[i], ["O", "O", "O"])) {
switch(i) {
case 0:
return [0, 1, 2];
case 1:
return [3, 4, 5];
case 2:
return [6, 7, 8];
case 3:
return [0, 3, 6];
case 4:
return [1, 4, 7];
case 5:
return [2, 5, 8];
case 6:
return [0, 4, 8];
case 7:
return [2, 4, 6];
}
}
}
} else {
return -1;
}
};
// method to determine if the position is a draw
Board.prototype.isDraw = function() {
if(this.isWin() === false && this.getNextMoveNum() === -1) {
return true;
} else {
return false;
}
};
// method which returns the number of the next move
Board.prototype.getNextMoveNum = function() {
// count number of available position
var num = 0;
for(var i = 0; i < 9; i++) {
if(this.board[i] === "") {
num += 1;
}
}
if(num === 0) {
return -1;
} else {
return 9 - num + 1;
}
};
// method check if the specified board position is available and returns true or
// false. pos takes values from 1 to 9.
Board.prototype.isAvailable = function(pos) {
if(this.board[pos - 1] === "") {
return true;
} else {
return false;
}
};
// method returns an array indexes of positions which are currently available
Board.prototype.available = function() {
var result = [];
for(var i = 0; i < 9; i++) {
if(this.board[i] === "") {
result.push(i);
}
}
return result;
};
// method which returns the next token to play assuming X always starts the game
Board.prototype.getNextTokenToPlay = function() {
var nextMoveNum = this.getNextMoveNum();
if(nextMoveNum % 2 === 0) {
return "O"; // "O" plays on all even moves
} else {
return "X"; // "X" plays on all odd moves
}
};
// method to return all possible boards given a board position
// this assumes that X always starts the game
Board.prototype.getAllPosBoards = function() {
var result = [];
var tempBoard = this.board.slice();
var possiblePositions = this.available();
var token = this.getNextTokenToPlay();
for(var i = 0; i < possiblePositions.length; i++) {
var newBoard = tempBoard.slice();
newBoard[possiblePositions[i]] = token;
result.push(newBoard);
}
return result;
};
// method to rank the move specified by pos which takes an integer 1 - 9.
Board.prototype.rankMove = function(pos) {
var token = this.getNextTokenToPlay();
var tempBoard = this.board.slice();
if(this.isAvailable(pos)) {
tempBoard[pos - 1] = token;
} else {
console.log("position already taken");
}
var tempBrd = new Board(tempBoard);
if(tempBrd.isWin()) {
return 10;
} else {
brds = [tempBrd.board];
return analyseLevels(brds, 2);
}
};
// method which returns an analysis of the Moves available at the current board
// position. Returns an array of arrays providing the index and the rank of the
// move
Board.prototype.analyseMovesFor = function() {
var result = []; // holds the result
var tempBoard = this.board.slice(); // copy present board
var choices = this.available(); // get a list of available indecies
for(var i = 0; i < choices.length; i++) {
var tempBoardObj = new Board(tempBoard);
var index = choices[i];
var rank = tempBoardObj.rankMove(index + 1);
//newBoard = tempBoard;
result.push([index, rank]);
}
return result;
};
// method to select the best move based on analyseMovesFor()
// returns the best move in the form index
Board.prototype.selectBestMove = function() {
var token = this.getNextTokenToPlay();
var selection = this.selectTopRankedMovesFor();
// check for posibility of a fork
for(var i = 0; i < selection.length; i++) {
if(this.isFork(selection[i][0])) {
// play at this position
return selection[i][0];
}
}
// can the opponent form a fork?
for(var l = 0; l < selection.length; l++) {
if(this.isOpponentFork(selection[l][0])) {
if(this.isCorner(selection[l][0])) {
// look for an edge play which will force a defense
for(var m = 0; m < selection.length; m++) {
if(this.isEdge(selection[m][0])) {
var crossRow = this.getCrossRow(selection[m][0]);
// does this row contain an opponent token
if(token === "X") {
opponentToken = "O";
} else {
opponentToken = "X";
}
if(crossRow.indexOf(opponentToken) === -1) {
return selection[m][0];
}
}
}
}
}
}
// no fork return first top ranked move then check for possibility of play at
// a corner
for(var k = 0; k < selection.length; k++) {
if(this.isCorner(selection[k][0])) {
return selection[k][0];
}
}
// if neither a fork or a corner is available to play then return the first
// top ranked move
return selection[0][0];
};
// helper function to return value of largest rank as an integer given an array
// containing the analysed moves for this position
function getFirstLargestSelection(moves) {
var selection = moves[0];
var largest = moves[0][1];
for(var i = 0; i < moves.length; i++) {
if(largest < moves[i][1]) {
largest = moves[i][1];
selection = moves[i];
}
}
return selection;
}
// method returns an array of top ranked moves
Board.prototype.selectTopRankedMovesFor = function() {
var result = [];
var movesFromAnalysis = this.analyseMovesFor();
var selection = getFirstLargestSelection(movesFromAnalysis);
var topRank = selection[1];
for(var i = 0; i < movesFromAnalysis.length; i++) {
if(movesFromAnalysis[i][1] === topRank) {
result.push(movesFromAnalysis[i]);
}
}
return result;
};
// method that determines if a selected play produces a fork. Returns true if
// a fork can be created from that position, otherwise false
Board.prototype.isFork = function(index) {
var token = this.getNextTokenToPlay();
var rows = this.getRowsForIndex(index);
var prospect = 0; // a prospect contains one token and two spaces
for(var i = 0; i < rows.length; i++) {
if(rows[i].indexOf(token) !== -1) { // row contains at least one tokenn
// count spaces
var spaces = 0;
for(var k = 0; k < 3; k++) {
if(rows[i][k] === "") {
spaces += 1;
}
}
if(spaces > 1) {
prospect += 1;
}
}
}
if(prospect >= 2) {
return true;
} else {
return false;
}
};
// method to return the prospect of the opponent playing a fork.
Board.prototype.isOpponentFork = function(index) {
var token = this.getNextTokenToPlay();
if(token === "X") {
token = "O";
} else {
token = "X";
}
var rows = this.getRowsForIndex(index);
var prospect = 0; // a prospect contains one token and two spaces
for(var i = 0; i < rows.length; i++) {
if(rows[i].indexOf(token) !== -1) { // row contains at least one tokenn
// count spaces
var spaces = 0;
for(var k = 0; k < 3; k++) {
if(rows[i][k] === "") {
spaces += 1;
}
}
if(spaces > 1) {
prospect += 1;
}
}
}
if(prospect >= 2) {
return true;
} else {
return false;
}
};
// method that determines if a selected play produces a corner move. Returns
// true or false
Board.prototype.isCorner = function(index) {
var cornerIndexes = [0, 2, 6, 8];
if(cornerIndexes.indexOf(index) !== -1) {
return true;
} else {
return false;
}
};
// method that determines if a selected play produces an edge move. Returns
// true or false
Board.prototype.isEdge = function(index) {
var edgeIndexes = [1, 3, 5, 7];
if(edgeIndexes.indexOf(index) !== -1) {
return true;
} else {
return false;
}
};
// helper function for rankMove to analyse each level given an array of boards
// and the level
function analyseLevels(brds, lvl) {
// get an array of boards for this level
var newBoards = []; // holds all posible boards for this level
for(var i = 0; i < brds.length; i++) {
var tempBoard = new Board(brds[i]);
var collection = tempBoard.getAllPosBoards();
for(var j = 0; j < collection.length; j++) {
newBoards.push(collection[j]);
}
}
for(var k = 0; k < newBoards.length; k++) {
var firstBoard = new Board(newBoards[0]);
if(newBoards.length === 1 && firstBoard.isWin()) {
return -10;
} else if(newBoards.length === 1 && firstBoard.isDraw()) {
return 0;
}else {
if(incTerminalState(newBoards)) {
if(lvl % 2 === 0) {
return -(12 - lvl);
} else {
return (11 - lvl);
}
} else {
return analyseLevels(newBoards, lvl + 1);
}
}
}
}
// helper method to check the equality of arrays arr1, and arr2. Returns
// true or false
function arraysEqual(arr1, arr2) {
if (arr1 === arr2) return true;
if (arr1 == null || arr2 == null) return false;
if (arr1.length != arr2.length) return false;
for (var i = 0; i < arr1.length; ++i) {
if (arr1[i] !== arr2[i]) return false;
}
return true;
}
// helper method to check the equality of nested arrays arr1, and arr2. Returns
// true or false. Deals with two dimensional arrays only
function nestedArraysEqual(arr1, arr2) {
if (arr1 === arr2) return true;
if (arr1 == null || arr2 == null) return false;
if (arr1.length != arr2.length) return false;
for (var i = 0; i < arr1.length; ++i) {
if (!arraysEqual(arr1[i], arr2[i])) return false;
}
return true;
}
// function which takes an array of boards and checks to determine if a terminal
// state is present in the array, either a win or a draw
function incTerminalState(boards) {
for(var i = 0; i < boards.length; i++) {
var tempBoard = new Board(boards[i]);
//console.log(tempBoard);
if(tempBoard.isWin() || tempBoard.isDraw()) {
return true;
}
}
return false;
}
</script>
</body>
</html>
10. By Dream
Made by Dream. Simple JavaScript Tic Tac Toe game with three modes. ( Source )
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="game.css">
<style>
body {
box-sizing: border-box;
display: flex;
height: 100vh;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: Oswald;
background-color: #5cc;
margin: 0;
}
.overlay {
display: none;
position: absolute;
width: 100%;
height: 85vh;
top: 0;
}
.overlay.show {
display: block;
}
.msg {
display: none;
position: absolute;
width: 100%;
height: 85vh;
top: 0;
font-size: 12vh;
overflow: hidden;
}
.msg span {
display: none;
position: absolute;
width: 100%;
height: 100%;
background: rgba(85, 204, 204, 0.8);
left: 0;
text-align: center;
line-height: 80vh;
}
.msg span.show {
display: block;
}
.tic-tac-toe {
position: relative;
display: grid;
grid-template-rows: repeat(3, 25vh);
grid-template-columns: repeat(3, 33.3%);
width: 75vh;
}
.tic-tac-toe .box {
display: block;
position: relative;
}
.tic-tac-toe .box:nth-of-type(1), .tic-tac-toe .box:nth-of-type(2), .tic-tac-toe .box:nth-of-type(4), .tic-tac-toe .box:nth-of-type(5), .tic-tac-toe .box:nth-of-type(7), .tic-tac-toe .box:nth-of-type(8) {
border-right: 3px solid #388;
}
.tic-tac-toe .box:nth-of-type(2), .tic-tac-toe .box:nth-of-type(3), .tic-tac-toe .box:nth-of-type(5), .tic-tac-toe .box:nth-of-type(6), .tic-tac-toe .box:nth-of-type(8), .tic-tac-toe .box:nth-of-type(9) {
border-left: 3px solid #388;
}
.tic-tac-toe .box:nth-of-type(4), .tic-tac-toe .box:nth-of-type(5), .tic-tac-toe .box:nth-of-type(6), .tic-tac-toe .box:nth-of-type(7), .tic-tac-toe .box:nth-of-type(8), .tic-tac-toe .box:nth-of-type(9) {
border-top: 3px solid #388;
}
.tic-tac-toe .box:nth-of-type(1), .tic-tac-toe .box:nth-of-type(2), .tic-tac-toe .box:nth-of-type(3), .tic-tac-toe .box:nth-of-type(4), .tic-tac-toe .box:nth-of-type(5), .tic-tac-toe .box:nth-of-type(6) {
border-bottom: 3px solid #388;
}
.tic-tac-toe .box.show-circle .circle {
display: block;
}
.tic-tac-toe .cross {
display: none;
position: relative;
width: 100%;
height: 100%;
}
.tic-tac-toe .cross::before,
.tic-tac-toe .cross::after{
content: "";
display: block;
position: absolute;
width: 80%;
height: 6px;
top: 50%;
left: 50%;
margin-top: -3px;
margin-left: -40%;
background-color: black;
}
.tic-tac-toe .cross:before {
transform: rotate(45deg);
}
.tic-tac-toe .cross:after {
transform: rotate(135deg);
}
.tic-tac-toe .circle{
display: none;
box-sizing: border-box;
position: absolute;
width: 16vh;
height: 16vh;
top: 50%;
margin-top: -8vh;
left: 50%;
margin-left: -8vh;
border-radius: 50%;
border: 6px solid white;
}
.tic-tac-toe input{
display: none;
position: absolute;
top: 0;
}
.tic-tac-toe input:checked ~ .cross{
display: block;
}
a .replay{
color: black;
font-size: 6vh;
margin: 5vh auto 0;
color: white;
background-color: #388;
padding: 1.6vh 4.8vh 1.8vh;
line-height: 1em;
text-decoration: none;
transform: color 0.4s;
}
a .replay:hover{
background-color: #166;
}
.controls{
position: absolute;
top: -3vh;
right: -32vh;
}
.controls a{
display: block;
color: #388;
font-size: 6vh;
text-decoration: none;
margin: 2vh auto;
transform: color 0.4s;
}
.controls a:hover{
color: #144;
}
.controls a.active{
color: #144;
}
.replay{
padding: 14px;
text-decoration: none;
background-color: white;
color: black;
}
</style>
</head>
<body>
<div class="tic-tac-toe normal">
<label class="box box-1">
<input type="checkbox" onchange="changed(this)" data-num="1"/>
<div class="cross"></div>
<div class="circle"></div>
</label>
<label class="box box-2">
<input type="checkbox" onchange="changed(this)" data-num="2"/>
<div class="cross"></div>
<div class="circle"></div>
</label>
<label class="box box-3">
<input type="checkbox" onchange="changed(this)" data-num="3"/>
<div class="cross"></div>
<div class="circle"></div>
</label>
<label class="box box-4">
<input type="checkbox" onchange="changed(this)" data-num="4"/>
<div class="cross"></div>
<div class="circle"></div>
</label>
<label class="box box-5">
<input type="checkbox" onchange="changed(this)" data-num="5"/>
<div class="cross"></div>
<div class="circle"></div>
</label>
<label class="box box-6">
<input type="checkbox" onchange="changed(this)" data-num="6"/>
<div class="cross"></div>
<div class="circle"></div>
</label>
<label class="box box-7">
<input type="checkbox" onchange="changed(this)" data-num="7"/>
<div class="cross"></div>
<div class="circle"></div>
</label>
<label class="box box-8">
<input type="checkbox" onchange="changed(this)" data-num="8"/>
<div class="cross"></div>
<div class="circle"></div>
</label>
<label class="box box-9">
<input type="checkbox" onchange="changed(this)" data-num="9"/>
<div class="cross"></div>
<div class="circle"></div>
</label>
<div class="controls"><a class="easy" href="javascript:lvl(0);">EASY</a><a class="normal active" href="javascript:lvl(1);">NORMAL</a><a class="impossible" href="javascript:lvl(2);">IMPOSSIBLE</a></div>
</div>
<div class="overlay"></div>
<div class="msg">
<span class="win">YOU WIN!</span>
<span class="lost">YOU LOST!</span>
<span class="draw">DRAW!</span></div>
<a class="replay" href="javascript:replay();">REPLAY</a>
<!-- now add javascript code -->
<script>
const boxes = document.querySelectorAll('.box');
let seq = { 1: '', 2: '', 3: '', 4: '', 5: '', 6: '', 7: '', 8: '', 9: '' };
let gameEnd = false;
const $ = el => document.querySelector(el);
function changed(el) {
if (el.checked) {
el.disabled = true;
let n = parseInt(el.getAttribute('data-num'));
seq[n] = 'x';
checkWin();
if (Object.values(seq).filter(Boolean).length < 9 && !gameEnd) {
calculateNextPosition();
}
}
}
const checkInclude = player => (...indices) => indices.every(i => seq[i] === player);
const checkIncludeX = checkInclude('x');
const checkIncludeO = checkInclude('o');
function checkWin() {
const gameWon = player => ( checkInclude(player)(1, 2, 3) ||
checkInclude(player)(4, 5, 6) ||
checkInclude(player)(7, 8, 9) ||
checkInclude(player)(1, 4, 7) ||
checkInclude(player)(2, 5, 8) ||
checkInclude(player)(3, 6, 9) ||
checkInclude(player)(1, 5, 9) ||
checkInclude(player)(3, 5, 7) )
if (gameWon('x') || gameWon('o')) {
const playerWon = gameWon('x') ? '.win' : '.lost';
boxes.forEach(box => box.querySelector('input').disabled = true);
$('.msg').style.display = 'block';
$(playerWon).classList.add('show');
gameEnd = true;
} else if (Object.values(seq).filter(Boolean).length === 9) {
$('.msg').style.display = 'block';
$('.draw').classList.add('show');
}
}
const addCircle = boxNumber => {
seq[boxNumber] = 'o';
$('.overlay').classList.add('show');
setTimeout(()=> {
$('.box-'+boxNumber).classList.add('show-circle');
$('.box-'+boxNumber).querySelector('input').disabled = true;
$('.overlay').classList.remove('show');
checkWin();
}, 400);
}
function calculateNextPosition() {
let tar = Math.ceil(Math.random()*9);
const xo_includes = _tar => checkIncludeO(_tar) || checkIncludeX(_tar);
const isValidNextPosition = newPos => !xo_includes(newPos) ? tar = newPos : null
while (checkIncludeO(tar) || checkIncludeX(tar)) {
tar = Math.ceil(Math.random()*9);
}
if (!$('.tic-tac-toe').classList.contains('easy')) {
for (let x = 1; x < 10; x++) {
if (checkIncludeX(x, x+1)) {
// x x _ / _ x x
if ([1, 4, 7].includes(x)) {
isValidNextPosition(x+2);
} else if ([2, 5, 8].includes(x)) {
isValidNextPosition(x-1)
}
}
if (checkIncludeX(x, x+2) && [1, 4, 7].includes(x)) {
// x _ x
isValidNextPosition(x+1)
}
if (checkIncludeX(x, x+3) && x <= 6) {
// x _ _ / _ x _ / _ _ x
// x _ _ / _ x _ / _ _ x
const _tar = (x+6 > 9) ? x-3 : x+6;
isValidNextPosition(_tar)
}
if ( [1, 3].includes(x) && checkIncludeX(x, 5) ) {
// x _ _ / _ _ x
// _ x _ / _ x _
// _ _ _ / _ _ _
const _tar = (x == 1) ? 9 : 7;
isValidNextPosition(_tar)
}
if ( [7, 9].includes(x) && checkIncludeX(x, 5) ) {
// _ _ _ / _ _ _
// _ x _ / _ x _
// _ _ x / x _ _
const _tar = (x == 7) ? 3 : 1;
isValidNextPosition(_tar)
}
if ($('.tic-tac-toe').classList.contains('impossible')) {
if (checkIncludeX(x, x+6) && x <= 3) {
// x _ _ / _ x _ / _ _ x
// _ _ _ / _ _ _ / _ _ _
// x _ _ / _ x _ / _ _ x
isValidNextPosition(x+3)
}
if ( (x == 1 && checkIncludeX(x, x+8)) || (x == 3 && checkIncludeX(x, x+4)) ) {
// x _ _ / _ _ x
// _ _ _ / _ _ _
// _ _ x / x _ _
isValidNextPosition(5)
}
}
}
}
addCircle(tar);
}
function replay() {
seq = {};
boxes.forEach(box => {
box.querySelector('input').disabled = false;
box.querySelector('input').checked = false;
box.classList.remove('show-circle');
})
$('.msg').style.display = "none";
$('.win').classList.remove('show');
$('.lost').classList.remove('show');
$('.draw').classList.remove('show');
gameEnd = false;
}
lvl = idx => {
const lvls = ['easy', 'normal', 'impossible'];
lvls.forEach(level => {
$('.tic-tac-toe').classList.remove(level);
$('.controls .'+level).classList.remove('active');
})
$('.tic-tac-toe').classList.add(lvls[idx]);
$('.controls .'+lvls[idx]).classList.add('active');
}
</script>
</body>
</html>
11. By SRoy
Made by SRoy. AI Tic tac Toe game. You can choose the first move or pass it to the AI, to start the game click the ‘Start’ button. ( Source )
<html>
<head>
<style>
body {
background: linear-gradient(magenta, orange, purple);
color: cyan;
text-shadow: 0pt 0pt 20pt blue;
}
button {
font-size: 20pt;
height: 50pt;
width: 50pt;
background: radial-gradient(magenta, purple);
color: yellow;
text-shadow: 0pt 0pt 3pt black;
}
</style>
</head>
<body>
<center><pre>
<h1>TIC TAC TOE</h1>
<button id="a00" onclick="f(0,0)"> </button><button id="a01" onclick="f(0,1)"> </button><button id="a02" onclick="f(0,2)"> </button>
<button id="a10" onclick="f(1,0)"> </button><button id="a11" onclick="f(1,1)"> </button><button id="a12" onclick="f(1,2)"> </button>
<button id="a20" onclick="f(2,0)"> </button><button id="a21" onclick="f(2,1)"> </button><button id="a22" onclick="f(2,2)"> </button><br>
<button id="gmb" onclick="gcntrl()" style="background: red; color: white; font-size: 15pt; height: 25pt; width: 60pt">START</button>
<h2 id=status></h2></pre>
</center>
<script>
var trn=0; // No. of turns
var ch1,ch2; // Characters 'x' & 'o'
var g=false; // Whether the game is being played
var win=0; // Decides who won
var a=new Array(); // The gameboard
a[0]=new Array();
a[1]=new Array();
a[2]=new Array();
function f(r,c) // For user's turn
{
if(g)
if(a[r][c]==0)
{
a[r][c]=1;
trn++;
set();
check();
if(g)
autogame();
}
}
function set() // Draws the gameboard
{
for(i=0;i<3;i++)
for(j=0;j<3;j++)
if(a[i][j]==1)
document.getElementById("a"+i+j).innerHTML=ch1;
else if(a[i][j]==-1)
document.getElementById("a"+i+j).innerHTML=ch2;
else
document.getElementById("a"+i+j).innerHTML=" ";
}
function autogame() // CPU's turn
{
var r,c,i,j;
var x;
for(i=0;i<3;i++) // Rows
{
x=0;
for(j=0;j<3;j++)
x=x+a[i][j];
if(x==-2)
for(j=0;j<3;j++)
if(a[i][j]==0)
{
a[i][j]=-1;
trn++;
set();
check();
return;
}
}
for(i=0;i<3;i++) // Columns
{
x=0;
for(j=0;j<3;j++)
x=x+a[j][i];
if(x==-2)
for(j=0;j<3;j++)
if(a[j][i]==0)
{
a[j][i]=-1;
trn++;
set();
check();
return;
}
}
x=0;
for(i=0;i<3;i++) // Diagonal 1
x=x+a[i][i];
if(x==-2)
for(i=0;i<3;i++)
if(a[i][i]==0)
{
a[i][i]=-1;
trn++;
set();
check();
return;
}
x=0;
for(i=0;i<3;i++) // Diagonal 2
x=x+a[i][2-i];
if(x==-2)
for(i=0;i<3;i++)
if(a[i][2-i]==0)
{
a[i][2-i]=-1;
trn++;
set();
check();
return;
}
// Check User's
for(i=0;i<3;i++) // Rows
{
x=0;
for(j=0;j<3;j++)
x=x+a[i][j];
if(x==2)
for(j=0;j<3;j++)
if(a[i][j]==0)
{
a[i][j]=-1;
trn++;
set();
check();
return;
}
}
for(i=0;i<3;i++) // Columns
{
x=0;
for(j=0;j<3;j++)
x=x+a[j][i];
if(x==2)
for(j=0;j<3;j++)
if(a[j][i]==0)
{
a[j][i]=-1;
trn++;
set();
check();
return;
}
}
x=0;
for(i=0;i<3;i++) // Diagonal 1
x=x+a[i][i];
if(x==2)
for(i=0;i<3;i++)
if(a[i][i]==0)
{
a[i][i]=-1;
trn++;
set();
check();
return;
}
x=0;
for(i=0;i<3;i++) // Diagonal
x=x+a[i][2-i];
if(x==2)
for(i=0;i<3;i++)
if(a[i][2-i]==0)
{
a[i][2-i]=-1;
trn++;
set();
check();
return;
}
r=(Math.floor(Math.random()*10))%3;
c=(Math.floor(Math.random()*10))%3;
if(a[r][c]==0)
{
a[r][c]=-1;
trn++;
}
else
autogame();
set();
check();
}
function check() // Checks if anybody won
{
var i,j;
var x;
for(i=0;i<3;i++) // Rows
{
x=0;
for(j=0;j<3;j++)
x=x+a[i][j];
if(x==3)
{
win=1;
gcntrl();
}
else if(x==-3)
{
win=2;
gcntrl();
}
}
for(i=0;i<3;i++) // Columns
{
x=0;
for(j=0;j<3;j++)
x=x+a[j][i];
if(x==3)
{
win=1;
gcntrl();
}
else if(x==-3)
{
win=2;
gcntrl();
}
}
x=a[0][0]+a[1][1]+a[2][2]; // Diagonal 1
if(x==3)
{
win=1;
gcntrl();
}
else if(x==-3)
{
win=2;
gcntrl();
}
x=a[0][2]+a[1][1]+a[2][0]; // Diagonal 2
if(x==3)
{
win=1;
gcntrl();
}
else if(x==-3)
{
win=2;
gcntrl();
}
if(trn==9)
gcntrl();
}
function gcntrl() // Function of the red button, controls the game
{
if(!g)
{
a=[[0,0,0],[0,0,0],[0,0,0]];
set();
document.getElementById("status").innerHTML="";
var x=confirm("Do you want to take the first move?\nIf yes, press \"OK\"\nPress \"Cancel\" to pass the move.");
var pr;
if(x)
{
ch1="x";
ch2="o";
pr="yours";
}
else
{
ch2="x";
ch1="o";
pr="mine";
autogame();
}
alert("First move is "+pr+"\nYour symbol "+ch1+"\nMy symbol "+ch2+"\nPress \"OK\"");
document.getElementById("gmb").innerHTML="RESET";
g=true;
}
else
{
document.getElementById("gmb").innerHTML="START";
if(win==0)
{
if(trn==9)
document.getElementById("status").innerHTML="Game tied!";
else
document.getElementById("status").innerHTML="Game terminated!";
}
else if(win==1)
document.getElementById("status").innerHTML="Congratulations! you won!";
else
document.getElementById("status").innerHTML="You lost!";
win=0;
g=false;
trn=0;
}
}
alert("Please upvote it if you like it...\n\nPress \"OK\", then press the \"START\" (red) button to play...")
</script>
</body>
</html>
12. By M Bima Y
Made by M Bima Y. A simple 2 Player tic tac toe game, the game also keep tracks of the previous wins. ( Source )
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tic Tac Toe Game</title>
<!-- Sweetalert2 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/sweetalert2.all.min.js" integrity="sha256-2iFgzMziCroYT0IkthOS8usgi+KXxOiA5tvNCMyh984=" crossorigin="anonymous"></script>
<!-- CSS bootstrap -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<!-- JavaScript Bootstrap -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<link rel="stylesheet" href="style.css">
<link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon" />
<style>
.game-container {
grid-template-columns: auto auto auto;
max-width: 400px;
}
.game {
border: 1px solid #000;
height: 110px;
display: flex;
justify-content: center;
align-items: center;
}
.x-shape, .o-shape {
position: absolute;
font-size: 45px;
font-weight: 300;
}
.x-shape {
color: #FF3C3C;
}
.o-shape {
color: #3C4FFF;
}
.turn-text {
font-size: 20px;
}
.turn-value {
font-size: 25px;
}
.score {
font-size: 24px;
}
.score span {
padding: 0 4px;
}
</style>
</head>
<body>
<div class="title-container container-fluid p-2 mt-4 mb-4 d-flex justify-content-center">
<h1 class="title">Tic Tac Toe (2 Player)</h1>
</div>
<div class="score-container container-fluid d-flex justify-content-center">
<div class="score container-sm d-flex justify-content-center">
<span class="red-score value-score text-danger">0</span>
<span>:</span>
<span class="blue-score value-score text-primary">0</span>
</div>
</div>
<div class="main-container container-fluid mt-5 mb-5">
<div class="game-container container-sm d-grid">
<div class="game game-1"></div>
<div class="game game-2"></div>
<div class="game game-3"></div>
<div class="game game-4"></div>
<div class="game game-5"></div>
<div class="game game-6"></div>
<div class="game game-7"></div>
<div class="game game-8"></div>
<div class="game game-9"></div>
</div>
<div class="btn-container d-flex justify-content-center mt-5 mb-5">
<button class="reset-btn btn btn-warning text-white">Reset</button>
</div>
</div>
<div class="info-container container-fluid pt-2 pb-2">
<div class="turn-container container"><span class="turn-text">Turn: </span><span class="turn-value"></span></div>
</div>
<script>
const score = {
htmls: document.querySelectorAll(".value-score"),
red: 0,
blue: 0,
add(winner=""){
if(!winner) return;
this[winner]++;
this.display();
},
display(){
let scores = [this.red, this.blue];
this.htmls.forEach((html, i) => {
html.innerHTML = scores[i];
});
}
};
const turn = {
html: document.querySelector(".turn-value"),
color: {
red: "#FF3C3C",
blue: "#3C4FFF"
},
options: {
style: {
color: ""
},
innerHTML: ""
},
getColor(value=""){
let color = value === "x" ? this.color.red :
value === "o" ? this.color.blue : "#000";
return color;
},
getOpposite(value=""){
let opposite = value === "x" ? "o" :
value === "o" ? "x" : "";
return opposite;
},
set(value=""){
let color = this.getColor(value);
this.options.style.color = color
this.options.innerHTML = value;
this.display();
},
change(value=""){
let opposite = this.getOpposite(value);
let color = this.getColor(opposite);
this.options.style.color = color;
this.options.innerHTML = opposite;
this.display();
},
display(){
this.html.style.color = this.options.style.color;
this.html.innerHTML = this.options.innerHTML;
}
};
// Main object
const game = {
squares: document.querySelectorAll(".game"),
fields: [],
value: "x",
winner: "",
paused: false,
display(){
this.squares.forEach((square, i) => {
let field = this.fields[i];
square.innerHTML = this.getShape(field);
});
},
async displayAlert(title="", text="", icon=""){
await Swal.fire({
title,
text,
icon
});
},
getWinner(value="", fields=[]){
let filtered = fields.filter((field, i) => {
return value === field;
});
let minimumPassed = filtered.length >= 3;
if(!(value && minimumPassed)){
return false;
}
const getIndexes = (value="", fields=[]) => {
let output = [];
fields.forEach((field, i) => {
if(value === field){
output.push(i);
}
});
return output;
};
const includeAll = (indexes=[], array=[]) => {
for(let i = 0; i < array.length; i++){
let nums = [];
for(let j = 0; j < array[i].length; j++){
let found = indexes.findIndex((n) => {
return n === array[i][j];
});
let bool = found !== -1;
nums.push(Number(bool));
}
let foundZero = nums.findIndex(n => n === 0);
if(foundZero !== -1){
continue;
}
return true;
}
return false;
};
const checkWinner = (value="") => {
let winnerPosition = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
let indexes = getIndexes(value, fields);
let isIncludeAll = includeAll(indexes, winnerPosition);
return isIncludeAll ? this.getColorName(value) : "";
};
return checkWinner(value)
},
getColorName(value=""){
return value === "x" ? "Red" :
value === "o" ? "Blue" : "";
},
getShape(value){
let xShapeClassName = "x-shape";
let oShapeClassName = "o-shape";
let xShape = `<span class="${xShapeClassName}">x</span>`;
let oShape = `<span class="${oShapeClassName}">o</span>`;
return value === "x" ? xShape
: value === "o" ? oShape
: "";
},
isDraw(){
let filteredFields = this.fields.filter((field, i) => {
return field != undefined;
});
return filteredFields.length === 9;
},
async add(value, position){
if(this.fields[position] || this.paused){
return false;
}
this.fields[position] = value;
turn.change(this.value);
this.display();
this.winner = this.getWinner(this.value, this.fields);
if(this.winner){
this.paused = true;
score.add(this.winner.toLowerCase());
await this.displayAlert(`${this.winner} won!`, "", "success");
return false;
}
if(this.isDraw()){
this.paused = true;
await this.displayAlert("Draw!");
return false;
}
this.value = this.value === "x" ? "o" : "x";
},
reset(){
if(!this.fields.length) return;
this.fields = [];
this.value = "x";
this.winner = "";
this.paused = false;
turn.set(this.value);
this.display();
},
init(){
const resetBtn = document.querySelector(".reset-btn");
resetBtn.addEventListener("click", () => {
this.reset();
});
this.squares.forEach((square, i) => {
square.addEventListener("click", () => {
this.add(this.value, i);
});
});
}
};
window.addEventListener("load", () => {
game.init();
turn.set("x");
});
</script>
</body>
</html>
13. By Micah Meadows
Made by Micah Meadows. Two player Tic tac Toe game. ( Source )
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<style>
body {
background-color: grey;
max-height: 100%;
max-width: 100%;
}
table button{
background-color: white;/* Green */
border: none;
color: black;
text-decoration: none;
display: inline-block;
font-size: 40px;
width: 100px;
height: 100px;
text-align: center;
}
#resetbtn, button
{
background-color: white;/* Green */
border: none;
color: black;
text-decoration: none;
display: inline-block;
font-size: 35px;
width: 200px;
height: 50px;
text-align: center;
border: 3px solid black;
position: relative;
}
#resetbtn h1{
}
.btnbox{
position: relative;
margin-left: 100px;
}
table{
position: relative;
max-height: 100%;
height: auto;
top: 0px;
margin-left: 40px;
background-color: black;
}
h1{
position: relative;
top: 10px;
text-align: center;
}
</style>
</head>
<body onload="onStart()">
<table>
<tr id="top-row">
<td onclick="chose(0)">
<button id="tl">tl</button></td>
<td onclick="chose(1)">
<button id="tc">tc</button></td>
<td onclick="chose(2)">
<button id="tr">tr</button></td>
</tr>
<tr id="mid-row">
<td onclick="chose(3)">
<button id="ml">ml</button></td>
<td onclick="chose(4)">
<button id="mc">mc</button></td>
<td onclick="chose(5)">
<button id="mr">mr</button></td>
</tr>
<tr id="bot-row">
<td onclick="chose(6)">
<button id="bl">bl</button></td>
<td onclick="chose(7)">
<button id="bc">bc</button></td>
<td onclick="chose(8)">
<button id="br">br</button></td>
</tr>
</table>
<h1 id="result"> Player 1 Wins! </h1>
<div class="btnbox">
<button id="resetbtn" onclick="resetGame()">RESET</button>
</div>
<script>
var player = 1;
var token = ["x", "o"];
var winner = '';
var alerted = 0;
var resultTxt;
var topL;
var topC;
var topR;
var midL;
var midC;
var midR;
var botL;
var botC;
var botR;
var resetBtn;
var board = ["", "", "", "", "", "", "", "", ""];
var numblank = board.length;
var solution = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[6,4,2]];
/*
0 | 1 | 2
---------
3 | 4 | 5
---------
6 | 7 | 8
*/
function onStart()
{
resetBtn = document.getElementById('resetbtn');
resultTxt = document.getElementById('result');
topL = document.getElementById('tl');
topC = document.getElementById('tc');
topR = document.getElementById('tr');
midL = document.getElementById('ml');
midC = document.getElementById('mc');
midR = document.getElementById('mr');
botL = document.getElementById('bl');
botC = document.getElementById('bc');
botR = document.getElementById('br');
topL.innerHTML = "";
topC.innerHTML = "";
topR.innerHTML = "";
midL.innerHTML = "";
midC.innerHTML = "";
midR.innerHTML = "";
botL.innerHTML = "";
botC.innerHTML = "";
botR.innerHTML = "";
resultTxt.innerHTML = "";
resetBtn.style.visibility ='hidden';
}
function chose(selection)
{
if(board[selection] == ''){
board[selection] = token[player-1];
}
if(alerted)
{
return;
}
switch (selection){
case 0:
if(topL.innerHTML == ''){
topL.innerHTML = token[player-1];
numblank--;
checkWin();
swap();
}
break;
case 1:
if(topC.innerHTML == ''){
topC.innerHTML = token[player-1];
numblank--;
checkWin();
swap();
}
break;
case 2:
if(topR.innerHTML == ''){
topR.innerHTML = token[player-1];
numblank--;
checkWin();
swap();
}
break;
case 3:
if(midL.innerHTML == ''){
midL.innerHTML = token[player-1];
numblank--;
checkWin();
swap();
}
break;
case 4:
if(midC.innerHTML == ''){
midC.innerHTML = token[player-1];
numblank--;
checkWin();
swap();
}
break;
case 5:
if(midR.innerHTML == ''){
midR.innerHTML = token[player-1];
numblank--
checkWin();
swap();
}
break;
case 6:
if(botL.innerHTML == ''){
botL.innerHTML = token[player-1];
numblank--;
checkWin();
swap();
}
break;
case 7:
if(botC.innerHTML == ''){
botC.innerHTML = token[player-1];
numblank--;
checkWin();
swap();
}
break;
case 8:
if(botR.innerHTML == ''){
botR.innerHTML = token[player-1];
numblank--;
checkWin();
swap();
}
break;
}
}
function swap(){
if(player == 1)
{
player = 2;
}
else if(player == 2)
{
player = 1;
}
}
function checkWin()
{
var a = 0;
var b = 0;
var c = 0;
for(i = 0; i < solution.length; i++)
{
a = solution[i][0];
b = solution[i][1];
c = solution[i][2];
if(board[a] == board[b] && board[a] == board[c])
{
if(board[a] != '' &&
board[b] != '' &&
board[c] != '')
{
if(player == 1){
winner = 'X';
}
else{
winner = 'O';
}
//alert("game over " +winner+ " won ");
resultTxt.innerHTML = "Player " + player + " won the game!";
resetBtn.style.visibility='visible';
alerted = 1;
}
}
}
if(numblank <= 0 && alerted == 0)
{
//alert("Cat!");
resultTxt.innerHTML = "Tied :("
resetBtn.style.visibility='visible';
alerted = 1;
}
}
function resetGame(){
alerted = 0;
player = 1;
topL.innerHTML = "";
topC.innerHTML = "";
topR.innerHTML = "";
midL.innerHTML = "";
midC.innerHTML = "";
midR.innerHTML = "";
botL.innerHTML = "";
botC.innerHTML = "";
botR.innerHTML = "";
board = ["", "", "", "", "", "", "", "", ""];
resultTxt.innerHTML = "";
resetBtn.style.visibility = 'hidden'
numblank = 9;
}
</script>
</body>
</html>
14. By SR
Made by SR. A two by two tic tac toe game made using JavaScript. ( Source )
<!-- for fun only -->
<html>
<head>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
border: 1px solid black;
}
body {
background: #E9F7CA;
font-size: 50px;
}
#board {
position: absolute;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: table;
width: 200px;
height: 200px;
}
#board > div {
display: table-row;
}
/*selection of child of child of board*/
#board > div > div {
display: table-cell;
background: #F7D488;
text-align: center;
vertical-align: middle;
width:100px;
height:100px;
}
</style>
</head>
<body>
<div id="board">
<div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
</div>
</div>
<script>
//going to beat minimax algo
// whn documnt is ready
window.onload =() =>{
// all 4 tiles/div.
cells = document.querySelectorAll("#board >div>div");
//first player is cpu;
player = "cpu";
// 4 div elements 0-3
cell_index = [0, 1, 2 , 3];
//counting moves
moveCount = 0;
//when game ends
const end = ()=>{
console.log("game over, x wins")
//remove event listener from all 4 divs
for( let i of cells){
i.removeEventListener("click", playermove);
}}
// cpu move
const move =()=>{
//to select from cell_index array
rand = Math.floor(Math.random() * cell_index.length);
// html div object/a cell from cells
mark = cells[cell_index[rand]];
//if cou's turn and place(div) we picked us not already marked
if(player == "cpu" && mark.innerText ==''){
mark.innerText = "x";
//now set value for next move (users)
player = "user"
//remove index after writing to tht area
cell_index.splice(rand,1);
moveCount++;
}else if(moveCount<2){
cell_index.splice(rand,1)
move();}
//we ll not check if this or that is winner as cpu is sleys going to win, lol
if(moveCount >=2){
end()
}
}
//player move ehn click on..
const playermove = (e) =>{
if(e.target.innerText == '' && player == "user"){
e.target.innerText = 0;
player = "cpu";
move();
}}
// adding evnt listelner to all tiles
for( let i of cells){
i.addEventListener("click", playermove)
}
// to init first move by cpu
setTimeout( move, 300);
}
</script>
</body>
<html>
15. By Alquen
Made by Alquen. ( Source )
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Tic Tac Toe</title>
<link rel="stylesheet" href="style.css" />
<link href="https://fonts.googleapis.com/css?family=Rock+Salt" rel="stylesheet">
<script src="app.js"></script>
<style>
*{
margin: 0;
padding: 0;
}
body{
background-color: papayawhip;
}
.box{
width: 33.33%;
height: 100%;
text-align: center;
font-size: 120px;
border: solid;
}
#main{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: grey;
margin: 20px auto 0 auto;
font-family: 'Rock Salt', cursive;
}
.column{
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 33.33%;
flex-direction: row;
}
#sup{
margin: 50px auto 0 auto;
left: 0;
right: 0;
text-align: center;
background-color: rgba(255, 100, 0, 0.7);
position: absolute;
padding: 20px;
font-family: Arial, Helvetica, sans-serif;
display: none;
color: white;
}
#restart{
text-align: center;
margin-bottom: 30px;
padding: 10px;
background-color: burlywood;
}
#score{
text-align: center;
}
input{
margin: 10px;
width: 50px;
height: 20px;
text-align: center;
font-size: 12pt;
}
</style>
</head>
<body>
<div id="score">
Win: <input id="win" value="0" disabled />
Loss: <input id="loss" value="0" disabled />
Tie: <input id="tie" value="0" disabled />
</div>
<div id="sup">
<button id="restart">Restart</button>
<p id="disp"></p>
</div>
<div id="main">
<div class="column">
<div id="0" class="box"></div>
<div id="1" class="box"></div>
<div id="2" class="box"></div>
</div>
<div class="column">
<div id="3" class="box"></div>
<div id="4" class="box"></div>
<div id="5" class="box"></div>
</div>
<div class="column">
<div id="6" class="box"></div>
<div id="7" class="box"></div>
<div id="8" class="box"></div>
</div>
</div>
<script>
"use strict"
const human = "O";
const enemy = "X";
let firstMover;
//Create an array that contains 0 to 8
let globalBoard = [0,1,2,3,4,5,6,7,8];
let gameCounter = 0;
const winCombination = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[6, 4, 2]
]
window.onload = function() {
alert("It's lag at first move because of too much recursion, and this will be fix soon")
//Setting the size of the main box by globally adjusting if phone or desktop.
const winWidth = window.innerWidth;
const winHeight = window.innerHeight;
const boxClass = document.getElementsByClassName("box");
//If the window's width is larger, the main box should depend on the window's height to properly fit;
if (winWidth >= winHeight){
document.getElementById("main").style.width = (winHeight * 0.8) + "px";
document.getElementById("main").style.height = (winHeight * 0.8) + "px";
Array.prototype.forEach.call(boxClass, function(e){ e.style.fontSize = (winHeight * 0.11) + "px"});
document.getElementById("sup").style.width = (winHeight * 0.3) + "px";
document.getElementById("sup").style.height = (winHeight * 0.2) + "px";
document.getElementById("sup").style.fontSize = (winHeight * 0.04) + "pt";
document.getElementById("restart").style.width = (winHeight * 0.15) + "px";
document.getElementById("restart").style.height = (winHeight * 0.08) + "px";
}
else{
//Beware of the spelling of width
document.getElementById("main").style.width = (winWidth * 0.8) + "px";
document.getElementById("main").style.height = (winWidth * 0.8) + "px";
Array.prototype.forEach.call(boxClass, function(e){ e.style.fontSize = (winWidth * 0.11) + "px"});
document.getElementById("sup").style.width = (winWidth * 0.3) + "px";
document.getElementById("sup").style.height = (winWidth * 0.2) + "px";
document.getElementById("sup").style.fontSize = (winWidth * 0.04) + "pt";
document.getElementById("restart").style.width = (winWidth * 0.20) + "px";
document.getElementById("restart").style.height = (winWidth * 0.08) + "px";
}
//Add click listener to the restart button
document.getElementById("restart").addEventListener("click", startGame)
startGame();
function startGame(){
//Run through all the cells and add click listeners
Array.prototype.forEach.call(boxClass, function(e){
e.addEventListener("click", playerTurn);
e.innerText = "";
e.style.backgroundColor = "white";
});
//Reset the declaration of winners
document.getElementById("sup").style.display = "none";
//Reset the globalBoard to an array from 0-8
globalBoard = [0,1,2,3,4,5,6,7,8];
//Determine who to move first
firstMove()
gameCounter++;
}
function playerTurn(cell){
//Called the turn function with the index of cell and the player
turn(cell.target.id, human);
if(!winCheck(globalBoard, human) && !tieCheck()){
turn(enemyMove(), enemy);
}
}
function randomMove(length){
return Math.floor(Math.random() * length)
}
function firstMove(){
//If gameCounter is odd, the enemy attack first
if(gameCounter % 2 == 1){
firstMover = enemy;
//The first move is random to avoid long recursion (at minimax)
turn(randomMove(globalBoard.length), enemy);
}
else{
firstMover = human;
}
}
function turn(cellID, player){
//Set the player's character to the globalBoard and set the main box according to the move
globalBoard[cellID] = player;
document.getElementById(cellID).innerText = player;
document.getElementById(cellID).removeEventListener("click", playerTurn);
//Get the state of winning or tie
let winState = winCheck(globalBoard, player);
let tieState = tieCheck();
if(winState) gameOver(winState);
else if(tieState) gameOver(tieState);
}
function winCheck(board, player){
//The collection of player's moves
let combination = [];
for(let i = 0; i < board.length; i++){
if(board[i] === player){
combination.push(i);
}
}
//Run through the winCombination and check if all elements are present via Array.prototype.every() function
for(let j = 0; j < winCombination.length; j++){
if(winCombination[j].every(function(comb){
return combination.indexOf(comb) != -1;
})){
return {toBeDisplay: winCombination[j], player: player, message: player + " wins"}
}
}
return false;
}
function gameOver(state){
//Get the winner's combination and the winner as arguments then display
let color;
//Human wins
if(state.player == human){
color = "red";
document.getElementById("win").value++;
}
//Enemy wins
else if(state.player == enemy){
color = "blue";
document.getElementById("loss").value++;
}
//Tie
else{
color = "green";
document.getElementById("tie").value++;
}
Array.prototype.forEach.call(state.toBeDisplay, function(e){ document.getElementById(e).style.backgroundColor = color })
//Remove the listener to make unclickable
Array.prototype.forEach.call(boxClass, function(e){
e.removeEventListener("click", playerTurn);
});
//Declare winners
document.getElementById("sup").style.display = "block";
document.getElementById("disp").innerText = state.message;
}
function emptyCells(){
let tempBoard = [];
let i = 0;
//If the type of the cell is still a number (no player move in that cell), collect it as empty cells
while(i < globalBoard.length){
if(typeof globalBoard[i] === "number"){
tempBoard.push(globalBoard[i])
}
i++;
}
return tempBoard;
//Higher order function implementation
//return globalBoard.filter(function(s){return typeof s === "number"});
}
function tieCheck(){
if(emptyCells().length == 0){
return {toBeDisplay: [0,1,2,3,4,5,6,7,8], player: undefined, message: "It's a tie"};
}
return false;
}
function enemyMove(){
//Just a random mover enemy
//return emptyCells()[Math.floor(Math.random() * emptyCells().length)];
return minimax(globalBoard, enemy).index;
}
function minimax(newBoard, player){
//Check for available spots
let availableSpots = emptyCells();
//Terminal State
if(winCheck(newBoard, human)){
return {score : -10};
}
else if(winCheck(newBoard, enemy)){
return {score: 10};
}
else if(tieCheck()){
return {score : 0};
}
//Loop through all available spots
let moves = [];
for(let i = 0; i < availableSpots.length; i++){
let move = {};
move.index = newBoard[availableSpots[i]];
//Assign the spots to the player
newBoard[availableSpots[i]] = player
//If the mover is the enemy, the human should move after
if(player == enemy){
move.score = minimax(newBoard, human).score;
}
else if(player === human){
move.score = minimax(newBoard, enemy).score;
}
//Return to the normal state without assigning
newBoard[availableSpots[i]] = move.index
//Collect the score and the index
moves.push(move);
}
let bestMove;
//If the player is enemy get the biggest score
if(player == enemy){
let bestScore = -Infinity;
for(let i = 0; i < moves.length; i++){
if(moves[i].score > bestScore){
bestScore = moves[i].score;
bestMove = i;
}
}
}
//If the player is human get the lowest score
else if(player == human){
let bestScore = Infinity;
for(let i = 0; i < moves.length; i++){
if(moves[i].score < bestScore){
bestScore = moves[i].score;
bestMove = i;
}
}
}
return moves[bestMove];
}
}
</script>
</body>
</html>
16. By Rull Deef 🐺
Made by Rull Deef 🐺. Two player game that runs only once, so you need to run the program again to play another game. ( Source )
<!DOCTYPE html>
<html>
<head>
<title>Tic tac toe - React practice</title>
<script nomodule src="https://unpkg.com/browser-es-module-loader/dist/babel-browser-build.js"></script>
<script nomodule src="https://unpkg.com/browser-es-module-loader"></script>
<style>
#root, .game {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
h1 {
text-align: center;
color: #333;
}
.cell {
width: 25vmin;
height: 25vmin;
margin: 1px;
border: 1px solid #aaa;
border-radius: 5px;
box-sizing: border-box;
box-shadow: 0 0 2px 1px #ddd;
font-family: monospace;
font-size: 15vmin;
display: inline-flex;
justify-content: center;
align-items: center;
}
.board {
display: grid;
grid-template: ". . ." ". . ." ". . .";
}
.info {
margin-top: 5vmin;
}
</style>
</head>
<body>
<div id="root"></div>
<script>
//</script><script type="module">
import htm from 'https://unpkg.com/htm?module'
import { React, ReactDOM } from 'https://unpkg.com/es-react-production'
const html = htm.bind(React.createElement)
function Cell(props) {
return html`<div className="cell"
onClick=${props.onClick}>${props.value}</div>`
}
class Board extends React.Component {
handleClick(i) {
const cells = this.props.cells.slice()
cells[i] = this.props.nextX? "X" : "O"
}
render() {
const cells = this.props.cells.map((cell, i) => {
return html`<${Cell} key=${i}
value=${this.props.cells[i]}
onClick=${()=>this.props.handle(i)}/>`
})
return html`<div className="board">${cells}</div>`
}
}
class Game extends React.Component {
constructor(props) {
super(props)
this.state = {
cells: new Array(9).fill(null),
nextX: true, winner: null
}
}
getWinner() {
const winpos = [
[0,1,2],[3,4,5],[6,7,8],[0,3,6],
[1,4,7],[2,5,8],[0,4,8],[2,4,6]]
const cells = this.state.cells
for(let pos of winpos) {
let a, b, c; [a, b, c] = pos
if(cells[a] && cells[a] == cells[b]
&& cells[a] == cells[c])
return cells[a]
}
return null
}
handleClick(i) {
const cells = this.state.cells.slice()
if(cells[i]) return
const w = this.getWinner()
if(!w) {
cells[i] = this.state.nextX? "X" : "O"
this.setState({cells, nextX: !this.state.nextX})
setTimeout(() => {
const u = this.getWinner()
if(u) this.setState({winner: u})
}, 1)
} else this.setState({winner: w})
}
render() {
let info = (this.state.nextX? "X" : "O")
+ "'s turn now!"
if(this.state.winner)
info = this.state.winner + " won!"
return html`<div className="game">
<h1>TIC TAC TOE GAME</h1>
<${Board} cells=${this.state.cells}
nextX=${this.state.nextX}
handle=${this.handleClick.bind(this)}/>
<small className="info">${info}</small>
</div>`
}
}
ReactDOM.render(
html`<${Game}/>`,
document.querySelector("#root")
)
</script>
</body>
</html>
17. By Nikky Amresh
Made by Nikky Amresh. The game has two modes, human vs human or human vs computer. ( Source )
<!DOCtype html>
<html>
<head>
<title>Tic Tac Toe</title>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<style>
body {
background-color:#000;
}
h1{
color:#4CAF50;
text-align:center;
text-decoration:underline ;
}
.h1{
position:fixed;
top:180px;
align:center;
}
#tt{
position:fixed;
color:#4CAF50;
left:40%;
top:330px;
}
#screen{
position:fixed;
width:100%;
height:1000px;
background-color:#0f0f0f;
z-index:1;
align:center;
}
select{
background-color: #4CAF50;
border: none;
color: white;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
position:absolute;
top:300px;
left:30%;
height:40px;
width:40%;
}
input{
width:80px;
height:80px;
background-color:#4CAF50;
color:#fff;
font-size:50px;
}
#reset{
position:fixed;
width:100%;
opacity:0;
display:none;
background-color:#000;
height:1000px;
}
.vote{
color:#fff;
position:fixed;
bottom:15px;
font-size:20px;
font-style: oblique;
}
.btn{
border: none;
position:fixed;
color: white;
left:30%;
display:none;
padding: 15px 32px;
width:150px;
text-decoration: none;
margin: 4px 2px;
cursor: pointer;
height:40px;
font-size:20px;
}
.w1{
top:350px;
background-color: #0cf;
color:#000;
width:200px;
left:20%;
}
.p1{
position:fixed;
color:#4CAF50;
left:10px;
top:330px;
display:none;
}
.p2{
position:fixed;
color:#4CAF50;
right:10px;
top:330px;
}
.r{
z-index:1;
top:400px;
background-color: #4CAF50;
}
.l{
top:350px;
background-color: red;
}
.w{
top:350px;
background-color: #0cf;
color:#000;
}
.vote a{
color:#4CAF50;
}
.d{
z-index:1;
top:350px;
background-color: #fff;
color:#000;
}
</style>
</head>
<body onload="mode();">
<div id="screen">
<h1 class="h1" align="center">Please Choose Game Mode</h1>
<select id="mode">
<option Selected>Choose Mode</option>
<option value="1">Computer Vs Human</option>
<option value="2">Human Vs Human</option>
<option disabled value="3">Computer Vs Computer (comming soon)</option>
</select>
</div>
<h1>Tic Tac Toe </h1>
<div id="reset"></div>
<button class="btn d" id="draw">Draw!</button>
<button class="btn l" id="loss">You Lost!</button>
<button class="btn w" id="win">You Won!</button>
<button class="btn w1" id="p2win">Player 1 (O)Won!</button>
<button class="btn w1" id="p1win">Player 2 (X)Won!</button>
<button class="btn r" id="resetbtn" onclick="resetclick()">Reset</button>
<div id="turn" style="display:none;">
<span id="p1" class="p1">Player2's (X)Turn</span>
<span id="p2" class="p2">Player1's (O)Turn</span></div>
<div id="turnc" style="display:none;">
<span id="ct" class="p1">Computer's' Turn</span>
<span id="yt" class="p2">Your Turn</span></div>
<span id="tt"></span>
<form align="center" >
<input type="button" id="b1" value=" " onclick="btn1(mode)">
<input type="button" id="b2" value=" " onclick="btn2(mode)">
<input type="button" id="b3" value=" " onclick="btn3(mode)"><br />
<input type="button" id="b4" value=" " onclick="btn4(mode)">
<input type="button" id="b5" value=" " onclick="btn5(mode)">
<input type="button" id="b6" value=" " onclick="btn6(mode)"><br />
<input type="button" id="b7" value=" " onclick="btn7(mode)">
<input type="button" id="b8" value=" " onclick="btn8(mode)">
<input type="button" id="b9" value=" " onclick="btn9(mode)">
</form>
<marquee direction="left" scrollamount="9" class="vote">if you really enjoyed my code. Then please support me <a onclick="alert('Thanks for your support 😊🙏🏻👍🏻')" href="https://www.sololearn.com/Discuss/578541/">here</a> </marquee>
<script>
function turnp(){$("#tt").html("Total Moves: "+moveCount),mode==2?$("#turn").show():$("#turn").hide();mode==1?$("#turnc").show():$("#turnc").hide();0==turn?($("#p2").show(),$("#p1").hide()):($("#p1").show(),$("#p2").hide());0==turn?($("#yt").show(),$("#ct").hide()):($("#ct").show(),$("#yt").hide())}function mode(){$("#mode").change(function(){$("#screen").hide(),mode=$("#mode").val(),mode==2?$("#turn").show():$("#turn").hide();mode==1?$("#turnc").show():$("#turnc").hide()})}function btn1(){" "==$("#b1").val()&&0==turn&&1==mode?($("#b1").attr("value"," X "),sqr1T=1,turn=1,turrn(),check()):" "==$("#b1").val()&&1==turn&&2==mode?($("#b1").attr("value"," X "),sqr1T=1,turn=0,turrn(),p1c()):" "==$("#b1").val()&&0==turn&&2==mode&&($("#b1").attr("value"," O "),sqr1T=1,turn=1,turrn(),p1c()),drawCheck()}function btn2(){" "==$("#b2").val()&&0==turn&&1==mode?($("#b2").attr("value"," X "),sqr2T=1,turn=1,turrn(),check()):" "==$("#b2").val()&&1==turn&&2==mode?($("#b2").attr("value"," X "),sqr2T=1,turn=0,turrn(),p1c()):" "==$("#b2").val()&&0==turn&&2==mode&&($("#b2").attr("value"," O "),sqr2T=1,turn=1,turrn(),p1c()),drawCheck()}function btn3(){" "==$("#b3").val()&&0==turn&&1==mode?($("#b3").attr("value"," X "),sqr3T=1,turn=1,turrn(),check()):" "==$("#b3").val()&&1==turn&&2==mode?($("#b3").attr("value"," X "),sqr3T=1,turn=0,turrn(),p1c()):" "==$("#b3").val()&&0==turn&&2==mode&&($("#b3").attr("value"," O "),sqr3T=1,turn=1,turrn(),p1c()),drawCheck()}function btn4(){" "==$("#b4").val()&&0==turn&&1==mode?($("#b4").attr("value"," X "),sqr4T=1,turn=1,turrn(),check()):" "==$("#b4").val()&&1==turn&&2==mode?($("#b4").attr("value"," X "),sqr4T=1,turn=0,turrn(),p1c()):" "==$("#b4").val()&&0==turn&&2==mode&&($("#b4").attr("value"," O "),sqr4T=1,turn=1,turrn(),p1c()),drawCheck()}function btn5(){" "==$("#b5").val()&&0==turn&&1==mode?($("#b5").attr("value"," X "),sqr5T=1,turn=1,turrn(),check()):" "==$("#b5").val()&&1==turn&&2==mode?($("#b5").attr("value"," X "),sqr5T=1,turn=0,turrn(),p1c()):" "==$("#b5").val()&&0==turn&&2==mode&&($("#b5").attr("value"," O "),sqr5T=1,turn=1,turrn(),p1c()),drawCheck()}function btn6(){" "==$("#b6").val()&&0==turn&&1==mode?($("#b6").attr("value"," X "),sqr6T=1,turn=1,turrn(),check()):" "==$("#b6").val()&&1==turn&&2==mode?($("#b6").attr("value"," X "),sqr6T=1,turn=0,turrn(),p1c()):" "==$("#b6").val()&&0==turn&&2==mode&&($("#b6").attr("value"," O "),sqr6T=1,turn=1,turrn(),p1c()),drawCheck()}function btn7(){" "==$("#b7").val()&&0==turn&&1==mode?($("#b7").attr("value"," X "),sqr7T=1,turn=1,turrn(),check()):" "==$("#b7").val()&&1==turn&&2==mode?($("#b7").attr("value"," X "),sqr7T=1,turn=0,turrn(),p1c()):" "==$("#b7").val()&&0==turn&&2==mode&&($("#b7").attr("value"," O "),sqr7T=1,turn=1,turrn(),p1c()),drawCheck()}function btn8(){" "==$("#b8").val()&&0==turn&&1==mode?($("#b8").attr("value"," X "),sqr8T=1,turn=1,turrn(),check()):" "==$("#b8").val()&&1==turn&&2==mode?($("#b8").attr("value"," X "),sqr8T=1,turn=0,turrn(),p1c()):" "==$("#b8").val()&&0==turn&&2==mode&&($("#b8").attr("value"," O "),sqr8T=1,turn=1,turrn(),p1c()),drawCheck()}function btn9(){" "==$("#b9").val()&&0==turn&&1==mode?($("#b9").attr("value"," X "),sqr9T=1,turn=1,turrn(),check()):" "==$("#b9").val()&&1==turn&&2==mode?($("#b9").attr("value"," X "),sqr9T=1,turn=0,turrn(),p1c()):" "==$("#b9").val()&&0==turn&&2==mode&&($("#b9").attr("value"," O "),sqr9T=1,turn=1,turrn(),p1c()),drawCheck()}function turrn(){sqr1=$("#b1").val(),sqr2=$("#b2").val(),sqr3=$("#b3").val(),sqr4=$("#b4").val(),sqr5=$("#b5").val(),sqr6=$("#b6").val(),sqr7=$("#b7").val(),sqr8=$("#b8").val(),sqr9=$("#b9").val()}function check(){" X "==sqr1&&" X "==sqr2&&" X "==sqr3?(wb(),reset()):" X "==sqr4&&" X "==sqr5&&" X "==sqr6?(wb(),reset()):" X "==sqr7&&" X "==sqr8&&" X "==sqr9?(wb(),reset()):" X "==sqr1&&" X "==sqr5&&" X "==sqr9?(wb(),reset()):" X "==sqr1&&" X "==sqr4&&" X "==sqr7?(wb(),reset()):" X "==sqr2&&" X "==sqr5&&" X "==sqr8?(wb(),reset()):" X "==sqr3&&" X "==sqr6&&" X "==sqr9?(wb(),reset()):" X "==sqr1&&" X "==sqr5&&" X "==sqr9?(wb(),reset()):" X "==sqr3&&" X "==sqr5&&" X "==sqr7?(wb(),reset()):(winCheck(),check2(),drawCheck())}function check2(){turrn(),drawCheck()," O "==sqr1&&" O "==sqr2&&" O "==sqr3?(lb() ,reset()):" O "==sqr4&&" O "==sqr5&&" O "==sqr6?(lb() ,reset()):" O "==sqr7&&" O "==sqr8&&" O "==sqr9?(lb() ,reset()):" O "==sqr1&&" O "==sqr5&&" O "==sqr9?(lb() ,reset()):" O "==sqr1&&" O "==sqr4&&" O "==sqr7?(lb() ,reset()):" O "==sqr2&&" O "==sqr5&&" O "==sqr8?(lb() ,reset()):" O "==sqr3&&" O "==sqr6&&" O "==sqr9?(lb() ,reset()):" O "==sqr1&&" O "==sqr5&&" O "==sqr9?(lb() ,reset()):" O "==sqr3&&" O "==sqr5&&" O "==sqr7&&(lb() ,reset())}function p1c(){" X "==sqr1&&" X "==sqr2&&" X "==sqr3?(p1w(),reset()):" X "==sqr4&&" X "==sqr5&&" X "==sqr6?(p1w(),reset()):" X "==sqr7&&" X "==sqr8&&" X "==sqr9?(p1w(),reset()):" X "==sqr1&&" X "==sqr5&&" X "==sqr9?(p1w(),reset()):" X "==sqr1&&" X "==sqr4&&" X "==sqr7?(p1w(),reset()):" X "==sqr2&&" X "==sqr5&&" X "==sqr8?(p1w(),reset()):" X "==sqr3&&" X "==sqr6&&" X "==sqr9?(p1w(),reset()):" X "==sqr1&&" X "==sqr5&&" X "==sqr9?(p1w(),reset()):" X "==sqr3&&" X "==sqr5&&" X "==sqr7?(p1w(),reset()):(p2c(),drawCheck())}function p2c(){turrn(),drawCheck()," O "==sqr1&&" O "==sqr2&&" O "==sqr3?(p2w(),reset()):" O "==sqr4&&" O "==sqr5&&" O "==sqr6?(p2w(),reset()):" O "==sqr7&&" O "==sqr8&&" O "==sqr9?(p2w(),reset()):" O "==sqr1&&" O "==sqr5&&" O "==sqr9?(p2w(),reset()):" O "==sqr1&&" O "==sqr4&&" O "==sqr7?(p2w(),reset()):" O "==sqr2&&" O "==sqr5&&" O "==sqr8?(p2w(),reset()):" O "==sqr3&&" O "==sqr6&&" O "==sqr9?(p2w(),reset()):" O "==sqr1&&" O "==sqr5&&" O "==sqr9?(p2w(),reset()):" O "==sqr3&&" O "==sqr5&&" O "==sqr7&&(p2w(),reset())}function drawCheck(){turnp(),turrn(),9==(moveCount=sqr1T+sqr2T+sqr3T+sqr4T+sqr5T+sqr6T+sqr7T+sqr8T+sqr9T)&&(reset(),db())}function winCheck(){check2()," O "==sqr1&&" O "==sqr2&&0==sqr3T&&1==turn?($("#b3").attr("value"," O "),sqr3T=1,turn=0):" O "==sqr2&&" O "==sqr3&&0==sqr1T&&1==turn?($("#b1").attr("value"," O "),sqr1T=1,turn=0):" O "==sqr4&&" O "==sqr5&&0==sqr6T&&1==turn?($("#b6").attr("value"," O "),sqr6T=1,turn=0):" O "==sqr5&&" O "==sqr6&&0==sqr4T&&1==turn?($("#b4").attr("value"," O "),sqr4T=1,turn=0):" O "==sqr7&&" O "==sqr8&&0==sqr9T&&1==turn?($("#b9").attr("value"," O "),sqr9T=1,turn=0):" O "==sqr8&&" O "==sqr9&&0==sqr7T&&1==turn?($("#b7").attr("value"," O "),sqr7T=1,turn=0):" O "==sqr1&&" O "==sqr5&&0==sqr9T&&1==turn?($("#b9").attr("value"," O "),sqr9T=1,turn=0):" O "==sqr5&&" O "==sqr9&&0==sqr1T&&1==turn?($("#b1").attr("value"," O "),sqr1T=1,turn=0):" O "==sqr3&&" O "==sqr5&&0==sqr7T&&1==turn?($("#b7").attr("value"," O "),sqr7T=1,turn=0):" O "==sqr7&&" O "==sqr5&&0==sqr3T&&1==turn?($("#b3").attr("value"," O "),sqr3T=1,turn=0):" O "==sqr1&&" O "==sqr3&&0==sqr2T&&1==turn?($("#b2").attr("value"," O "),sqr2T=1,turn=0):" O "==sqr4&&" O "==sqr6&&0==sqr5T&&1==turn?($("#b5").attr("value"," O "),sqr5T=1,turn=0):" O "==sqr7&&" O "==sqr9&&0==sqr8T&&1==turn?($("#b8").attr("value"," O "),sqr8T=1,turn=0):" O "==sqr1&&" O "==sqr7&&0==sqr4T&&1==turn?($("#b4").attr("value"," O "),sqr4T=1,turn=0):" O "==sqr2&&" O "==sqr8&&0==sqr5T&&1==turn?($("#b5").attr("value"," O "),sqr5T=1,turn=0):" O "==sqr3&&" O "==sqr9&&0==sqr6T&&1==turn?($("#b6").attr("value"," O "),sqr6T=1,turn=0):" O "==sqr1&&" O "==sqr5&&0==sqr9T&&1==turn?($("#b9").attr("value"," O "),sqr9T=1,turn=0):" O "==sqr4&&" O "==sqr7&&0==sqr1T&&1==turn?($("#b1").attr("value"," O "),sqr1T=1,turn=0):" O "==sqr5&&" O "==sqr8&&0==sqr2T&&1==turn?($("#b2").attr("value"," O "),sqr2T=1,turn=0):" O "==sqr6&&" O "==sqr9&&0==sqr3T&&1==turn?($("#b3").attr("value"," O "),sqr3T=1,turn=0):" O "==sqr1&&" O "==sqr4&&0==sqr7T&&1==turn?($("#b7").attr("value"," O "),sqr7T=1,turn=0):" O "==sqr2&&" O "==sqr5&&0==sqr8T&&1==turn?($("#b8").attr("value"," O "),sqr8T=1,turn=0):" O "==sqr3&&" O "==sqr6&&0==sqr9T&&1==turn?($("#b9").attr("value"," O "),sqr9T=1,turn=0):" O "==sqr1&&" O "==sqr9&&0==sqr5T&&1==turn?($("#b5").attr("value"," O "),sqr5T=1,turn=0):" O "==sqr3&&" O "==sqr7&&0==sqr5T&&1==turn?($("#b5").attr("value"," O "),sqr5T=1,turn=0):computer(),check2()}function computer(){check2()," X "==sqr1&&" X "==sqr2&&0==sqr3T&&1==turn?($("#b3").attr("value"," O "),sqr3T=1,turn=0):" X "==sqr2&&" X "==sqr3&&0==sqr1T&&1==turn?($("#b1").attr("value"," O "),sqr1T=1,turn=0):" X "==sqr4&&" X "==sqr5&&0==sqr6T&&1==turn?($("#b6").attr("value"," O "),sqr6T=1,turn=0):" X "==sqr5&&" X "==sqr6&&0==sqr4T&&1==turn?($("#b4").attr("value"," O "),sqr4T=1,turn=0):" X "==sqr7&&" X "==sqr8&&0==sqr9T&&1==turn?($("#b9").attr("value"," O "),sqr9T=1,turn=0):" X "==sqr8&&" X "==sqr9&&0==sqr7T&&1==turn?($("#b7").attr("value"," O "),sqr7T=1,turn=0):" X "==sqr1&&" X "==sqr5&&0==sqr9T&&1==turn?($("#b9").attr("value"," O "),sqr9T=1,turn=0):" X "==sqr5&&" X "==sqr9&&0==sqr1T&&1==turn?($("#b1").attr("value"," O "),sqr1T=1,turn=0):" X "==sqr3&&" X "==sqr5&&0==sqr7T&&1==turn?($("#b7").attr("value"," O "),sqr7T=1,turn=0):" X "==sqr7&&" X "==sqr5&&0==sqr3T&&1==turn?($("#b3").attr("value"," O "),sqr3T=1,turn=0):" X "==sqr1&&" X "==sqr3&&0==sqr2T&&1==turn?($("#b2").attr("value"," O "),sqr2T=1,turn=0):" X "==sqr4&&" X "==sqr6&&0==sqr5T&&1==turn?($("#b5").attr("value"," O "),sqr5T=1,turn=0):" X "==sqr7&&" X "==sqr9&&0==sqr8T&&1==turn?($("#b8").attr("value"," O "),sqr8T=1,turn=0):" X "==sqr1&&" X "==sqr7&&0==sqr4T&&1==turn?($("#b4").attr("value"," O "),sqr4T=1,turn=0):" X "==sqr2&&" X "==sqr8&&0==sqr5T&&1==turn?($("#b5").attr("value"," O "),sqr5T=1,turn=0):" X "==sqr3&&" X "==sqr9&&0==sqr6T&&1==turn?($("#b6").attr("value"," O "),sqr6T=1,turn=0):" X "==sqr1&&" X "==sqr5&&0==sqr9T&&1==turn?($("#b9").attr("value"," O "),sqr9T=1,turn=0):" X "==sqr4&&" X "==sqr7&&0==sqr1T&&1==turn?($("#b1").attr("value"," O "),sqr1T=1,turn=0):" X "==sqr5&&" X "==sqr8&&0==sqr2T&&1==turn?($("#b2").attr("value"," O "),sqr2T=1,turn=0):" X "==sqr6&&" X "==sqr9&&0==sqr3T&&1==turn?($("#b3").attr("value"," O "),sqr3T=1,turn=0):" X "==sqr1&&" X "==sqr4&&0==sqr7T&&1==turn?($("#b7").attr("value"," O "),sqr7T=1,turn=0):" X "==sqr2&&" X "==sqr5&&0==sqr8T&&1==turn?($("#b8").attr("value"," O "),sqr8T=1,turn=0):" X "==sqr3&&" X "==sqr6&&0==sqr9T&&1==turn?($("#b9").attr("value"," O "),sqr9T=1,turn=0):" X "==sqr1&&" X "==sqr9&&0==sqr5T&&1==turn?($("#b5").attr("value"," O "),sqr5T=1,turn=0):" X "==sqr3&&" X "==sqr7&&0==sqr5T&&1==turn?($("#b5").attr("value"," O "),sqr5T=1,turn=0):AI(),check2()}function AI(){turrn()," "==$("#b5").val()&&1==turn?($("#b5").attr("value"," O "),turn=0,sqr5T=1):" "==$("#b1").val()&&1==turn?($("#b1").attr("value"," O "),turn=0,sqr1T=1):" "==$("#b9").val()&&1==turn?($("#b9").attr("value"," O "),turn=0,sqr9T=1):" "==$("#b6").val()&&1==turn?($("#b6").attr("value"," O "),turn=0,sqr6T=1):" "==$("#b2").val()&&1==turn?($("#b2").attr("value"," O "),turn=0,sqr2T=1):" "==$("#b8").val()&&1==turn?($("#b8").attr("value"," O "),turn=0,sqr8T=1):" "==$("#b3").val()&&1==turn?($("#b3").attr("value"," O "),turn=0,sqr3T=1):" "==$("#b7").val()&&1==turn?($("#b7").attr("value"," O "),turn=0,sqr7T=1):" "==$("#b4").val()&&1==turn&&($("#b4").attr("value"," O "),turn=0,sqr4T=1),check2()}function resetclick(){$("#b1").attr("value"," "),$("#b2").attr("value"," "),$("#b3").attr("value"," "),$("#b4").attr("value"," "),$("#b5").attr("value"," "),$("#b6").attr("value"," "),$("#b7").attr("value"," "),$("#b8").attr("value"," "),$("#b9").attr("value"," "),$("#win").hide(),$("#loss").hide(),$("#p1win").hide(),$("#p2win").hide(),$("#draw").hide(),$("#reset").hide(),$("#resetbtn").hide(), sqr1T=0,sqr2T=0,sqr3T=0,sqr4T=0,sqr5T=0,sqr6T=0,sqr7T=0,sqr8T=0,sqr9T=0,turrn(),turn=0,moveCount=0}function reset(){turnp(),$("#reset").show(), $("#resetbtn").show(),$("#turn").hide(), 0==turn?($("#p2").show(),$("#p1").hide()):($("#p1").show(),$("#p2").hide())}function wb(){$("#win").show()}function p1w(){$("#p1win").show()}function p2w() {$("#p2win").show()}function lb(){$("#loss").show()}function db(){$("#draw").show()}function resetter(){reset()}var sqr1,sqr2,sqr3,sqr4,sqr5,sqr6,sqr7,sqr8,sqr9,sqr1T=0,sqr2T=0,sqr3T=0,sqr4T=0,sqr5T=0,sqr6T=0,sqr7T=0,sqr8T=0,sqr9T=0,moveCount=0,turn=0;
</script>
</body>
</html>
18. By Igor Makarsky
Made by Igor Makarsky. ( Source )
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style>
.square {
float:left;
position: relative;
width:30%;
padding-bottom:30%; /* it equals width for a 1:1 aspect ratio */
margin:1.66%;
background-color:white;
}
.content {
position:absolute;
height:100%;
width:100%;
font-size:19.0vw;
}
body {
color:#000;
text-align:center;
background:#ECECEC;
}
th, td {
text-align:center;
}
dialog {
top:30%;
z-index: 1;
}
</style>
</head>
<body>
<dialog id="dialog">
<h2>It's a draw!</h2>
<p>Click OK to continue</p>
<button id="dialogBtn" class="btn btn-info">OK</button>
</dialog>
<div class="container">
<table class="table">
<thead>
<tr>
<th>X</th>
<th>Turn</th>
<th>O</th>
</tr>
</thead>
<tbody>
<tr>
<td><span id="xScore">0</span></td>
<td id="header">X</td>
<td><span id="oScore">0</span></td>
</tr>
</tbody>
</table>
<!-- 1st row -->
<div class="square">
<div class="content"></div>
</div>
<div class="square">
<div class="content"></div>
</div>
<div class="square">
<div class="content"></div>
</div>
<!-- 2nd row -->
<div class="square">
<div class="content"></div>
</div>
<div class="square">
<div class="content"></div>
</div>
<div class="square">
<div class="content"></div>
</div>
<!-- 3rd row -->
<div class="square">
<div class="content"></div>
</div>
<div class="square">
<div class="content"></div>
</div>
<div class="square">
<div class="content"></div>
</div>
<div>
<button id="newGame" class="btn btn-info" onclick="startNewGame()">New game</button>
</div>
<div class="panel panel-default" style="margin-top:5px">
<div class="panel-body">Made by <a href="https://www.sololearn.com/Profile/779917">Igor Makarsky</a></div>
</div>
</div>
<script>
var turn = "X";
var next = "O";
var isOver = false;
var header = document.getElementById("header");
var xScore = document.getElementById("xScore");
var oScore = document.getElementById("oScore");
var elements = document.getElementsByClassName("content");
document.getElementById("newGame").style.visibility = "hidden";
</script>
<script>
var UI = (function() {
var DOMstrings = {
dialog: 'dialog'
};
return {
showDialog: function() {
document.getElementById(DOMstrings.dialog).show();
},
closeDialog: function() {
document.getElementById(DOMstrings.dialog).close();
},
restart: function() {
// Remove winner colors.
// Remove X O signs.
// Reset the score
// Reset the turn. The loser goes first.
}
};
})();
var Game = (function() {
var isOver = false;
return {
restart: function() {
isOver = false;
}
};
})();
var Controller = (function(UICtrl, GameCtrl) {
var setupEventListeners = function() {
document.getElementById('dialogBtn').addEventListener('click', () => {
UICtrl.closeDialog();
});
let squares = document.getElementsByClassName("content");
[].forEach.call(squares, (el) => {
el.onclick = (e) => putSign(e.target);
});
};
return {
init: function() {
setupEventListeners();
}
};
})(UI, Game);
document.addEventListener('DOMContentLoaded', Controller.init);
function putSign(e) {
if (e.innerHTML === "") {
e.innerHTML = turn;
turn = next;
next = e.innerHTML;
header.innerHTML = turn;
var result = null;
if (!isOver) {
result = getWinner();
}
if (result === "draw" && isOver === false) {
isOver = true;
document.getElementById("newGame").style.visibility = "visible";
UI.showDialog();
}
if (result === "X" && isOver === false) {
xScore.innerHTML++;
isOver = true;
document.getElementById("newGame").style.visibility = "visible";
}
if (result === "O" && isOver === false) {
oScore.innerHTML++;
isOver = true;
document.getElementById("newGame").style.visibility = "visible";
}
}
}
function getWinner() {
if (elements[0].innerHTML == elements[1].innerHTML &&
elements[0].innerHTML == elements[2].innerHTML &&
elements[0].innerHTML !== "") {
colorBackground(elements[0]);
colorBackground(elements[1]);
colorBackground(elements[2]);
return elements[0].innerHTML;
}
if (elements[3].innerHTML == elements[4].innerHTML &&
elements[3].innerHTML == elements[5].innerHTML &&
elements[3].innerHTML !== "") {
colorBackground(elements[3]);
colorBackground(elements[4]);
colorBackground(elements[5]);
return elements[3].innerHTML;
}
if (elements[6].innerHTML == elements[7].innerHTML &&
elements[6].innerHTML == elements[8].innerHTML &&
elements[6].innerHTML !== "") {
colorBackground(elements[6]);
colorBackground(elements[7]);
colorBackground(elements[8]);
return elements[6].innerHTML;
}
if (elements[0].innerHTML == elements[3].innerHTML &&
elements[0].innerHTML == elements[6].innerHTML &&
elements[0].innerHTML !== "") {
colorBackground(elements[0]);
colorBackground(elements[3]);
colorBackground(elements[6]);
return elements[0].innerHTML;
}
if (elements[1].innerHTML == elements[4].innerHTML &&
elements[1].innerHTML == elements[7].innerHTML &&
elements[1].innerHTML !== "") {
colorBackground(elements[1]);
colorBackground(elements[4]);
colorBackground(elements[7]);
return elements[1].innerHTML;
}
if (elements[2].innerHTML == elements[5].innerHTML &&
elements[2].innerHTML == elements[8].innerHTML &&
elements[2].innerHTML !== "") {
colorBackground(elements[2]);
colorBackground(elements[5]);
colorBackground(elements[8]);
return elements[2].innerHTML;
}
if (elements[0].innerHTML == elements[4].innerHTML &&
elements[0].innerHTML == elements[8].innerHTML &&
elements[0].innerHTML !== "") {
colorBackground(elements[0]);
colorBackground(elements[4]);
colorBackground(elements[8]);
return elements[0].innerHTML;
}
if (elements[2].innerHTML == elements[4].innerHTML &&
elements[2].innerHTML == elements[6].innerHTML &&
elements[2].innerHTML !== "") {
colorBackground(elements[2]);
colorBackground(elements[4]);
colorBackground(elements[6]);
return elements[2].innerHTML;
}
var filled = 0;
for (var i = 0; i < elements.length; i++) {
if (elements[i].innerHTML == "X" || elements[i].innerHTML == "O") {
filled++;
}
if (filled == 9) {
return "draw";
}
}
return false;
}
function colorBackground(el) {
el.style.backgroundColor = "#b3ffb3";
}
function startNewGame() {
for (var i = 0; i < elements.length; i++) {
elements[i].innerHTML = "";
elements[i].style.backgroundColor = "#FFF";
}
turn = "X";
next = "O";
header.innerHTML = turn;
isOver = false;
document.getElementById("newGame").style.visibility = "hidden";
}
</script>
</body>
</html>
19. By David (DonDejvo)
Made by David (DonDejvo). Simple JavaScript AI Tic tac toe game. ( Source )
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=0">
<title>Page Title</title>
<style>
* {
box-sizing: border-box;
}
html, body {
user-select: none;
-webkit-user-select: none;
font-family: Arial;
}
#board {
position: relative;
width: 100%;
display: grid;
grid-template-columns: repeat(3, 1fr);
border: 1vw solid black;
}
#board > div::before {
content: "";
padding-bottom: 100%;
}
.board-cell {
border: 1vw solid black;
display: flex;
justify-content: center;
align-items: center;
font-size: 20vw;
}
#msg_container {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
width: 60%;
height: 20vw;
border: 1vw solid black;
left: 20%;
top: 80vw;
background: silver;
font-size: 10vw;
}
</style>
</head>
<body>
<div id="board">
<div id="msg_container">
<div id="msg"></div>
</div>
</div>
<script>
let cells, msg_con, msg;
const winning = [
[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]
];
const x = "<span style='color:blue;'>x</span>";
const o = "<span style='color:red;'>o</span>";
const board = [];
let finished = false;
let turnCount = 0, starting = 0, playing = 0;
const players = [0, 1]; // human = 0, bot = 1
onload = init;
function place(idx) {
if(board[idx] != -1 || finished) {
return;
}
board[idx] = playing;
cells[idx].innerHTML = playing == 0 ? x : o;
++turnCount;
if(checkBoard(board, turnCount, true) == -1) {
playing = (playing + 1) % 2;
next();
}
}
function switchPlayers() {
[players[0], players[1]] = [players[1], players[0]];
}
function newGame() {
msg_con.style.display = "none";
for(let i = 0; i < 9; ++i) {
board[i] = -1;
cells[i].innerHTML = "";
}
turnCount = 0;
finished = false;
playing = starting;
next();
}
function gameOver(except) {
for(let i = 0; i < 9; ++i) {
const symbol = board[i];
if(!except.includes(i) && symbol != -1) {
cells[i].innerHTML = "<span style='color:grey;'>" + (symbol == 0 ? "x" : "o") + "</span>";
}
}
finished = true;
msg_con.style.display = "flex";
msg.innerHTML = except.length ? (playing == 0 ? x : o) + " won" : "It\'s draw";
setTimeout(() => {
switchPlayers();
newGame();
}, 3000);
}
function checkBoard(board, turnCount, real = false) {
for(const c of winning) {
const symbol = board[c[0]];
if(symbol != -1 && symbol == board[c[1]] && symbol == board[c[2]]) {
if(real) {
gameOver(c);
}
return symbol;
}
}
if(turnCount == 9) {
if(real) {
gameOver([]);
}
return -2;
}
return -1;
}
function onCellClick(idx) {
if(finished || players[playing] == 1) {
return;
}
place(idx);
}
function init() {
const grid = document.getElementById("board");
cells = document.getElementsByClassName("board-cell");
msg_con = document.getElementById("msg_container");
msg = document.getElementById("msg");
for(let i = 0; i < 9; ++i) {
const cell = document.createElement("div");
cell.classList.add("board-cell");
cell.onclick = () => onCellClick(i);
grid.appendChild(cell);
}
newGame();
}
function next() {
if(players[playing] == 1) {
playBot();
}
}
function playBot() {
if(turnCount == 0) {
place(Math.floor(Math.random() * 9));
} else {
let idx;
calc(turnCount, playing, true);
place(idx);
function calc(t, p, setValue = false) {
const res = checkBoard(board, t);
switch(res) {
case 0: return 1;
case 1: return -1;
case -2: return 0;
default: break;
}
let best, desired, other;
if(p == 0) {
best = -Infinity;
desired = 1;
other = 1;
} else {
best = Infinity;
desired = -1;
other = 0;
}
for (let i = 0; i < 9; ++i) {
if (board[i] == -1) {
board[i] = p;
const temp = calc(t + 1, other, false);
const val = p == 0 ? Math.max(temp, best) : Math.min(temp, best);
board[i] = -1;
if (val != best) {
if (setValue) {
idx = i;
}
if (val == desired) {
return val;
}
best = val;
}
}
}
return best;
}
}
}
</script>
</body>
</html>
20. By Salif Mehmed 🇹🇷🇧🇬
Made by Salif Mehmed 🇹🇷🇧🇬. ( Source )
<!DOCTYPE html>
<html>
<head>
<title>Tic Tac Toe</title>
<style>
body {
background-color:blue;
color:white;
}
#tbl {
margin-top:50px;
}
#tbl td {
background-color:white;
border:3px solid blue;
color:black;
border-radius:10px;
height:50px;
width:50px;
text-align:center;
font-size:20pt;
font-weight:bolder;
}
@keyframes spinx {
from {
transform:rotateX(0deg);
}
to {
transform:rotateX(360deg);
}
}
@keyframes spiny {
from {
transform:rotateY(0deg);
}
to {
transform:rotateY(360deg);
}
}
@keyframes spinz {
from {
transform:rotateZ(0deg);
}
to {
transform:rotateZ(360deg);
}
}
@keyframes spinall {
from {
transform:rotateX(0deg) rotateY(0deg) rotateZ(0deg);
}
to {
transform:rotateX(360deg) rotateY(360deg) rotateZ(360deg);
}
}
.f {
margin-top:60px;
}
input {
padding: 10px 20px;
display: inline-block;
background-color:#007bff;
color:white;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
input:focus {
outline:none;
background-color:#0069d9;
}
</style>
</head>
<body>
<h1 id="or" align="center"></h1>
<table border="0" id="tbl" align="center" cellpadding="10" cellspacing="0">
<tr><td id="t1"></td><td id="t2"></td><td id="t3"></td></tr>
<tr><td id="t4"></td><td id="t5"></td><td id="t6"></td></tr>
<tr><td id="t7"></td><td id="t8"></td><td id="t9"></td></tr>
</table>
<div class="f" align="center">
<input type="button" onclick="sm('x')" value="X">
<input type="button" onclick="sm('y')" value="Y">
<input type="button" onclick="sm('z')" value="Z">
<input type="button" onclick="sm('0')" value="0">
<input type="button" onclick="sm('all')" value="all">
</div>
<script>
var xo=false, a=["", "", "", "", "", "", "", "", ""], p=false, ab=0, vor="0-0", vorx=0, voro=0;
Object.prototype.text=function(v) {
this.innerText=v;
};
Object.prototype.cl=function() {
if(p || this.textv()) {return;}
this.text(xof());
this.style.backgroundColor="red";
this.style.color="white";
a[this.id.charAt(1)-1]=xo?"x":"0";
switch(true){
case a[0]+a[1]+a[2]==="xxx" : s("x"); return; break;
case a[3]+a[4]+a[5]==="xxx" : s("x"); return; break;
case a[6]+a[7]+a[8]==="xxx" : s("x"); return; break;
case a[0]+a[3]+a[6]==="xxx" : s("x"); return; break;
case a[1]+a[4]+a[7]==="xxx" : s("x"); return; break;
case a[2]+a[5]+a[8]==="xxx" : s("x"); return; break;
case a[0]+a[4]+a[8]==="xxx" : s("x"); return; break;
case a[2]+a[4]+a[6]==="xxx" : s("x"); return; break;
case a[0]+a[1]+a[2]==="000" : s("0"); return; break;
case a[3]+a[4]+a[5]==="000" : s("0"); return; break;
case a[6]+a[7]+a[8]==="000" : s("0"); return; break;
case a[0]+a[3]+a[6]==="000" : s("0"); return; break;
case a[1]+a[4]+a[7]==="000" : s("0"); return; break;
case a[2]+a[5]+a[8]==="000" : s("0"); return; break;
case a[0]+a[4]+a[8]==="000" : s("0"); return; break;
case a[2]+a[4]+a[6]==="000" : s("0"); return; break;
}
ab++;
if(ab===9){s(""); return;}
};
Object.prototype.textv=function() {
if(this.innerText=="x" || this.innerText=="0") {
return true;
}
return false;
};
function $(v) {
return document.getElementById(v);
}
window.onload=function() {
$("t1").setAttribute("onclick", "c(this)");
$("t2").setAttribute("onclick", "c(this)");
$("t3").setAttribute("onclick", "c(this)");
$("t4").setAttribute("onclick", "c(this)");
$("t5").setAttribute("onclick", "c(this)");
$("t6").setAttribute("onclick", "c(this)");
$("t7").setAttribute("onclick", "c(this)");
$("t8").setAttribute("onclick", "c(this)");
$("t9").setAttribute("onclick", "c(this)");
$("or").text(vor);
}
function pr() {
$("t1").text("");
$("t2").text("");
$("t3").text("");
$("t4").text("");
$("t5").text("");
$("t6").text("");
$("t7").text("");
$("t8").text("");
$("t9").text("");
$("t1").oc();
$("t2").oc();
$("t3").oc();
$("t4").oc();
$("t5").oc();
$("t6").oc();
$("t7").oc();
$("t8").oc();
$("t9").oc();
xo=false;
a=["", "", "", "", "", "", "", "", ""];
ab=0;
vor=vorx+"-"+voro;
$("or").text(vor);
p=false;
}
Object.prototype.oc=function(){
this.style.backgroundColor="white";
this.style.color="black";
}
function c(v) {
if(p || v.textv()) {return;}
v.text(xof());
v.style.backgroundColor="orange";
v.style.color="white";
a[v.id.charAt(1)-1]=xo?"x":"0";
switch(true){
case a[0]+a[1]+a[2]==="xxx" : s("x"); return; break;
case a[3]+a[4]+a[5]==="xxx" : s("x"); return; break;
case a[6]+a[7]+a[8]==="xxx" : s("x"); return; break;
case a[0]+a[3]+a[6]==="xxx" : s("x"); return; break;
case a[1]+a[4]+a[7]==="xxx" : s("x"); return; break;
case a[2]+a[5]+a[8]==="xxx" : s("x"); return; break;
case a[0]+a[4]+a[8]==="xxx" : s("x"); return; break;
case a[2]+a[4]+a[6]==="xxx" : s("x"); return; break;
case a[0]+a[1]+a[2]==="000" : s("0"); return; break;
case a[3]+a[4]+a[5]==="000" : s("0"); return; break;
case a[6]+a[7]+a[8]==="000" : s("0"); return; break;
case a[0]+a[3]+a[6]==="000" : s("0"); return; break;
case a[1]+a[4]+a[7]==="000" : s("0"); return; break;
case a[2]+a[5]+a[8]==="000" : s("0"); return; break;
case a[0]+a[4]+a[8]==="000" : s("0"); return; break;
case a[2]+a[4]+a[6]==="000" : s("0"); return; break;
}
ab++;
if(ab===9){s("d"); return;}
if(a[0]+a[1]+a[2]==="00") {$("t"+np(0, 1, 2)).click(); return;}
else if(a[3]+a[4]+a[5]==="00") {$("t"+np(3, 4, 5)).cl(); return;}
else if(a[6]+a[7]+a[8]==="00") {$("t"+np(6, 7, 8)).cl(); return;}
else if(a[0]+a[3]+a[6]==="00") {$("t"+np(0, 3, 6)).cl(); return;}
else if(a[1]+a[4]+a[7]==="00") {$("t"+np(1, 4, 7)).cl(); return;}
else if(a[2]+a[5]+a[8]==="00") {$("t"+np(2, 5, 8)).cl(); return;}
else if(a[0]+a[4]+a[8]==="00") {$("t"+np(0, 4, 8)).cl(); return;}
else if(a[2]+a[4]+a[6]==="00") {$("t"+np(2, 4, 6)).cl(); return;}
else if(a[0]+a[1]+a[2]==="xx") {$("t"+np(0, 1, 2)).cl(); return;}
else if(a[3]+a[4]+a[5]==="xx") {$("t"+np(3, 4, 5)).cl(); return;}
else if(a[6]+a[7]+a[8]==="xx") {$("t"+np(6, 7, 8)).cl(); return;}
else if(a[0]+a[3]+a[6]==="xx") {$("t"+np(0, 3, 6)).cl(); return;}
else if(a[1]+a[4]+a[7]==="xx") {$("t"+np(1, 4, 7)).cl(); return;}
else if(a[2]+a[5]+a[8]==="xx") {$("t"+np(2, 5, 8)).cl(); return;}
else if(a[0]+a[4]+a[8]==="xx") {$("t"+np(0, 4, 8)).cl(); return;}
else if(a[2]+a[4]+a[6]==="xx") {$("t"+np(2, 4, 6)).cl(); return;}
else if(a[0]+a[1]+a[2]==="x0") {$("t"+np(0, 1, 2)).cl(); return;}
else if(a[3]+a[4]+a[5]==="x0") {$("t"+np(3, 4, 5)).cl(); return;}
else if(a[6]+a[7]+a[8]==="x0") {$("t"+np(6, 7, 8)).cl(); return;}
else if(a[0]+a[3]+a[6]==="x0") {$("t"+np(0, 3, 6)).cl(); return;}
else if(a[1]+a[4]+a[7]==="x0") {$("t"+np(1, 4, 7)).cl(); return;}
else if(a[2]+a[5]+a[8]==="x0") {$("t"+np(2, 5, 8)).cl(); return;}
else if(a[0]+a[4]+a[8]==="x0") {$("t"+np(0, 4, 8)).cl(); return;}
else if(a[2]+a[4]+a[6]==="x0") {$("t"+np(2, 4, 6)).cl(); return;}
else if(a[0]+a[1]+a[2]==="0x") {$("t"+np(0, 1, 2)).cl(); return;}
else if(a[3]+a[4]+a[5]==="0x") {$("t"+np(3, 4, 5)).cl(); return;}
else if(a[6]+a[7]+a[8]==="0x") {$("t"+np(6, 7, 8)).cl(); return;}
else if(a[0]+a[3]+a[6]==="0x") {$("t"+np(0, 3, 6)).cl(); return;}
else if(a[1]+a[4]+a[7]==="0x") {$("t"+np(1, 4, 7)).cl(); return;}
else if(a[2]+a[5]+a[8]==="0x") {$("t"+np(2, 5, 8)).cl(); return;}
else if(a[0]+a[4]+a[8]==="0x") {$("t"+np(0, 4, 8)).cl(); return;}
else if(a[2]+a[4]+a[6]==="0x") {$("t"+np(2, 4, 6)).cl(); return;}
else if(a[4]==="x" || a[4]==="0") {
if(a[1]==="x" || a[1]==="0") {
if(a[3]==="x" || a[3]==="0") {$("t1").cl(); return;}
else {$("t4").cl(); return;}
}
else {$("t2").cl(); return;}
}
else {$("t5").cl(); return;}
}
function np(v1, v2, v3) {
if(a[v1]=="") {return v1+1;}
if(a[v2]=="") {return v2+1;}
if(a[v3]=="") {return v3+1;}
}
function xof() {
xo=!xo;
return xo?"x":"0";
}
function s(v) {
if(v==="x") {
vorx++;
$("or").innerText="You win!";}
else if(v==="0") {
voro++;
$("or").innerText="You lose!";}
else {
vorx++;
voro++;
$("or").innerText="DRAW!";}
p=true;
window.setTimeout("pr()", 1500);
}
function sm(v) {
switch(v){
case "x" :
$("tbl").style.animation="spinx 10s linear infinite"; break;
case "y" :
$("tbl").style.animation="spiny 10s linear infinite"; break;
case "z" :
$("tbl").style.animation="spinz 10s linear infinite"; break;
case "0" :
$("tbl").style.animation="none"; break;
case "all" :
$("tbl").style.animation="spinall 10s linear infinite"; break;
}
}
</script>
</body>
</html>
21. By Supachai Rojanasiripong
Made by Supachai Rojanasiripong. AI Tic tac toe game with option to choose who draws the first move. ( Source )
<!--Coded by Supachai Rojanasiripong-->
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" charset="UTF-8">
<title>Tic Tac Toe</title>
<style>
body {
background-color:#F5F5F5;
color:#556B2F;
font-family:Arial, sans-serif;
}
#label {
position:relative;
top:0px;
width:345px;
height:180px;
background-color:#F0E68C;
}
#nev{
position:relative;
top:50px;
width:90px;
height:20px;
left:200px;
background-color:#F0E68C;
font-size:16px;
font-weight:bold;
text-align:center;
border:2px solid #556B2F;
border-radius:5px;
transform:rotate(-5deg);
animation:swing 15s infinite;
z-index:3;
}
@keyframes swing {
50% {
transform-origin:left;
transform:rotate(25deg);
}
}
#tic {
position:relative;
top:30px;
left:30px;
width:80px;
height:70px;
transform:rotate(15deg);
border:4px dashed #556B2F;
font-weight:bold;
font-size:60px;
}
#tac {
position:relative;
top:-10px;
left:120px;
width:70px;
transform:rotate(-10deg);
background-color:#556B2F;
font-weight:bold;
font-size:40px;
color:#F0E68C;
padding:5px;
text-align:center;
}
#toe {
position:relative;
top:-70px;
left:210px;
width:70px;
height:70px;
transform:rotate(5deg);
border:4px dashed #556B2F;
font-weight:bold;
font-size:60px;
z-index:2;
}
#ttt {
width:200px;
animation:swingT 15s infinite;
}
@keyframes swingT {
50% {
transform:rotate(-25deg);
}
}
#menuBorder{
position:relative;
top:10px;
left:0px;
width:345px;
height:100px;
background-color:#556B2F;
color:#F0E68C;
display:block;
}
#first {
position:relative;
top:10px;
left:10px;
font-size:20px;
font-weight; bold;
}
#hBtn {
position:relative;
top:20px;
left:47px;
width:100px;
border:1px solid #F0E68C;
text-align:center;
font-size:30px;
}
#cBtn {
position:relative;
left:157px;
top:-17px;
width:140px;
border:1px solid #556B2F;
text-align:center;
font-size:30px;
}
#sBtn {
position:relative;
top:20px;
width:345px;
height:24px;
background-color:#F0E68C;
font-size:22px;
font-weight:bold;
text-align:right;
}
p {
position:relative;
top:10px;
font-size:16px
}
#console {
display:none;
}
#again {
position:relative;
top:10px;
left:10px;
height:30px;
border:none;
font-size:20px;
background-color:#556B2F;
color:#F0E68C;
}
#menuBtn {
position:relative;
top:10px;
left:160px;
height:30px;
border:none;
font-size:20px;
background-color:#556B2F;
color:#F0E68C;
}
#topConsole {
position:relative;
width:345px;
height:410px;
background-color:#F0E68C;
}
.board {
position:relative;
top:15px;
left:8px;
width:330px;
height:335px;
text-align:center;
}
.input {
position:relative;
top:8px;
width:100px;
height:100px;
display:inline-block;
border:3px solid #556B2F;
color:#F0E68C;
font-size:75px;
text-align:center;
overflow:hidden;
}
#who {
position:relative;
top:20px;
left:10px;
height:30px;
width:180px;
font-size:16px;
text-align:left;
}
#level {
position:relative;
top:-10px;
left:185px;
height:30px;
width:150px;
font-size:16px;
text-align:right;
}
#info {
position:relative;
top:10px;
left:17px;
width:300px;
height:70px;
text-align:center;
font-size:60px;
transform:rotate(2deg);
animation:quake 0.1s infinite;
border:4px solid;
}
@keyframes quake {
50% {
transform:rotate(-2deg);
}
}
</style>
</head>
<body>
<div id="menu">
<div id="label">
<div id="ttt">
<div id="nev">Never win</div>
<div id="tic">Tic</div>
<div id="tac">Tac</div>
<div id="toe">Toe</div>
</div>
</div>
<div id="menuBorder">
<div id="first">Who turn first? :</div>
<div id="hBtn" type="submit" onclick="whoFirstTurn('Human')">Human</div>
<div id="cBtn" type="submit" onclick="whoFirstTurn('Computer')">Computer</div>
</div>
<div id="sBtn" onclick="start()">>>Start Game</div>
<p>Coded by Supachai Rojanasiripong</p>
</div>
<div id="console">
<div id="topConsole">
<button id="again" onclick="start()">Play Again</button>
<button id="menuBtn" onclick="openMenu()">Menu</button>
<div class="board">
<div>
<div class="input" id="0" onclick="turn('0')"></div>
<div class="input" id="1" onclick="turn('1')"></div>
<div class="input" id="2" onclick="turn('2')"></div>
</div>
<div>
<div class="input" id="3" onclick="turn('3')"></div>
<div class="input" id="4" onclick="turn('4')"></div>
<div class="input" id="5" onclick="turn('5')"></div>
</div>
<div>
<div class="input" id="6" onclick="turn('6')"></div>
<div class="input" id="7" onclick="turn('7')"></div>
<div class="input" id="8" onclick="turn('8')"></div>
</div>
</div>
<div id="who"></div>
<div id="level"></div>
</div>
<div id="info"></div>
</div>
<script>
//Coded by Supachai Rojanasiripong
alert("If you like it, upvote me please. this code work on mobile only.")
var isStart = false;
var humanFirst = true;
var whoTurn;
var count;
var isClicked = [];
var humanWin;
var com;
var human;
var winList = [];
var level = 'Hard';
function whoFirstTurn(value){
switch(value){
case "Human":
document.getElementById("hBtn").style. borderColor = "#F0E68C";
document.getElementById("cBtn").style. borderColor = "#556B2F";
humanFirst = true;
break;
case "Computer":
document.getElementById("hBtn").style.borderColor = "#556B2F";
document.getElementById("cBtn").style.borderColor = "#F0E68C";
humanFirst = false;
break;
}
}
function openMenu(){
document.getElementById("console").style.display = "none";
document.getElementById("menu").style.display = "block";
}
function start(){
document.getElementById("menu").style.display = "none";
document.getElementById("console").style.display = "block";
count = 0;
var info = document.getElementById("info");
info.style.display = "none";
isStart = true;
humanWin = false;
isClicked = [];
winList = [];
for(let i=0;i<9;i++){
document.getElementById(i.toString()).style.backgroundColor = "#F0E68C";
document.getElementById(i.toString()).style.color = "#556B2F";
document.getElementById(i.toString()).innerHTML = '';
}
if(humanFirst==true){
whoTurn = 'Human';
human = 'o';
com = 'x'
} else{
whoTurn = 'Computer';
com = 'o';
human = 'x'
}
document.getElementById("who").innerHTML = "<b>The first turn : "+whoTurn;
document.getElementById("level").innerHTML = "<b>Level : "+level;
gameLoop();
}
function gameLoop(){
if(whoTurn=='Human'&&humanWin!=true){
count++;
} else{
if(humanWin!=true){
if(humanFirst==true&&count<9||humanFirst==false){
count++;
var input = '';
for(let i=0;i<9;i++){
let temp = document.getElementById(i.toString()).innerHTML;
if(temp==''){temp = 0;}
input += temp;
}
var turnId = getTurn(input);
if(turnId!=undefined){
comTurn(turnId);
} else{
comTurn(randMove());
}
}
}
}
}
function comTurn(id){
document.getElementById(id).innerHTML = com;
isClicked.push(id);
if(humanFirst!=true){
checkO();
} else{
checkX();
}
whoTurn = 'Human';
gameLoop();
}
function turn(id){
if(whoTurn=='Human'&&isClicked.indexOf(id)==-1){
document.getElementById(id).innerHTML = human;
info.innerHTML = '';
isClicked.push(id);
if(humanFirst==true){
checkO();
} else{
checkX();
}
whoTurn = 'Computer';
if(humanWin!=true){
gameLoop();
}
}
}
var turnMap =
[
//fisstMove
'000000000',
//center1 opp return on edges
'000xo0000','0x00o0000','0000ox000','0000o00x0',
//center2 opp return on conners
'0000o0x00','x000o0000','00x0o0000','0000o000x',
//center3 opp attrack edges
'0xo0o0x00','x000ox00o','00x0o0ox0','o00xo000x',
//center4 opp attrack edge revert
'00o0oxx00','x000o00xo','00xxo0o00','ox00o000x',
//conner1
'000x00o00','000x00oxo','ox0000000','ox0x00o00','00o00x000','oxo00x000','0000000xo','00o00x0xo',
//conner1 revert
'000000ox0','o00x00ox0','o00x00000','oxox00000','0xo000000','0xo00x00o','00000x00o','00000xoxo',
//conner2
'x00000o00','x00000oxo','o0x000000','o0xx00o00','00o00000x','oxo00000x','000000x0o','00o00xx0o',
//conner2 revert
'000000o0x','o00x00o0x','o00000x00','oxo000x00','x0o000000','x0o00x00o','00x00000o','00x000oxo',
//conner3
'0x0000o00','0x0000oxo','o0000x000','o00x0xo00','00o0000x0','oxo0000x0',
'000x0000o','00ox0x00o',
//conner3 revert
'00000xo00','o00x0xo00','o000000x0','oxo0000x0','00ox00000','00ox0x00o',
'0x000000o','0x0000oxo',
//conner4
'00x000o00','o0xx00o00','o0000000x','oxo00000x','00o000x00','00o00xx0o','x0000000o','x00000oxo',
//connor5
'0000x0o00','o000x0000','00o0x0000','0000x000o',
//humanFirstCenter1
'0000o0000',
//humanFirstCenter2
'00o0o0x00','x000o000o','00x0o0o00','o000o000x',
//humanFirstConner1
'000000o00','o00000000','00o000000','00000000o',
//humanFirstConner2
'0o00x0o00','o000xo000','00o0x00o0','000ox000o',
//humanFirstConner2 revert
'0o00x000o','0000xoo00','o000x00o0','00oox0000',
//humanFirstConner3
'00o0x0o00','o000x000o',
//humanFirstEdge1
'000o00000','0o0000000','00000o000','0000000o0',
//humanFirstEdge2
'000oxo000','0o00x00o0',
];
function getTurn(input){
for(let i=0;i<turnMap.length;i++){
if(turnMap[i]==input){
switch(i){
//first move
case 0:
var x = Math.floor(Math.random()*5);
switch(x){
case 0:return '0';break;
case 1:return '2';break;
case 2:return '6';break;
case 3:return '8';break;
case 4:return '4';break;
}
break;
//center1 opp return on edges
case 1:return '8';break;
case 2:return '6';break;
case 3:return '0';break;
case 4:return '2';break;
//center2 opp return on conner
case 5:return '2';break;
case 6:return '8';break;
case 7:return '6';break;
case 8:return '0';break;
//center3 opp attrack edges
case 9:return '8';break;
case 10:return '6';break;
case 11:return '0';break;
case 12:return '2';break;
//cennter4 opp attrack edges revert
case 13:return '0';break;
case 14:return '2';break;
case 15:return '8';break;
case 16:return '6';break;
//conner1
case 17:return '8';break;
case 18:return '2';break;
case 19:return '6';break;
case 20:return '8';break;
case 21:return '0';break;
case 22:return '6';break;
case 23:return '2';break;
case 24:return '0';break;
//conner1 revert
case 25:return '0';break;
case 26:return '2';break;
case 27:return '2';break;
case 28:return '8';break;
case 29:return '8';break;
case 30:return '6';break;
case 31:return '6';break;
case 32:return '0';break;
//conner2
case 33:return '8';break;
case 34:return '2';break;
case 35:return '6';break;
case 36:return '8';break;
case 37:return '0';break;
case 38:return '6';break;
case 39:return '2';break;
case 40:return '0';break;
//conner2 revert
case 41:return '0';break;
case 42:return '2';break;
case 43:return '2';break;
case 44:return '8';break;
case 45:return '8';break;
case 46:return '6';break;
case 47:return '6';break;
case 48:return '0';break;
//conner3
case 49:return '8';break;
case 50:return '4';break;
case 51:return '6';break;
case 52:return '4';break;
case 53:return '0';break;
case 54:return '4';break;
case 55:return '2';break;
case 56:return '4';break;
//conner3 revert
case 57:return '0';break;
case 58:return '4';break;
case 59:return '2';break;
case 60:return '4';break;
case 61:return '8';break;
case 62:return '4';break;
case 63:return '6';break;
case 64:return '4';break;
//conner4
case 65:return '0';break;
case 66:return '8';break;
case 67:return '2';break;
case 68:return '6';break;
case 69:return '8';break;
case 70:return '0';break;
case 71:return '6';break;
case 72:return '2';break;
//conner5
case 73:return '2';break;
case 74:return '8';break;
case 75:return '6';break;
case 76:return '0';break;
//humunFirstCenter1
case 77:
var x = Math.floor(Math.random()*4);
switch(x){
case 0:return '6';break;
case 1:return '0';break;
case 2:return '2';break;
case 3:return '8';break;
}
break;
//humanFirstCenter2
case 78:return '0';break;
case 79:return '2';break;
case 80:return '8';break;
case 81:return '6';break;
//humanFirstConner1
case 82:return '4';break;
case 83:return '4';break;
case 84:return '4';break;
case 85:return '4';break;
//humunFirstConner2
case 86:
var x = Math.floor(Math.random()*3);
switch(x){
case 0:return '0';break;
case 1:return '2';break;
case 2:return '5';break;
}
break;
case 87:
var x = Math.floor(Math.random()*3);
switch(x){
case 0:return '2';break;
case 1:return '8';break;
case 2:return '7';break;
}
break;
case 88:
var x = Math.floor(Math.random()*3);
switch(x){
case 0:return '8';break;
case 1:return '6';break;
case 2:return '3';break;
}
break;
case 89:
var x = Math.floor(Math.random()*3);
switch(x){
case 0:return '6';break;
case 1:return '0';break;
case 2:return '1';break;
}
break;
//humunFirstConner2 revert
case 90:
var x = Math.floor(Math.random()*3);
switch(x){
case 0:return '0';break;
case 1:return '2';break;
case 2:return '3';break;
}
break;
case 91:
var x = Math.floor(Math.random()*3);
switch(x){
case 0:return '2';break;
case 1:return '8';bteak;
case 2:return '1';break;
}
break;
case 92:
var x = Math.floor(Math.random()*3);
switch(x){
case 0:return '8';break;
case 1:return '6';break;
case 2:return '5';break;
}
break;
case 93:
var x = Math.floor(Math.random()*3);
switch(x){
case 0:return '6';break;
case 1:return '0';break;
case 2:return '7';break;
}
break;
//humanFirstConner3
case 94:
var x = Math.floor(Math.random()*4);
switch(x){
case 0:return '1';break;
case 1:return '5';break;
case 2:return '7';break;
case 3:return '3';break;
}
break;
case 95:
var x = Math.floor(Math.random()*4);
switch(x){
case 0:return '1';break;
case 1:return '5';break;
case 2:return '7';break;
case 3:return '3';break;
}
break;
//humanFirstEdge1
case 96:return '4';
case 97:return '4';
case 98:return '4';
case 99:return '4';
//humanFirstEdge2
case 100:
var x = Math.floor(Math.random()*4);
switch(x){
case 0:return '0';break;
case 1:return '2';break;
case 2:return '8';break;
case 3:return '6';break;
}
break;
case 101:
var x = Math.floor(Math.random()*4);
switch(x){
case 0:return '0';break;
case 1:return '2';break;
case 2:return '8';break;
case 3:return '6';break;
}
break;
}
}
}
}
function randMove(){
var arr = [];
for(let i=0;i<9;i++){
arr[i] = document.getElementById(i.toString()).innerHTML;
}
if(humanFirst==true){
//attrack
if(arr[0]=='x'&&arr[1]=='x'&&arr[2]==''){
return '2';
} else
if(arr[0]=='x'&&arr[1]==''&&arr[2]=='x'){
return '1';
} else
if(arr[0]==''&&arr[1]=='x'&&arr[2]=='x'){
return '0';
} else
if(arr[3]=='x'&&arr[4]=='x'&&arr[5]==''){
return '5';
} else
if(arr[3]=='x'&&arr[4]==''&&arr[5]=='x'){
return '4';
} else
if(arr[3]==''&&arr[4]=='x'&&arr[5]=='x'){
return '3';
} else
if(arr[6]=='x'&&arr[7]=='x'&&arr[8]==''){
return '8';
} else
if(arr[6]=='x'&&arr[7]==''&&arr[8]=='x'){
return '7';
} else
if(arr[6]==''&&arr[7]=='x'&&arr[8]=='x'){
return '6';
} else
if(arr[0]=='x'&&arr[3]=='x'&&arr[6]==''){
return '6';
} else
if(arr[0]=='x'&&arr[3]==''&&arr[6]=='x'){
return '3';
} else
if(arr[0]==''&&arr[3]=='x'&&arr[6]=='x'){
return '0';
} else
if(arr[1]=='x'&&arr[4]=='x'&&arr[7]==''){
return '7';
} else
if(arr[1]=='x'&&arr[4]==''&&arr[7]=='x'){
return '7';
} else
if(arr[1]==''&&arr[4]=='x'&&arr[7]=='x'){
return '1';
} else
if(arr[2]=='x'&&arr[5]=='x'&&arr[8]==''){
return '8';
} else
if(arr[2]=='x'&&arr[5]==''&&arr[8]=='x'){
return '5';
} else
if(arr[2]==''&&arr[5]=='x'&&arr[8]=='x'){
return '2';
} else
if(arr[0]=='x'&&arr[4]=='x'&&arr[8]==''){
return '8';
} else
if(arr[0]=='x'&&arr[4]==''&&arr[8]=='x'){
return '4';
} else
if(arr[0]==''&&arr[4]=='x'&&arr[8]=='x'){
return '0';
} else
if(arr[6]=='x'&&arr[4]=='x'&&arr[2]==''){
return '2';
} else
if(arr[6]=='x'&&arr[4]==''&&arr[2]=='x'){
return '4';
} else
if(arr[6]==''&&arr[4]=='x'&&arr[2]=='x'){
return '6';
} else
//defend
if(arr[0]=='o'&&arr[1]=='o'&&arr[2]==''){
return '2';
} else
if(arr[0]=='o'&&arr[1]==''&&arr[2]=='o'){
return '1';
} else
if(arr[0]==''&&arr[1]=='o'&&arr[2]=='o'){
return '0';
} else
if(arr[3]=='o'&&arr[4]=='o'&&arr[5]==''){
return '5';
} else
if(arr[3]=='o'&&arr[4]==''&&arr[5]=='o'){
return '4';
} else
if(arr[3]==''&&arr[4]=='o'&&arr[5]=='o'){
return '3';
} else
if(arr[6]=='o'&&arr[7]=='o'&&arr[8]==''){
return '8';
} else
if(arr[6]=='o'&&arr[7]==''&&arr[8]=='o'){
return '7';
} else
if(arr[6]==''&&arr[7]=='o'&&arr[8]=='o'){
return '6';
} else
if(arr[0]=='o'&&arr[3]=='o'&&arr[6]==''){
return '6';
} else
if(arr[0]=='o'&&arr[3]==''&&arr[6]=='o'){
return '3';
} else
if(arr[0]==''&&arr[3]=='o'&&arr[6]=='o'){
return '0';
} else
if(arr[1]=='o'&&arr[4]=='o'&&arr[7]==''){
return '7';
} else
if(arr[1]=='o'&&arr[4]==''&&arr[7]=='o'){
return '7';
} else
if(arr[1]==''&&arr[4]=='o'&&arr[7]=='o'){
return '1';
} else
if(arr[2]=='o'&&arr[5]=='o'&&arr[8]==''){
return '8';
} else
if(arr[2]=='o'&&arr[5]==''&&arr[8]=='o'){
return '5';
} else
if(arr[2]==''&&arr[5]=='o'&&arr[8]=='o'){
return '2';
} else
if(arr[0]=='o'&&arr[4]=='o'&&arr[8]==''){
return '8';
} else
if(arr[0]=='o'&&arr[4]==''&&arr[8]=='o'){
return '4';
} else
if(arr[0]==''&&arr[4]=='o'&&arr[8]=='o'){
return '0';
} else
if(arr[6]=='o'&&arr[4]=='o'&&arr[2]==''){
return '2';
} else
if(arr[6]=='o'&&arr[4]==''&&arr[2]=='o'){
return '4';
} else
if(arr[6]==''&&arr[4]=='o'&&arr[2]=='o'){
return '6';
} else
do{
var i = Math.floor(Math.random()*9);
}while(arr[i]=='o'||arr[i]=='x');
return i.toString();
} else{
//attack
if(arr[0]=='o'&&arr[1]=='o'&&arr[2]==''){
return '2';
} else
if(arr[0]=='o'&&arr[1]==''&&arr[2]=='o'){
return '1';
} else
if(arr[0]==''&&arr[1]=='o'&&arr[2]=='o'){
return '0';
} else
if(arr[3]=='o'&&arr[4]=='o'&&arr[5]==''){
return '5';
} else
if(arr[3]=='o'&&arr[4]==''&&arr[5]=='o'){
return '4';
} else
if(arr[3]==''&&arr[4]=='o'&&arr[5]=='o'){
return '3';
} else
if(arr[6]=='o'&&arr[7]=='o'&&arr[8]==''){
return '8';
} else
if(arr[6]=='o'&&arr[7]==''&&arr[8]=='o'){
return '7';
} else
if(arr[6]==''&&arr[7]=='o'&&arr[8]=='o'){
return '6';
} else
if(arr[0]=='o'&&arr[3]=='o'&&arr[6]==''){
return '6';
} else
if(arr[0]=='o'&&arr[3]==''&&arr[6]=='o'){
return '3';
} else
if(arr[0]==''&&arr[3]=='o'&&arr[6]=='o'){
return '0';
} else
if(arr[1]=='o'&&arr[4]=='o'&&arr[7]==''){
return '7';
} else
if(arr[1]=='o'&&arr[4]==''&&arr[7]=='o'){
return '7';
} else
if(arr[1]==''&&arr[4]=='o'&&arr[7]=='o'){
return '1';
} else
if(arr[2]=='o'&&arr[5]=='o'&&arr[8]==''){
return '8';
} else
if(arr[2]=='o'&&arr[5]==''&&arr[8]=='o'){
return '5';
} else
if(arr[2]==''&&arr[5]=='o'&&arr[8]=='o'){
return '2';
} else
if(arr[0]=='o'&&arr[4]=='o'&&arr[8]==''){
return '8';
} else
if(arr[0]=='o'&&arr[4]==''&&arr[8]=='o'){
return '4';
} else
if(arr[0]==''&&arr[4]=='o'&&arr[8]=='o'){
return '0';
} else
if(arr[6]=='o'&&arr[4]=='o'&&arr[2]==''){
return '2';
} else
if(arr[6]=='o'&&arr[4]==''&&arr[2]=='o'){
return '4';
} else
if(arr[6]==''&&arr[4]=='o'&&arr[2]=='o'){
return '6';
} else
//defend
if(arr[0]=='x'&&arr[1]=='x'&&arr[2]==''){
return '2';
} else
if(arr[0]=='x'&&arr[1]==''&&arr[2]=='x'){
return '1';
} else
if(arr[0]==''&&arr[1]=='x'&&arr[2]=='x'){
return '0';
} else
if(arr[3]=='x'&&arr[4]=='x'&&arr[5]==''){
return '5';
} else
if(arr[3]=='x'&&arr[4]==''&&arr[5]=='x'){
return '4';
} else
if(arr[3]==''&&arr[4]=='x'&&arr[5]=='x'){
return '3';
} else
if(arr[6]=='x'&&arr[7]=='x'&&arr[8]==''){
return '8';
} else
if(arr[6]=='x'&&arr[7]==''&&arr[8]=='x'){
return '7';
} else
if(arr[6]==''&&arr[7]=='x'&&arr[8]=='x'){
return '6';
} else
if(arr[0]=='x'&&arr[3]=='x'&&arr[6]==''){
return '6';
} else
if(arr[0]=='x'&&arr[3]==''&&arr[6]=='x'){
return '3';
} else
if(arr[0]==''&&arr[3]=='x'&&arr[6]=='x'){
return '0';
} else
if(arr[1]=='x'&&arr[4]=='x'&&arr[7]==''){
return '7';
} else
if(arr[1]=='x'&&arr[4]==''&&arr[7]=='x'){
return '7';
} else
if(arr[1]==''&&arr[4]=='x'&&arr[7]=='x'){
return '1';
} else
if(arr[2]=='x'&&arr[5]=='x'&&arr[8]==''){
return '8';
} else
if(arr[2]=='x'&&arr[5]==''&&arr[8]=='x'){
return '5';
} else
if(arr[2]==''&&arr[5]=='x'&&arr[8]=='x'){
return '2';
} else
if(arr[0]=='x'&&arr[4]=='x'&&arr[8]==''){
return '8';
} else
if(arr[0]=='x'&&arr[4]==''&&arr[8]=='x'){
return '4';
} else
if(arr[0]==''&&arr[4]=='x'&&arr[8]=='x'){
return '0';
} else
if(arr[6]=='x'&&arr[4]=='x'&&arr[2]==''){
return '2';
} else
if(arr[6]=='x'&&arr[4]==''&&arr[2]=='x'){
return '4';
} else
if(arr[6]==''&&arr[4]=='x'&&arr[2]=='x'){
return '6';
} else
do{
var i = Math.floor(Math.random()*9);
}while(arr[i]=='o'||arr[i]=='x');
return i.toString();
}
}
function checkO(){
var arr = [];
for(let i=0;i<9;i++){
arr[i] = document.getElementById(i.toString()).innerHTML;
}
if(arr[0]=='o'&&arr[1]=='o'&&arr[2]=='o'){
winList = ['0','1','2'];
} else
if(arr[3]=='o'&&arr[4]=='o'&&arr[5]=='o'){
winList = ['3','4','5'];
} else
if(arr[6]=='o'&&arr[7]=='o'&&arr[8]=='o'){
winList = ['6','7','8'];
} else
if(arr[0]=='o'&&arr[3]=='o'&&arr[6]=='o'){
winList = ['0','3','6'];
} else
if(arr[1]=='o'&&arr[4]=='o'&&arr[7]=='o'){
winList = ['1','4','7'];
} else
if(arr[2]=='o'&&arr[5]=='o'&&arr[8]=='o'){
winList = ['2','5','8'];
} else
if(arr[0]=='o'&&arr[4]=='o'&&arr[8]=='o'){
winList = ['0','4','8'];
} else
if(arr[2]=='o'&&arr[4]=='o'&&arr[6]=='o'){
winList = ['2','4','6'];
}
if(winList.length!=0){
if(humanFirst==true){
humanWin = true;
} else{
humanWin = false;
}
drawWinList();
isClicked = ['0','1','2','3','4','5','6','7','8'];
} else {
if(count==9){
info.style.display = "block";
info.style.color = "#556B2F"
info. innerHTML = "Draw";
}
}
}
function checkX(){
var arr = [];
for(let i=0;i<9;i++){
arr[i] = document.getElementById(i.toString()).innerHTML;
} if(arr[0]=='x'&&arr[1]=='x'&&arr[2]=='x'){
winList = ['0','1','2'];
} else
if(arr[3]=='x'&&arr[4]=='x'&&arr[5]=='x'){
winList = ['3','4','5'];
} else
if(arr[6]=='x'&&arr[7]=='x'&&arr[8]=='x'){
winList = ['6','7','8'];
} else
if(arr[0]=='x'&&arr[3]=='x'&&arr[6]=='x'){
winList = ['0','3','6'];
} else
if(arr[1]=='x'&&arr[4]=='x'&&arr[7]=='x'){
winList = ['1','4','7'];
} else
if(arr[2]=='x'&&arr[5]=='x'&&arr[8]=='x'){
winList = ['2','5','8'];
} else
if(arr[0]=='x'&&arr[4]=='x'&&arr[8]=='x'){
winList = ['0','4','8'];
} else
if(arr[2]=='x'&&arr[4]=='x'&&arr[6]=='x'){
winList = ['2','4','6'];
}
if(winList.length!=0){
if(humanFirst!=true){
humanWin = true;
} else{
humanWin = false;
}
drawWinList();
isClicked = ['0','1','2','3','4','5','6','7','8'];
} else {
if(count==9){
info.style.display = "block";
info.style.color = "#556B2F"
info. innerHTML = "Draw";
}
}
}
function drawWinList(){
let color;
if(humanWin==true){
color = "#556B2F";
info.style.display = "block";
info.style.color = color;
info.innerHTML = "You Win!!"
} else{
color = "#CD5C5C"
info.style.display = "block";
info.style.color = color;
info.innerHTML = "You Lose!! ";
}
for(let i=0;i<winList.length;i++){
document.getElementById(winList[i]).style.backgroundColor = color;
document.getElementById(winList[i]).style.color = "#FFFFFF";
}
}
</script>
</body>
</html>
22. By Jason Stone
Made by Jason Stone. ( Source )
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<style>
body {
text-align: center;
}
canvas {
border: solid;
}
</style>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<script>
// declare a few variables
var canvas, width, height, ctx;
// create the board class so I can create new boards as needed for the minimax algorithm
class Board {
// if there's no input it creates a blank board, otherwise it assumes the input is an object of the class board and copies that board's board to the new object's board
constructor(input) {
if (!input) this.board = [["", "", ""], ["", "", ""], ["", "", ""]];
else {
this.board = [[], [], []];
for (let x = 0; x < 3; x++) {
for (let y = 0; y < 3; y++) {
this.board[x][y] = input.board[x][y];
}
}
}
}
// puts down an X
makePlayerMove(x, y) {
if (this.board[x][y] != "") throw new Error("cannot place an X at position " + x + " " + y)
else this.board[x][y] = "X";
}
// puts down an O
makeOpponentMove(x, y) {
if (this.board[x][y] != "") throw new Error("cannot place an O at position " + x + " " + y)
else this.board[x][y] = "O";
}
// gets the winner, returning either "player" (you), "opponent" (AI), or "" (no winner)
winner() {
if (
(this.board[0][0] == "X" && this.board[1][0] == "X" && this.board[2][0] == "X") ||
(this.board[0][1] == "X" && this.board[1][1] == "X" && this.board[2][1] == "X") ||
(this.board[0][2] == "X" && this.board[1][2] == "X" && this.board[2][2] == "X") ||
(this.board[0][0] == "X" && this.board[0][1] == "X" && this.board[0][2] == "X") ||
(this.board[1][0] == "X" && this.board[1][1] == "X" && this.board[1][2] == "X") ||
(this.board[2][0] == "X" && this.board[2][1] == "X" && this.board[2][2] == "X") ||
(this.board[0][0] == "X" && this.board[1][1] == "X" && this.board[2][2] == "X") ||
(this.board[0][2] == "X" && this.board[1][1] == "X" && this.board[2][0] == "X")
) {
return "player";
} else if (
(this.board[0][0] == "O" && this.board[1][0] == "O" && this.board[2][0] == "O") ||
(this.board[0][1] == "O" && this.board[1][1] == "O" && this.board[2][1] == "O") ||
(this.board[0][2] == "O" && this.board[1][2] == "O" && this.board[2][2] == "O") ||
(this.board[0][0] == "O" && this.board[0][1] == "O" && this.board[0][2] == "O") ||
(this.board[1][0] == "O" && this.board[1][1] == "O" && this.board[1][2] == "O") ||
(this.board[2][0] == "O" && this.board[2][1] == "O" && this.board[2][2] == "O") ||
(this.board[0][0] == "O" && this.board[1][1] == "O" && this.board[2][2] == "O") ||
(this.board[0][2] == "O" && this.board[1][1] == "O" && this.board[2][0] == "O")
) {
return "opponent";
} else if (this.isFull()) {
return "tie";
} else return "";
}
isFull() {
var isFull = true;
for (var x = 0; x < 3; x++) {
for (var y = 0; y < 3; y++) {
if (this.board[x][y] == "") isFull = false;
}
}
return isFull;
}
}
// create the main board
var mainBoard = new Board();
// for when the window loads
window.onload = function() {
// get the canvas, its width and height, and the drawing context
canvas = document.querySelector("#canvas");
width = canvas.width;
height = canvas.height;
ctx = canvas.getContext("2d");
// create the tic tac toe lines
ctx.strokeStyle = "#000";
ctx.beginPath();
ctx.moveTo(width / 3, 0);
ctx.lineTo(width / 3, height);
ctx.moveTo(2 * width / 3, 0);
ctx.lineTo(2 * width / 3, height);
ctx.moveTo(0, height / 3);
ctx.lineTo(width, height / 3);
ctx.moveTo(0, 2 * height / 3);
ctx.lineTo(width, 2 * height / 3);
ctx.stroke();
ctx.closePath();
// create the script to be run when you click/tap on the canvas
canvas.onclick = function(event) {
// get the x & y of where you clicked/tapped
var x = event.pageX - this.offsetLeft;
var y = event.pageY - this.offsetTop;
x = Math.floor(x / width * 3);
y = Math.floor(y / width * 3);
// if there's a valid x & y
if (x >= 0 && x <= 2 && y >= 0 && y <= 2) {
// if the spot is empty
if (mainBoard.board[x][y] == "") {
// put down an X
putX(x, y);
// initialize boardFull to true
var boardFull = true;
// for position on board
for (let x = 0; x < 3; x++) {
for (let y = 0; y < 3; y++) {
// if that position is unfilled set boardFull to false
if (mainBoard.board[x][y] == "") boardFull = false;
}
}
// if the board is not full make the AI move
if (!boardFull) AImove()
// if the board is full and you won make an alert that you won and delete canvas.onclick
else if (mainBoard.winner == "player") {
alert("You won!")
canvas.onclick = () => {};
}
// otherwise alert that it's a tie and delete canvas.onclick
else {
alert("It's a tie!");
canvas.onclick = () => {};
}
}
}
}
if (!confirm("Do you want to go first?")) AImove();
}
function putX(x, y) {
// draw the X
ctx.beginPath();
ctx.moveTo(x * width / 3 + width / 12, y * height / 3 + height / 12);
ctx.lineTo(x * width / 3 + 3 * width / 12, y * height / 3 + 3 * height / 12);
ctx.moveTo(x * width / 3 + 3 * width / 12, y * height / 3 + height / 12);
ctx.lineTo(x * width / 3 + width / 12, y * height / 3 + 3 * height / 12);
ctx.stroke();
ctx.closePath();
// put down the X on the board in the program
mainBoard.makePlayerMove(x, y);
}
function putO(x, y) {
// draw the O
ctx.beginPath();
ctx.arc(x * width / 3 + width / 6, y * height / 3 + height / 6, width / 12, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
// put down the O on the board in the program
mainBoard.makeOpponentMove(x, y);
}
function AImove() {
// if you won alert that you won and remove canvas.onclick
if (mainBoard.winner() == "player") {
alert("You won!");
canvas.onclick = () => {};
}
// if you aren't in a winning state
else {
// get the best move. If this function returns null give an invalid move that doesn't return an error
var move = getBestMove() || {x: 0, y: -1};
// put down the AI move
putO(move.x, move.y);
// if the AI won alert you that it won and delete canvas.onclick
if (mainBoard.winner() == "opponent") {
alert("You lost!");
canvas.onclick = () => {};
}
else if (mainBoard.winner() == "tie") {
alert("It's a tie!");
canvas.onclick = () => {};
}
}
}
// the minimax function
function minimax(board, player) {
// if you won return a bad score since this is trying to get the computer to win
if (board.winner() == "player") return -1;
// if the AI won return a good score
else if (board.winner() == "opponent") return 1;
// if tie return neutral score
else if (board.winner() == "tie") return 0;
// initiate moveScores to an empty array
let moveScores = [];
// for each position on the board that is empty
for (let x = 0; x < 3; x++) {
for (let y = 0; y < 3; y++) {
if (board.board[x][y] == "") {
// create a new board with the same state as the board passed to the function
let newBoard = new Board(board);
// if the player value passed to the function is "player" then put an X down and call minimax and add the return value to the array moveScores
if (player == "player") {
newBoard.makePlayerMove(x, y);
moveScores.push(minimax(newBoard, "opponent"));
}
// if the player value passed to the function isn't "player" (which means opponent/AI) put an O down and call minimax and add the return value to the array moveScores
else {
newBoard.makeOpponentMove(x, y);
moveScores.push(minimax(newBoard, "player"));
}
}
}
}
// if this is player's turn return the minimum of the moveScores
if (player == "player") {
return Math.min(...moveScores);
}
// else return the maximum of the moveScores
else {
return Math.max(...moveScores);
}
}
function getBestMove() {
// initiate the score array
var score = [];
// for every empty position in the board get what happens when you put an O at that spot and return the resulting score
for (let x = 0; x < 3; x++) {
for (let y = 0; y < 3; y++) {
if (mainBoard.board[x][y] == "") {
let newBoard = new Board(mainBoard);
newBoard.makeOpponentMove(x, y);
score.push([x, y, minimax(newBoard, "player")]);
}
}
}
// initiate the moves array and initiate bestScore to -1
var moves = [];
var bestScore = -1;
// get the max score in score and put it in bestScore
for (let i = 0; i < score.length; i++) {
bestScore = Math.max(bestScore, score[i][2]);
}
// for each move in score that has a score equal to bestScore add it to the array moves
for (let i = 0; i < score.length; i++) {
if (score[i][2] == bestScore) {
moves.push({x: score[i][0], y: score[i][1]});
}
}
// return a random element of the array moves
return moves[Math.floor(Math.random() * moves.length)];
}
</script>
</body>
</html>
23. By Mǟɖ↻ôɖɆⱤ💉
Made by Mǟɖ↻ôɖɆⱤ💉. ( Source )
<!DOCTYPE html>
<html>
<head>
<title>ticTacToe</title>
<style>
.tictac {
background-color: white;
color: blue;
border: 2px solid #000000;
transition-duration: 0.3s;
}
</style>
<script src = "https://code.jquery.com/jquery-3.1.1.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.0.2/anime.min.js"></script>
</head>
<body>
<SCRIPT>
//if IE4/NS6, apply style
if (document.all||document.getElementById){
document.write('<style>.tictac{')
document.write('width:90px;height:90px;')
document.write('}</style>')
}
//defining grids
var sqr1
var sqr2
var sqr3
var sqr4
var sqr5
var sqr6
var sqr7
var sqr8
var sqr9
var sqr1T = 0
var sqr2T = 0
var sqr3T = 0
var sqr4T = 0
var sqr5T = 0
var sqr6T = 0
var sqr7T = 0
var sqr8T = 0
var sqr9T = 0
var moveCount = 0
var turn = 0
var mode = 1
//use function to manipulate values
function vari()
{
sqr1 = document.tic.sqr1.value
sqr2 = document.tic.sqr2.value
sqr3 = document.tic.sqr3.value
sqr4 = document.tic.sqr4.value
sqr5 = document.tic.sqr5.value
sqr6 = document.tic.sqr6.value
sqr7 = document.tic.sqr7.value
sqr8 = document.tic.sqr8.value
sqr9 = document.tic.sqr9.value
}
// winning status checker function
function check()
{
if(sqr1 == " X " && sqr2 == " X " && sqr3 == " X ")
{
alert("You Win!")
reset()
}
else if(sqr4 == " X " && sqr5 == " X " && sqr6 == " X ")
{
alert("You Win!")
reset()
}
else if(sqr7 == " X " && sqr8 == " X " && sqr9 == " X ")
{
alert("You Win!")
reset()
}
else if(sqr1 == " X " && sqr5 == " X " && sqr9 == " X ")
{
alert("You Win!")
reset()
}
else if(sqr1 == " X " && sqr4 == " X " && sqr7 == " X ")
{
alert("You Win!")
reset()
}
else if(sqr2 == " X " && sqr5 == " X " && sqr8 == " X ")
{
alert("You Win!")
reset()
}
else if(sqr3 == " X " && sqr6 == " X " && sqr9 == " X ")
{
alert("You Win!")
reset()
}
else if(sqr1 == " X " && sqr5 == " X " && sqr9 == " X ")
{
alert("You Win!")
reset()
}
else if(sqr3 == " X " && sqr5 == " X " && sqr7 == " X ")
{
alert("You Win!")
reset()
}
else
{
winCheck()
check2()
drawCheck()
}
}
//losing status checker function
function check2()
{
vari()
drawCheck()
if(sqr1 == " O " && sqr2 == " O " && sqr3 == " O ")
{
alert("You Lose!")
reset()
}
else if(sqr4 == " O " && sqr5 == " O " && sqr6 == " O ")
{
alert("You Lose!")
reset()
}
else if(sqr7 == " O " && sqr8 == " O " && sqr9 == " O ")
{
alert("You Lose!")
reset()
}
else if(sqr1 == " O " && sqr5 == " O " && sqr9 == " O ")
{
alert("You Lose!")
reset()
}
else if(sqr1 == " O " && sqr4 == " O " && sqr7 == " O ")
{
alert("You Lose!")
reset()
}
else if(sqr2 == " O " && sqr5 == " O " && sqr8 == " O ")
{
alert("You Lose!")
reset()
}
else if(sqr3 == " O " && sqr6 == " O " && sqr9 == " O ")
{
alert("You Lose!")
reset()
}
else if(sqr1 == " O " && sqr5 == " O " && sqr9 == " O ")
{
alert("You Lose!")
reset()
}
else if(sqr3 == " O " && sqr5 == " O " && sqr7 == " O ")
{
alert("You Lose!")
reset()
}
}
//for upcoming versions
function player1Check()
{
if(sqr1 == " X " && sqr2 == " X " && sqr3 == " X ")
{
alert("Player 1 wins!")
reset()
}
else if(sqr4 == " X " && sqr5 == " X " && sqr6 == " X ")
{
alert("Player 1 wins!")
reset()
}
else if(sqr7 == " X " && sqr8 == " X " && sqr9 == " X ")
{
alert("Player 1 wins!")
reset()
}
else if(sqr1 == " X " && sqr5 == " X " && sqr9 == " X ")
{
alert("Player 1 wins!")
reset()
}
else if(sqr1 == " X " && sqr4 == " X " && sqr7 == " X ")
{
alert("Player 1 wins!")
reset()
}
else if(sqr2 == " X " && sqr5 == " X " && sqr8 == " X ")
{
alert("Player 1 wins!")
reset()
}
else if(sqr3 == " X " && sqr6 == " X " && sqr9 == " X ")
{
alert("Player 1 wins!")
reset()
}
else if(sqr1 == " X " && sqr5 == " X " && sqr9 == " X ")
{
alert("Player 1 wins!")
reset()
}
else if(sqr3 == " X " && sqr5 == " X " && sqr7 == " X ")
{
alert("Player 1 wins!")
reset()
}
else
{
player2Check()
drawCheck()
}
}
//for upcoming version
function player2Check()
{
vari()
drawCheck()
if(sqr1 == " O " && sqr2 == " O " && sqr3 == " O ")
{
alert("Player 2 wins!")
reset()
}
else if(sqr4 == " O " && sqr5 == " O " && sqr6 == " O ")
{
alert("Player 2 wins!")
reset()
}
else if(sqr7 == " O " && sqr8 == " O " && sqr9 == " O ")
{
alert("Player 2 wins!")
reset()
}
else if(sqr1 == " O " && sqr5 == " O " && sqr9 == " O ")
{
alert("Player 2 wins!")
reset()
}
else if(sqr1 == " O " && sqr4 == " O " && sqr7 == " O ")
{
alert("Player 2 wins!")
reset()
}
else if(sqr2 == " O " && sqr5 == " O " && sqr8 == " O ")
{
alert("Player 2 wins!")
reset()
}
else if(sqr3 == " O " && sqr6 == " O " && sqr9 == " O ")
{
alert("Player 2 wins!")
reset()
}
else if(sqr1 == " O " && sqr5 == " O " && sqr9 == " O ")
{
alert("Player 2 wins!")
reset()
}
else if(sqr3 == " O " && sqr5 == " O " && sqr7 == " O ")
{
alert("Player 2 wins!")
reset()
}
}
//drawing section
function drawCheck()
{
vari()
moveCount = sqr1T + sqr2T + sqr3T + sqr4T + sqr5T + sqr6T + sqr7T + sqr8T + sqr9T
if(moveCount == 9)
{
reset()
alert("Draw")
}
}
//win status
function winCheck()
{
check2()
if(sqr1 == " O " && sqr2 == " O " && sqr3T == 0 && turn == 1)
{
document.tic.sqr3.value = " O "
sqr3T = 1;
turn = 0;
}
else if(sqr2 == " O " && sqr3 == " O " && sqr1T == 0 && turn == 1)
{
document.tic.sqr1.value = " O "
sqr1T = 1;
turn = 0;
}
else if(sqr4 == " O " && sqr5 == " O " && sqr6T == 0 && turn == 1)
{
document.tic.sqr6.value = " O "
sqr6T = 1;
turn = 0;
}
else if(sqr5 == " O " && sqr6 == " O " && sqr4T == 0 && turn == 1)
{
document.tic.sqr4.value = " O "
sqr4T = 1;
turn = 0;
}
else if(sqr7 == " O " && sqr8 == " O " && sqr9T == 0 && turn == 1)
{
document.tic.sqr9.value = " O "
sqr9T = 1;
turn = 0;
}
else if(sqr8 == " O " && sqr9 == " O " && sqr7T == 0 && turn == 1)
{
document.tic.sqr7.value = " O "
sqr7T = 1;
turn = 0;
}
else if(sqr1 == " O " && sqr5 == " O " && sqr9T == 0 && turn == 1)
{
document.tic.sqr9.value = " O "
sqr9T = 1;
turn = 0;
}
else if(sqr5 == " O " && sqr9 == " O " && sqr1T == 0 && turn == 1)
{
document.tic.sqr1.value = " O "
sqr1T = 1;
turn = 0;
}
else if(sqr3 == " O " && sqr5 == " O " && sqr7T == 0 && turn == 1)
{
document.tic.sqr7.value = " O "
sqr7T = 1;
turn = 0;
}
else if(sqr7 == " O " && sqr5 == " O " && sqr3T == 0 && turn == 1)
{
document.tic.sqr3.value = " O "
sqr3T = 1;
turn = 0;
}
else if(sqr1 == " O " && sqr3 == " O " && sqr2T == 0 && turn == 1)
{
document.tic.sqr2.value = " O "
sqr2T = 1;
turn = 0;
}
else if(sqr4 == " O " && sqr6 == " O " && sqr5T == 0 && turn == 1)
{
document.tic.sqr5.value = " O "
sqr5T = 1;
turn = 0;
}
else if(sqr7 == " O " && sqr9 == " O " && sqr8T == 0 && turn == 1)
{
document.tic.sqr8.value = " O "
sqr8T = 1;
turn = 0;
}
else if(sqr1 == " O " && sqr7 == " O " && sqr4T == 0 && turn == 1)
{
document.tic.sqr4.value = " O "
sqr4T = 1;
turn = 0;
}
else if(sqr2 == " O " && sqr8 == " O " && sqr5T == 0 && turn == 1)
{
document.tic.sqr5.value = " O "
sqr5T = 1;
turn = 0;
}
else if(sqr3 == " O " && sqr9 == " O " && sqr6T == 0 && turn == 1)
{
document.tic.sqr6.value = " O "
sqr6T = 1;
turn = 0;
}
else if(sqr1 == " O " && sqr5 == " O " && sqr9T == 0 && turn == 1)
{
document.tic.sqr9.value = " O "
sqr9T = 1;
turn = 0;
}
else if(sqr4 == " O " && sqr7 == " O " && sqr1T == 0 && turn == 1)
{
document.tic.sqr1.value = " O "
sqr1T = 1;
turn = 0;
}
else if(sqr5 == " O " && sqr8 == " O " && sqr2T == 0 && turn == 1)
{
document.tic.sqr2.value = " O "
sqr2T = 1;
turn = 0;
}
else if(sqr6 == " O " && sqr9 == " O " && sqr3T == 0 && turn == 1)
{
document.tic.sqr3.value = " O "
sqr3T = 1;
turn = 0;
}
else if(sqr1 == " O " && sqr4 == " O " && sqr7T == 0 && turn == 1)
{
document.tic.sqr7.value = " O "
sqr7T = 1;
turn = 0;
}
else if(sqr2 == " O " && sqr5 == " O " && sqr8T == 0 && turn == 1)
{
document.tic.sqr8.value = " O "
sqr8T = 1;
turn = 0;
}
else if(sqr3 == " O " && sqr6 == " O " && sqr9T == 0 && turn == 1)
{
document.tic.sqr9.value = " O "
sqr9T = 1;
turn = 0;
}
else if(sqr1 == " O " && sqr9 == " O " && sqr5T == 0 && turn == 1)
{
document.tic.sqr5.value = " O "
sqr5T = 1;
turn = 0;
}
else if(sqr3 == " O " && sqr7 == " O " && sqr5T == 0 && turn == 1)
{
document.tic.sqr5.value = " O "
sqr5T = 1;
turn = 0;
}
else
{
computer()
}
check2()
}
//feedback implementation
function computer()
{
check2()
if(sqr1 == " X " && sqr2 == " X " && sqr3T == 0 && turn == 1)
{
document.tic.sqr3.value = " O "
sqr3T = 1;
turn = 0;
}
else if(sqr2 == " X " && sqr3 == " X " && sqr1T == 0 && turn == 1)
{
document.tic.sqr1.value = " O "
sqr1T = 1;
turn = 0;
}
else if(sqr4 == " X " && sqr5 == " X " && sqr6T == 0 && turn == 1)
{
document.tic.sqr6.value = " O "
sqr6T = 1;
turn = 0;
}
else if(sqr5 == " X " && sqr6 == " X " && sqr4T == 0 && turn == 1)
{
document.tic.sqr4.value = " O "
sqr4T = 1;
turn = 0;
}
else if(sqr7 == " X " && sqr8 == " X " && sqr9T == 0 && turn == 1)
{
document.tic.sqr9.value = " O "
sqr9T = 1;
turn = 0;
}
else if(sqr8 == " X " && sqr9 == " X " && sqr7T == 0 && turn == 1)
{
document.tic.sqr7.value = " O "
sqr7T = 1;
turn = 0;
}
else if(sqr1 == " X " && sqr5 == " X " && sqr9T == 0 && turn == 1)
{
document.tic.sqr9.value = " O "
sqr9T = 1;
turn = 0;
}
else if(sqr5 == " X " && sqr9 == " X " && sqr1T == 0 && turn == 1)
{
document.tic.sqr1.value = " O "
sqr1T = 1;
turn = 0;
}
else if(sqr3 == " X " && sqr5 == " X " && sqr7T == 0 && turn == 1)
{
document.tic.sqr7.value = " O "
sqr7T = 1;
turn = 0;
}
else if(sqr7 == " X " && sqr5 == " X " && sqr3T == 0 && turn == 1)
{
document.tic.sqr3.value = " O "
sqr3T = 1;
turn = 0;
}
else if(sqr1 == " X " && sqr3 == " X " && sqr2T == 0 && turn == 1)
{
document.tic.sqr2.value = " O "
sqr2T = 1;
turn = 0;
}
else if(sqr4 == " X " && sqr6 == " X " && sqr5T == 0 && turn == 1)
{
document.tic.sqr5.value = " O "
sqr5T = 1;
turn = 0;
}
else if(sqr7 == " X " && sqr9 == " X " && sqr8T == 0 && turn == 1)
{
document.tic.sqr8.value = " O "
sqr8T = 1;
turn = 0;
}
else if(sqr1 == " X " && sqr7 == " X " && sqr4T == 0 && turn == 1)
{
document.tic.sqr4.value = " O "
sqr4T = 1;
turn = 0;
}
else if(sqr2 == " X " && sqr8 == " X " && sqr5T == 0 && turn == 1)
{
document.tic.sqr5.value = " O "
sqr5T = 1;
turn = 0;
}
else if(sqr3 == " X " && sqr9 == " X " && sqr6T == 0 && turn == 1)
{
document.tic.sqr6.value = " O "
sqr6T = 1;
turn = 0;
}
else if(sqr1 == " X " && sqr5 == " X " && sqr9T == 0 && turn == 1)
{
document.tic.sqr9.value = " O "
sqr9T = 1;
turn = 0;
}
else if(sqr4 == " X " && sqr7 == " X " && sqr1T == 0 && turn == 1)
{
document.tic.sqr1.value = " O "
sqr1T = 1;
turn = 0;
}
else if(sqr5 == " X " && sqr8 == " X " && sqr2T == 0 && turn == 1)
{
document.tic.sqr2.value = " O "
sqr2T = 1;
turn = 0;
}
else if(sqr6 == " X " && sqr9 == " X " && sqr3T == 0 && turn == 1)
{
document.tic.sqr3.value = " O "
sqr3T = 1;
turn = 0;
}
else if(sqr1 == " X " && sqr4 == " X " && sqr7T == 0 && turn == 1)
{
document.tic.sqr7.value = " O "
sqr7T = 1;
turn = 0;
}
else if(sqr2 == " X " && sqr5 == " X " && sqr8T == 0 && turn == 1)
{
document.tic.sqr8.value = " O "
sqr8T = 1;
turn = 0;
}
else if(sqr3 == " X " && sqr6 == " X " && sqr9T == 0 && turn == 1)
{
document.tic.sqr9.value = " O "
sqr9T = 1;
turn = 0;
}
else if(sqr1 == " X " && sqr9 == " X " && sqr5T == 0 && turn == 1)
{
document.tic.sqr5.value = " O "
sqr5T = 1;
turn = 0;
}
else if(sqr3 == " X " && sqr7 == " X " && sqr5T == 0 && turn == 1)
{
document.tic.sqr5.value = " O "
sqr5T = 1;
turn = 0;
}
else
{
AI()
}
check2()
}
//AI implementation
function AI()
{
vari()
if(document.tic.sqr5.value == " " && turn == 1)
{
document.tic.sqr5.value = " O "
turn = 0
sqr5T = 1
}
else if(document.tic.sqr1.value == " " && turn == 1)
{
document.tic.sqr1.value = " O "
turn = 0
sqr1T = 1
}
else if(document.tic.sqr9.value == " " && turn == 1)
{
document.tic.sqr9.value = " O "
turn = 0
sqr9T = 1
}
else if(document.tic.sqr6.value == " " && turn == 1)
{
document.tic.sqr6.value = " O "
turn = 0
sqr6T = 1
}
else if(document.tic.sqr2.value == " " && turn == 1)
{
document.tic.sqr2.value = " O "
turn = 0
sqr2T = 1
}
else if(document.tic.sqr8.value == " " && turn == 1)
{
document.tic.sqr8.value = " O "
turn = 0
sqr8T = 1
}
else if(document.tic.sqr3.value == " " && turn == 1)
{
document.tic.sqr3.value = " O "
turn = 0
sqr3T = 1
}
else if(document.tic.sqr7.value == " " && turn == 1)
{
document.tic.sqr7.value = " O "
turn = 0
sqr7T = 1
}
else if(document.tic.sqr4.value == " " && turn == 1)
{
document.tic.sqr4.value = " O "
turn = 0
sqr4T = 1
}
check2()
}
/*reset board*/
function reset()
{
document.tic.sqr1.value = " "
document.tic.sqr2.value = " "
document.tic.sqr3.value = " "
document.tic.sqr4.value = " "
document.tic.sqr5.value = " "
document.tic.sqr6.value = " "
document.tic.sqr7.value = " "
document.tic.sqr8.value = " "
document.tic.sqr9.value = " "
sqr1T = 0
sqr2T = 0
sqr3T = 0
sqr4T = 0
sqr5T = 0
sqr6T = 0
sqr7T = 0
sqr8T = 0
sqr9T = 0
vari()
turn = 0
moveCount = 0
}
function resetter()
{
reset()
}
</SCRIPT>
<h1 align="center">Tic Tac Toe</h1>
<hr>
<marquee behavior="scroll" direction="left" scrollamount="-30">⬇️⬇️ Hope you guys Enjoy the game 😊 ⬇️⬇️</marquee>
<hr>
<FORM NAME="tic" method="post" align="center">
<INPUT TYPE="button"
NAME="sqr1"
class="tictac" value=" " onClick="if(document.tic.sqr1.value == ' ' && turn == 0 && mode == 1) {
document.tic.sqr1.value = ' X '; sqr1T = 1; turn = 1; vari(); check();
}
else if(document.tic.sqr1.value == ' ' && turn == 1 && mode == 2) {
document.tic.sqr1.value = ' X '; sqr1T = 1; turn = 0; vari(); player1Check()
}
else if(document.tic.sqr1.value == ' ' && turn == 0 && mode == 2) {
document.tic.sqr1.value = ' O '; sqr1T = 1; turn = 1; vari(); player1Check()
} drawCheck()">
<INPUT TYPE="button"
NAME="sqr2"
class="tictac" value=" " onClick="if(document.tic.sqr2.value == ' ' && turn == 0 && mode == 1) {
document.tic.sqr2.value = ' X '; sqr2T = 1; turn = 1; vari(); check();
}
else if(document.tic.sqr2.value == ' ' && turn == 1 && mode == 2) {
document.tic.sqr2.value = ' X '; sqr2T = 1; turn = 0; vari(); player1Check()
}
else if(document.tic.sqr2.value == ' ' && turn == 0 && mode == 2) {
document.tic.sqr2.value = ' O '; sqr2T = 1; turn = 1; vari(); player1Check()
} drawCheck()">
<INPUT TYPE="button"
NAME="sqr3"
class="tictac" value=" " onClick="if(document.tic.sqr3.value == ' ' && turn == 0 && mode == 1) {
document.tic.sqr3.value = ' X '; sqr3T = 1; turn = 1; vari(); check();
}
else if(document.tic.sqr3.value == ' ' && turn == 1 && mode == 2) {
document.tic.sqr3.value = ' X '; sqr3T = 1; turn = 0; vari(); player1Check()
}
else if(document.tic.sqr3.value == ' ' && turn == 0 && mode == 2) {
document.tic.sqr3.value = ' O '; sqr3T = 1; turn = 1; vari(); player1Check()
} drawCheck()"><br />
<INPUT TYPE="button"
NAME="sqr4"
class="tictac" value=" " onClick="if(document.tic.sqr4.value == ' ' && turn == 0 && mode == 1) {
document.tic.sqr4.value = ' X '; sqr4T = 1; turn = 1; vari(); check();
}
else if(document.tic.sqr4.value == ' ' && turn == 1 && mode == 2) {
document.tic.sqr4.value = ' X '; sqr4T = 1; turn = 0; vari(); player1Check()
}
else if(document.tic.sqr4.value == ' ' && turn == 0 && mode == 2) {
document.tic.sqr4.value = ' O '; sqr4T = 1; turn = 1; vari(); player1Check()
} drawCheck()">
<INPUT TYPE="button"
NAME="sqr5"
class="tictac" value=" " onClick="if(document.tic.sqr5.value == ' ' && turn == 0 && mode == 1) {
document.tic.sqr5.value = ' X '; sqr5T = 1; turn = 1; vari(); check();
}
else if(document.tic.sqr5.value == ' ' && turn == 1 && mode == 2) {
document.tic.sqr5.value = ' X '; sqr5T = 1; turn = 0; vari(); player1Check()
}
else if(document.tic.sqr5.value == ' ' && turn == 0 && mode == 2) {
document.tic.sqr5.value = ' O '; sqr5T = 1; turn = 1; vari(); player1Check()
} drawCheck()">
<INPUT TYPE="button"
NAME="sqr6"
class="tictac" value=" " onClick="if(document.tic.sqr6.value == ' ' && turn == 0 && mode == 1) {
document.tic.sqr6.value = ' X '; sqr6T = 1; turn = 1; vari(); check();
}
else if(document.tic.sqr6.value == ' ' && turn == 1 && mode == 2) {
document.tic.sqr6.value = ' X '; sqr6T = 1; turn = 0; vari(); player1Check()
}
else if(document.tic.sqr6.value == ' ' && turn == 0 && mode == 2) {
document.tic.sqr6.value = ' O '; sqr6T = 1; turn = 1; vari(); player1Check()
} drawCheck()"><br />
<INPUT TYPE="button"
NAME="sqr7"
class="tictac" value=" " onClick="if(document.tic.sqr7.value == ' ' && turn == 0 && mode == 1) {
document.tic.sqr7.value = ' X '; sqr7T = 1; turn = 1; vari(); check();
}
else if(document.tic.sqr7.value == ' ' && turn == 1 && mode == 2) {
document.tic.sqr7.value = ' X '; sqr7T = 1; turn = 0; vari(); player1Check()
}
else if(document.tic.sqr7.value == ' ' && turn == 0 && mode == 2) {
document.tic.sqr7.value = ' O '; sqr7T = 1; turn = 1; vari(); player1Check()
} drawCheck()">
<INPUT TYPE="button"
NAME="sqr8"
class="tictac" value=" " onClick="if(document.tic.sqr8.value == ' ' && turn == 0 && mode == 1) {
document.tic.sqr8.value = ' X '; sqr8T = 1; turn = 1; vari(); check();
}
else if(document.tic.sqr8.value == ' ' && turn == 1 && mode == 2) {
document.tic.sqr8.value = ' X '; sqr8T = 1; turn = 0; vari(); player1Check()
}
else if(document.tic.sqr8.value == ' ' && turn == 0 && mode == 2) {
document.tic.sqr8.value = ' O '; sqr8T = 1; turn = 1; vari(); player1Check()
} drawCheck()">
<INPUT TYPE="button"
NAME="sqr9" class="tictac" value=" " onClick="if(document.tic.sqr9.value == ' ' && turn == 0 && mode == 1) {
document.tic.sqr9.value = ' X '; sqr9T = 1; turn = 1; vari(); check();
}
else if(document.tic.sqr9.value == ' ' && turn == 1 && mode == 2) {
document.tic.sqr9.value = ' X '; sqr9T = 1; turn = 0; vari(); player1Check()
}
else if(document.tic.sqr9.value == ' ' && turn == 0 && mode == 2) {
document.tic.sqr9.value = ' O '; sqr9T = 1; turn = 1; vari(); player1Check()
} drawCheck()">
</form>
</body>
<br /><br />
<footer>
© All rights reserved by <a href="https://code.sololearn.com/WhEZu2Y95CIx/?ref=app">maDCoder 💉</a><br />
Version 1.0 <em>License by <a href="https://www.gnu.org/licenses/gpl-3.0.en.html">
GNU General Public License</a></em>
</footer>
<script>
alert("⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️\n\n\n If anyone wins assure me in comments 😁\n\n\n⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️")
alert(" Instruction⬇️\n\n\nYou need to click on any square from the grid 3 X 3. While you click it represent 'x' then my AI function generate a '0' in any square of the grid depending on your input. This is how user input and my AI feedback go through.\n\nThe grid seems like that⬇️\n\n1 2 3\n\n4 5 6\n\n7 8 9\n\n➡️The Rule is simple. You must target to fill 3 consecutive 'x' in horizontally or vertically or might it be in a cross-section. My AI will never make you win 😁")
alert("DISCLAIMER⬇️\n\nTicTacToe v1.0\n\nBasically I am not a professional programmer nor a gammer at all. But I want to make a professional tic tac toe game which will be open source. This code will also help my further lessons in SoloLearn for being a professional programmer.\n\nThis is my first version and I just implement a classical UI and simple AI. I know it is very easy to beat down my AI but I assure you my upcomming versions will be harder and harder😁\n\nEnjoy guys and give your feedBack in comments section below⬇️")
$(function() {
});
</script>
</body>
</html>
<!-- Special thanks to $__junayeD ●_° -->
24. By …
Made by …. The program has two modes, 1 player and 2 Player mode, one player is with AI and two player is with another player. ( Source )
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style>
body,
html {
width: 100%;
height: 100%;
}
li {
list-style: none;
}
.outer-container {
background: rgba(240,180,135,1);
box-shadow: inset -1px 1px 7px rgba(0,0,0,.2), inset 1px -1px 7px rgba(0,0,0,.2), 1px 12px 5px rgba(0,0,0,.4), 4px 3px 8px rgba(0,0,0,.4), 5px 10px 10px rgba(0,0,0,.2), -5px 10px 10px rgba(0,0,0,.4);
position: relative;
border-radius: 10px;
width: 400px;
height: 390px;
margin: 10% auto;
padding: 40px 0 0;
}
.board-container {
width: 350px;
height: 350px;
background: rgba(40,40,40,1)
-webkit-radial-gradient(center, rgba(40,80,60,1), rgba(0,20,20,.6));
background: rgba(40,40,40,1)
-moz-radial-gradient(center, rgba(40,80,60,1), rgba(0,20,20,.6));
background: rgba(40,40,40,1)
-ms-radial-gradient(center, rgba(40,80,60,1), rgba(0,20,20,.6));
background: rgba(40,40,40,1)
radial-gradient(center, rgba(40,80,60,1), rgba(0,20,20,.6));
background-size: cover;
position: relative;
margin: 0 auto;
overflow: hidden;
}
.game-board {
width: 100%;
height: 100%;
margin: 0 auto;
position: relative;
}
.boxes {
padding: 0;
width: 100%;
height: 100%;
position: relative;
left: 12px;
top: 0;
}
.boxes li {
width: 30%;
height: 30%;
display: inline-block;
position: relative;
z-index: 1000;
margin-left: 2px;
margin-right: 2px;
overflow: hidden;
}
li i {
font-size: 6.5rem;
text-align: center;
display: block;
width: 100%;
height: 100%;
font-style: normal;
font-family: "Architects Daughter", "Helvetica", "sans-serif";
color: rgba(220,220,220,.7);
z-index: 500;
}
li span {
position: relative;
bottom: 15px;
}
/* Canvas Drawing */
#myCanvas {
width: 330px;
height: 330px;
position: absolute;
z-index: 0;
left: 10px;
top: 0;
opacity: 0;
}
/* Player/Computer prompt */
.player-one-turn {
background: rgba(0,200,200,1);
left: 15px;
}
.player-two-turn {
background: rgba(200,100,100,1);
right: 15px;
}
.player-one-turn,
.player-two-turn {
position: absolute;
top: 0;
width: 170px;
height: 50px;
z-index: -10;
color: white;
text-align: center;
}
.player-one-turn p,
.player-two-turn p {
font-size: 1.3rem;
margin-top: 10px;
}
/* Score keeping */
.points-divider,
.score-1,
.score-2 {
position: absolute;
font-size: .9rem;
margin: 0;
display: none;
}
.score-1,
.score-2 {
font-family: 'Architects Daughter', sans-serif;
top: 17px;
color: rgba(100,60,50,.8);
}
.score-1 .points,
.score-2 .points {
position: absolute;
text-align: center;
bottom: 14px;
color: rgba(100,60,50, .9);
font-family: 'Architects Daughter', sans-serif;
}
.points-divider {
top: 5px;
left: 141px;
font-size: 2rem;
font-family: helvetica, sans-serif;
font-style: normal;
opacity: .2;
}
.score-1 {
left: 75px;
}
.score-2 {
left: 161px;
}
/* reset button */
.hard-reset {
position: absolute;
top: 5px;
right: 20px;
background: none;
border: none;
font-family: 'Architects Daughter', sans-serif;
color: rgba(100,60,50,.8);
font-size: 1.1rem;
border-radius: 20px;
border: 2px dashed transparent;
display: none;
}
.hard-reset:hover {
border: 2px dashed rgba(100,60,50,1);
color: rgba(100,60,50,1);
}
.hard-reset:focus {
outline: none;
}
/* Result Feedback */
span.rotate {
color: rgba(0,200,200,1);
}
i.win {
background: black;
}
.draw-message,
.lose-message,
.win-message {
background: rgba(0,0,0,.8);
width: 400px;
height: 400px;
z-index: 2000;
position: absolute;
display: none;
top: -15px;
left: 0;
box-sizing: border-box;
}
.draw-message p,
.lose-message p,
.win-message p {
color: white;
text-align: center;
position: absolute;
font-size: 2.3rem;
margin: 0;
top: 150px;
left: 50px;
font-family: 'Architects Daughter', sans-serif;
}
/*============================================
Game Starter
============================================*/
.game-choice,
.game-starter {
background: rgba(40,40,40,1)
-webkit-radial-gradient(center, rgba(40,80,60,1), rgba(0,20,20,.6));
background: rgba(40,40,40,1)
-moz-radial-gradient(center, rgba(40,80,60,1), rgba(0,20,20,.6));
background: rgba(40,40,40,1)
-ms-radial-gradient(center, rgba(40,80,60,1), rgba(0,20,20,.6));
background: rgba(40,40,40,1)
radial-gradient(center, rgba(40,80,60,1), rgba(0,20,20,.6));
display: block;
width: 100%;
height: 500px;
position: absolute;
top: 0px;
text-align: center;
font-family: 'Architects Daughter', Helvetica, sans-serif;
z-index: 1500;
/* display: none;*/
}
.game-starter {
display: none;
}
.game-choice p,
.game-starter p {
font-size: 2.2rem;
}
.game-choice button,
.game-choice p,
.game-starter button,
.game-starter p {
color: rgba(220,220,220,1);
position: relative;
top: 50px;
margin: 10px auto;
}
.game-choice p,
.game-starter p {
max-width: 80%;
}
.game-choice button,
.game-starter button {
background: none;
border: none;
opacity: .6;
border-radius: 20px;
border: 2px solid transparent;
font-size: 1.7rem;
}
.game-starter button {
font-size: 2.8rem;
}
.game-choice button:focus,
.game-starter button:focus {
outline: none;
}
.game-choice button:hover,
.game-starter button:hover {
opacity: 1;
border: 2px dashed rgba(230,230,230,.5);
}
.game-starter button.back-button {
position: absolute;
top: 270px;
right: 130px;
font-size: 1.5rem;
border: none;
}
.game-starter .back-button:hover {
border: none;
}
button {
cursor: pointer;
}
/*============================
Win/Lose animation
==============================*/
.rotate {
-webkit-animation: rotating 2s linear infinite;
-moz-animation: rotating 2s linear infinite;
-ms-animation: rotating 2s linear infinite;
-o-animation: rotating 2s linear infinite;
animation: rotating 2s linear infinite;
}
@-webkit-keyframes rotating /* Safari and Chrome */ {
from {
-ms-transform: rotateY(0deg);
-moz-transform: rotateY(0deg);
-webkit-transform: rotateY(0deg);
-o-transform: rotateY(0deg);
transform: rotateY(0deg);
}
to {
-ms-transform: rotateY(360deg);
-moz-transform: rotateY(360deg);
-webkit-transform: rotateY(360deg);
-o-transform: rotateY(360deg);
transform: rotateY(360deg);
}
}
@keyframes rotating {
from {
-ms-transform: rotateY(0deg);
-moz-transform: rotateY(0deg);
-webkit-transform: rotateY(0deg);
-o-transform: rotateY(0deg);
transform: rotateY(0deg);
}
to {
-ms-transform: rotateY(360deg);
-moz-transform: rotateY(360deg);
-webkit-transform: rotateY(360deg);
-o-transform: rotateY(360deg);
transform: rotateY(360deg);
}
}
</style>
</head>
<body>
<div class="outer-container">
<button class="hard-reset">Reset All</button>
<p class="score-1"><span class="points"></span><span class="name"></span></p>
<i class="points-divider">|</i>
<p class="score-2"><span class="points"></span><span class="name"></span></p>
<div class="player-one-turn">
<p></p>
</div>
<div class="player-two-turn">
<p></p>
</div>
<div class="board-container">
<div class="game-starter">
<p>Would you like to be X or O?</p>
<button class="choose-x">X</button>
<button class="choose-o">O</button>
<button class="back-button"><i class="fa fa-arrow-left"></i> Back</button>
</div>
<div class="game-choice">
<p>How do you want to play?</p>
<button class="one-player">One Player</button>
<button class="two-player">Two Player</button>
</div>
<div class="game-board">
<div class="draw-message">
<p>It was a draw..</p>
</div>
<div class="lose-message">
<p>Uh oh, you lost..</p>
</div>
<div class="win-message">
<p>You Won!!! :)</p>
</div>
<canvas id="myCanvas"></canvas>
<ul class="boxes">
</ul>
</div>
</div>
</div>
<script>
var MYAPP = MYAPP || {
gameInPlay: false,
winCombos: [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[1, 4, 7],
[2, 5, 8],
[3, 6, 9],
[1, 5, 9],
[7, 5, 3]
],
playerOneScore: 0,
playerTwoScore: 0,
timeOuts: [],
initializeVars: function() {
this.numFilledIn = 0;
this.currentBoard = {
1: '',
2: '',
3: '',
4: '',
5: '',
6: '',
7: '',
8: '',
9: ''
};
},
initializeGame: function() {
MYAPP.initializeVars();
MYAPP.display.drawBoard();
$('.game-choice button').click(function() {
MYAPP.secondPlayer = MYAPP.game.gameSelection(this);
MYAPP.display.hideGameChoice();
MYAPP.display.showGameStarter(MYAPP.secondPlayer);
$('.game-starter .choose-x, .game-starter .choose-o').off().click(MYAPP.game.firstGame);
$('.back-button').on('click', function() {
MYAPP.display.hideGameStarter();
MYAPP.display.showGameChoice();
});
});
$('.hard-reset').on('click', MYAPP.game.resetGame);
}
};
/*=========================
Display functions
==========================*/
MYAPP.display = {
hideGameStarter: function() {
$('.game-starter').fadeOut();
},
showGameStarter: function(isTwoPlayer) {
var message;
if (isTwoPlayer) {
message = "Player 1 : Would you like X or O?"
}
else {
message = "Would you like to be X or O?";
}
MYAPP.timeOuts.push(
setTimeout(function() {
$('.game-starter').fadeIn(500).children('p').text(message);
}, 700));
},
showGameChoice: function() {
$('.game-choice').fadeIn(600);
},
hideGameChoice: function() {
$('.game-choice').fadeOut(600);
},
showPlayerOnePrompt: function() {
if (MYAPP.secondPlayer) {
$('.player-one-turn p').text('Go Player 1!');
}
else {
$('.player-one-turn p').text('Your turn!');
}
$('.player-one-turn').animate({'top': '-45px'}, 500);
},
hidePlayerOnePrompt: function() {
$('.player-one-turn').animate({'top': '0'}, 500);
},
showPlayerTwoPrompt: function() {
if (MYAPP.secondPlayer) {
$('.player-two-turn p').text('Go Player 2!');
}
else {
$('.player-two-turn p').text('Computer\'s turn');
}
$('.player-two-turn').animate({'top': '-45px'}, 500);
},
hidePlayerTwoPrompt: function() {
$('.player-two-turn').animate({'top': '0'}, 500);
},
showDrawMessage: function() {
MYAPP.timeOuts.push(
setTimeout(function() {
$('.draw-message').fadeIn(500);
}, 1500));
},
hideDrawMessage: function() {
$('.draw-message').fadeOut(1000);
},
showLoseMessage: function() {
MYAPP.timeOuts.push(
setTimeout(function() {
$('.lose-message').fadeIn(500);
}, 1500)
);
},
hideLoseMessage: function() {
$('.lose-message').fadeOut(1000);
},
showWinMessage: function() {
MYAPP.timeOuts.push(
setTimeout(function() {
$('.win-message').fadeIn(500).children('p').text("Player " + MYAPP.turn + " wins!! :D ")
}, 1500));
},
hideWinMessage: function() {
$('.win-message').fadeOut(1000);
},
drawBoard: function() {
MYAPP.timeOuts.push(setTimeout(function() {
var c = document.getElementById("myCanvas");
var canvas = c.getContext("2d");
canvas.lineWidth = 1;
canvas.strokeStyle = "#fff";
//vertical lines
canvas.beginPath();
canvas.moveTo(100, 0);
canvas.lineTo(100, 146.5);
canvas.closePath();
canvas.stroke();
canvas.beginPath();
canvas.moveTo(200, 0);
canvas.lineTo(200, 146.5);
canvas.closePath();
canvas.stroke();
// horizontal lines
canvas.lineWidth = .5;
canvas.beginPath();
canvas.moveTo(4, 48.5);
canvas.lineTo(296, 48.5);
canvas.closePath();
canvas.stroke();
canvas.beginPath();
canvas.moveTo(4, 98.5);
canvas.lineTo(296, 98.5);
canvas.closePath();
canvas.stroke();
}, 1500));
},
resetSquares: function() {
$('.boxes').html('');
for (var i = 1; i <= 9; i++) {
var box = '<li class="' + i + '"><i class="letter"><span></span></i></li>';
$(box).appendTo($('.boxes'));
}
},
showScore: function() {
if (MYAPP.secondPlayer) {
$('.score-1').children('.name').text('player 1');
$('.score-2').children('.name').text('player 2');
}
else {
$('.score-1').children('.name').text('player 1');
$('.score-2').children('.name').text('computer');
}
$('.score-1, .score-2').children('.points').text('0');
$('.score-1,.score-2, .points-divider').fadeIn();
},
updateScore: function(turn) {
var currentScore = turn === 1 ? MYAPP.playerOneScore : MYAPP.playerTwoScore;
$('.score-' + turn).children('.points').text(currentScore);
}
};
/*=========================
Game Logic
==========================*/
MYAPP.game = {
whoStarts: function() {
var random = Math.floor(Math.random() * 2 + 1);
return random;
},
gameSelection: function(item) {
if ($(item).text() === 'One Player') {
// returns what secondPlayer value to set
return false;
}
else {
return true;
}
},
firstGame: function() {
MYAPP.playerOneSymbol = $(this).text();
MYAPP.playerTwoSymbol = MYAPP.playerOneSymbol == 'X' ? 'O' : 'X';
MYAPP.turn = MYAPP.game.whoStarts();
MYAPP.display.hideGameStarter();
$('#myCanvas').animate({'opacity': '1'}, 1200);
$('.hard-reset').fadeIn(600);
MYAPP.display.showScore();
MYAPP.display.resetSquares();
MYAPP.game.play();
},
play: function() {
MYAPP.gameInPlay = true;
$('.boxes li').on('click', function() {
MYAPP.game.playerTurn(this);
});
MYAPP.timeOuts.push(
setTimeout(function(){
if (MYAPP.turn === 1) {
MYAPP.display.showPlayerOnePrompt();
}
else if (MYAPP.turn === 2) {
MYAPP.display.showPlayerTwoPrompt();
}
}, 1500),
setTimeout(function() {
if (MYAPP.turn === 2 && !MYAPP.secondPlayer) {
MYAPP.game.computerPlay();
}
}, 1200));
},
playerTurn: function(square) {
var symbol = MYAPP.turn === 1 ? MYAPP.playerOneSymbol : MYAPP.playerTwoSymbol;
var box = $(square).children('i').children('span');
if (box.text() === '' && MYAPP.gameInPlay && (MYAPP.turn === 1 || (MYAPP.turn === 2 && MYAPP.secondPlayer))) {
box.text(symbol);
var number = $(square).attr('class');
MYAPP.game.updateSquare(number, symbol);
MYAPP.game.endTurn(symbol);
}
},
computerPlay: function() {
var computer = MYAPP.computer;
//test computer move suggestion
var boxNumber;
if (computer.computerWhichMove(MYAPP.game) && MYAPP.turn === 2) {
boxNumber = computer.computerWhichMove(MYAPP.game);
var currentBox = $('.' + boxNumber).children('i');
var symbol = MYAPP.playerTwoSymbol;
MYAPP.timeOuts.push(
setTimeout(function() {
currentBox.children('span').text(symbol);
MYAPP.game.updateSquare(boxNumber, MYAPP.playerTwoSymbol);
MYAPP.game.endTurn(symbol);
}, 1000));
}
},
endTurn: function(symbol) {
MYAPP.numFilledIn = MYAPP.numFilledIn + 1;
if (MYAPP.gameInPlay) {
if (MYAPP.game.checkWin(symbol)[0]) {
MYAPP.game.updateScore(MYAPP.turn);
if (MYAPP.secondPlayer) {
MYAPP.display.showWinMessage();
}
else {
MYAPP.turn === 1 ? MYAPP.display.showWinMessage() : MYAPP.display.showLoseMessage();
}
MYAPP.gameInPlay = false;
MYAPP.game.showWinningCombination();
MYAPP.display.hidePlayerOnePrompt();
MYAPP.display.hidePlayerTwoPrompt();
MYAPP.game.reset();
}
// stop if it is a draw
else if (MYAPP.numFilledIn >= 9) {
MYAPP.gameInPlay = false;
MYAPP.display.hidePlayerOnePrompt();
MYAPP.display.hidePlayerTwoPrompt();
MYAPP.display.showDrawMessage();
MYAPP.turn = MYAPP.game.whoStarts();
MYAPP.game.reset();
} else {
if (MYAPP.turn === 1) {
MYAPP.display.hidePlayerOnePrompt();
MYAPP.display.showPlayerTwoPrompt();
MYAPP.turn = 2;
// call computer turn if no second player
if (!MYAPP.secondPlayer) {
MYAPP.game.computerPlay();
}
} else if (MYAPP.turn === 2) {
MYAPP.display.showPlayerOnePrompt();
MYAPP.display.hidePlayerTwoPrompt();
MYAPP.turn = 1;
}
}
}
},
updateSquare: function(number, symbol) {
MYAPP.currentBoard[number] = symbol;
},
checkWin: function(symbol) {
var currentBoard = MYAPP.currentBoard;
var wins = MYAPP.winCombos;
var winningCombo = [];
var winner = wins.some(function(combination) {
var winning = true;
for (var i = 0; i < combination.length; i++) {
if (currentBoard[combination[i]] !== symbol) {
winning = false;
}
}
if (winning) {
winningCombo = combination;
}
return winning;
});
return [winner, winningCombo];
},
showWinningCombination: function() {
var symbol = MYAPP.turn === 1 ? MYAPP.playerOneSymbol : MYAPP.playerTwoSymbol;
var combo = MYAPP.game.checkWin(symbol)[1];
for (var i = 0; i < combo.length; i++) {
var currentBox = '.' + combo[i];
// Black box and rotating test for winning combo
$(currentBox).children('i').addClass('win').children('span').addClass('rotate');
}
},
updateScore: function(turn) {
turn === 1 ? MYAPP.playerOneScore += 1 : MYAPP.playerTwoScore += 1;
MYAPP.display.updateScore(turn);
},
reset: function() {
MYAPP.initializeVars();
MYAPP.timeOuts.push(
setTimeout(function() {
MYAPP.display.hideDrawMessage();
MYAPP.display.hideLoseMessage();
MYAPP.display.hideWinMessage();
$('.boxes li').fadeOut();
}, 5000),
setTimeout(function(){
MYAPP.display.resetSquares();
$('.boxes li').fadeIn();
MYAPP.numFilledIn = 0;
}, 6000),
//Make sure time for next timeout is long enough
//to not cause problems after first game
setTimeout(function() {
MYAPP.gameInPlay = true;
MYAPP.game.play();
}, 6000)
);
},
resetGame: function() {
$('#myCanvas').css('opacity', '0');
$('.hard-reset').fadeOut();
$('.points-divider, .score-1, .score-2').fadeOut();
MYAPP.playerOneScore = 0;
MYAPP.playerTwoScore = 0;
MYAPP.display.resetSquares();
MYAPP.initializeVars();
MYAPP.gameInPlay = false;
MYAPP.playerOneSymbol = null;
MYAPP.playerTwoSymbol = null;
MYAPP.timeOuts.forEach(function(timer) {
clearTimeout(timer);
});
$('.draw-message, .win-message, .lose-message').hide();
MYAPP.display.hidePlayerOnePrompt();
MYAPP.display.hidePlayerTwoPrompt();
MYAPP.display.showGameChoice();
}
};
/* End Game Logic */
/*================================
Computer Move Decisions
=================================*/
MYAPP.computer = {
computerWhichMove: function () {
var move = this.winOrBlockChoice('win')[0];
if (!move) {
move = this.winOrBlockChoice('block')[0]; }
if (!move) {
move = this.doubleThreatChoice('win');
}
if (!move) {
move = this.doubleThreatChoice('block');
}
if (!move) {
move = this.firstPlay();
}
if (!move) {
move = this.playCenter();
}
if (!move) {
move = this.emptyCorner();
}
if (!move) {
move = this.emptySide();
}
move = (move && MYAPP.currentBoard[move]) === '' ? move : false;
return move;
},
winOrBlockChoice: function(choiceType, board) {
var board = board || MYAPP.currentBoard;
if (choiceType === 'win') {
var currentSymbol = MYAPP.playerTwoSymbol;
var opponentSymbol = MYAPP.playerOneSymbol;
} else if (choiceType === 'block') {
var currentSymbol = MYAPP.playerOneSymbol;
var opponentSymbol = MYAPP.playerTwoSymbol;
} else {
return;
}
var moves = [];
MYAPP.winCombos.forEach(function(combo) {
var notFound = [];
var notPlayer = true;
for (var i = 0; i < combo.length; i++) {
if (board[combo[i]] !== currentSymbol) {
if (board[combo[i]] === opponentSymbol) {
notPlayer = false;
} else {
notFound.push(combo[i]);
}
}
}
if (notFound.length === 1 && notPlayer) {
var move = notFound[0];
moves.push(move);
}
});
return moves;
},
doubleThreatChoice: function(choiceType) {
// use winChoice function to test a spot for double threat
var board = MYAPP.currentBoard;
var move;
if (choiceType === 'win') {
var currentSymbol = MYAPP.playerTwoSymbol;
var opponentSymbol = MYAPP.playerOneSymbol;
} else if (choiceType === 'block') {
var currentSymbol = MYAPP.playerOneSymbol;
var opponentSymbol = MYAPP.playerTwoSymbol;
}
// forced diagonal win on 4th move prevention
if (board[5] === currentSymbol && MYAPP.numFilledIn === 3) {
if ((board[1] === opponentSymbol && board[9] === opponentSymbol) || (board[3] === opponentSymbol && board[7] === opponentSymbol)) {
// Play an edge to block double threat
move = this.emptySide();
}
}
if (!move && board[5] === opponentSymbol && MYAPP.numFilledIn === 2) {
move = this.diagonalSecondAttack();
}
if (!move) {
// clone current board;
var testBoard = $.extend({}, board);
for (var i = 1; i <= 9; i++) {
testBoard = $.extend({}, board);
if (testBoard[i] === '') {
testBoard[i] = currentSymbol;
if (this.winOrBlockChoice(choiceType, testBoard).length >= 2) {
move = i;
}
}
}
}
return move || false;
},
diagonalSecondAttack: function() {
var board = MYAPP.currentBoard;
var comp = MYAPP.playerTwoSymbol;
var corners = [1,3,7,9];
for (var i = 0; i < corners.length; i++) {
if (board[corners[i]] === comp) {
return 10 - corners[i];
}
}
},
firstPlay: function() {
var board = MYAPP.currentBoard;
var corners = [1, 3, 7, 9];
var move;
if (MYAPP.numFilledIn === 1) {
// player plays center
if (board[5] === MYAPP.playerOneSymbol) {
var cornerNum = Math.floor(Math.random() * 4 + 1);
move = [1, 3, 7, 9][cornerNum];
}
//player plays corner, play opposite corner
else {
for (var i = 0; i < corners.length; i++) {
if (MYAPP.currentBoard[corners[i]] === MYAPP.playerOneSymbol) {
move = 5;
}
}
}
} else if (MYAPP.numFilledIn === 0) {
var cornerNum = Math.floor(Math.random() * corners.length + 1);
move = corners[cornerNum];
}
return move ? move : false;
},
playCenter: function() {
if (MYAPP.currentBoard[5] === '') {
return 5;
}
},
emptyCorner: function() {
var board = MYAPP.currentBoard;
var corners = [1, 3, 7, 9];
var move;
for (var i = 0; i < corners.length; i++) {
if (board[corners[i]] === '') {
move = corners[i];
}
}
return move || false;
},
emptySide: function() {
var sides = [2, 4, 6, 8];
for (var i = 0; i < sides.length; i++) {
if (MYAPP.currentBoard[sides[i]] === '') {
return sides[i];
}
}
return false;
}
}
/* End Computer Move Decisions */
$(document).ready(function() {
MYAPP.initializeGame();
});
</script>
</body>
</html>
25. By Kartikey Sahu
Made by Kartikey Sahu. JavaScript tic tac toe with scoreboard and option to enter your name. ( Source )
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Tic Tac Toe</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Muli:400" rel="stylesheet">
<style>
html,
body {
margin: 0;
height: 100vh;
width: 100vw;
font-family: 'Muli', sans-serif;
user-select: none;
}
body {
display: grid;
grid-template: auto 512px auto / auto 360px auto;
}
#root {
grid-column-start: 2;
grid-row-start: 2;
display: grid;
grid-template-rows: repeat(3, 3.3fr) 1.1fr;
border: 1px solid;
}
header {
font-size: 36px;
display: grid;
align-content: center;
justify-content: center;
}
#base {
display: grid;
grid-template: auto 124px auto / auto 124px auto;
}
footer {
border-bottom: 1px solid;
display: grid;
grid-template-columns: 1fr 1fr;
}
footer div {
display: grid;
align-content: center;
justify-content: center;
}
footer div {
font-size: 32px;
}
#undo,
#board,
#redo {
grid-row-start: 2;
display: grid;
align-content: center;
justify-content: center;
}
#board {
grid-template: repeat(3, 40px) / repeat(3, 40px);
background: #999;
grid-gap: 1px;
padding: 1px;
}
button {
background: white;
border: 0 none;
font: inherit;
transition-duration: 0.3s;
}
#board button:focus {
outline: 1px dashed #333;
}
#player {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 1px;
background: #333;
}
#player div {
display: grid;
align-content: center;
justify-content: center;
}
#player-a,
#player-b {
transition-duration: 0.3s;
background-color: lightblue;
}
</style>
</head>
<body>
<div id="root">
<header>Tic Tac Toe</header>
<div id="base">
<div id="undo">
<button onclick="ttt.clear()">Clear</button>
</div>
<div id="board">
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
</div>
<div id="redo">
<button onclick="ttt.newGame()">Restart</button>
</div>
</div>
<footer>
<div id="score-a">3</div>
<div id="score-b">5</div>
</footer>
<div id="player">
<div id='player-a'>Player A</div>
<div id='player-b'>Player B</div>
</div>
</div>
<script>
alert("X for first player and O for second player")
var
winWhen = [
[0, 1, 2],
[0, 3, 6],
[0, 4, 8],
[1, 4, 7],
[2, 4, 6],
[2, 5, 8],
[3, 4, 5],
[6, 7, 8]
],
ttt = {
scoreA: 0,
scoreB: 0,
playerA: 'Player A',
playerB: 'Player B',
state: [-1, -1, -1, -1, -1, -1, -1, -1, -1],
now: 'X',
pA: '',
pB: '',
sA: '',
sB: '',
enabled: true
},
btn;
ttt.playerA = prompt("Enter the name of first player", ttt.playerA);
ttt.playerB = prompt("Enter the name of second player", ttt.playerB);
window.onload = function () {
ttt.pA = document.getElementById('player-a');
ttt.pB = document.getElementById('player-b');
ttt.sA = document.getElementById('score-a');
ttt.sB = document.getElementById('score-b');
ttt.pA.innerText = ttt.playerA == null ? 'Player A' : ttt.playerA
ttt.pB.innerText = ttt.playerB == null ? 'Player B' : ttt.playerB
ttt.sA.innerText = ttt.scoreA;
ttt.sB.innerText = ttt.scoreB;
btn = document.querySelectorAll('#board button')
btn[0].addEventListener('click', function(){ttt.clicked(0)})
btn[1].addEventListener('click', function(){ttt.clicked(1)})
btn[2].addEventListener('click', function(){ttt.clicked(2)})
btn[3].addEventListener('click', function(){ttt.clicked(3)})
btn[4].addEventListener('click', function(){ttt.clicked(4)})
btn[5].addEventListener('click', function(){ttt.clicked(5)})
btn[6].addEventListener('click', function(){ttt.clicked(6)})
btn[7].addEventListener('click', function(){ttt.clicked(7)})
btn[8].addEventListener('click', function(){ttt.clicked(8)})
}
ttt.clicked = function (i) {
if (ttt.state[i] === -1 && ttt.enabled) {
ttt.state[i] = ttt.now;
for (var i = 0; i < 9; i++) {
var value = ttt.state[i];
if (value !== -1) {
btn[i].innerText = value;
}
}
var won = ttt.hasWon();
if (won) {
if (ttt.now === 'X') {
ttt.scoreA++;
ttt.sA.innerText = ttt.scoreA;
} else {
ttt.scoreB++;
ttt.sB.innerText = ttt.scoreB;
}
if (ttt.scoreA > ttt.scoreB) {
ttt.pA.style.backgroundColor = 'greenyellow';
ttt.pB.style.backgroundColor = 'lightcoral';
} else if (ttt.scoreA === ttt.scoreB) {
ttt.pA.style.backgroundColor = 'lightblue';
ttt.pB.style.backgroundColor = 'lightblue';
} else {
ttt.pB.style.backgroundColor = 'greenyellow';
ttt.pA.style.backgroundColor = 'lightcoral';
}
}
ttt.now = (ttt.now === 'X') ? 'O' : 'X';
}
}
ttt.hasWon = function () {
for (var g = 0; g < winWhen.length; g++) {
if (
btn[winWhen[g][0]].innerText != '' &&
btn[winWhen[g][1]].innerText != '' &&
btn[winWhen[g][2]].innerText != ''
) {
if (
btn[winWhen[g][0]].innerText == btn[winWhen[g][1]].innerText &&
btn[winWhen[g][1]].innerText == btn[winWhen[g][2]].innerText
) {
for (k = 0; k < 3; k++) {
btn[winWhen[g][k]].style.background = "gold"
}
ttt.enabled = false
window.setTimeout(ttt.clear, 1000);
return true;
}
}
}
if(ttt.state.indexOf(-1) == -1){
setTimeout(ttt.clear, 300)
}
return false;
}
ttt.fill = function () {
for (var i = 0; i < 9; i++) {
btn[i].innerText = '';
}
}
ttt.clear = function () {
for (var i = 0; i < 9; i++) {
btn[i].style.backgroundColor = '#fff'
}
ttt.state = new Array(9).fill(-1);
ttt.fill();
ttt.now = 'X';
ttt.enabled = true;
}
ttt.newGame = function () {
ttt.clear();
ttt.scoreA = ttt.scoreB = 0;
ttt.sA.innerText =
ttt.sB.innerText = 0;
ttt.pA.style.backgroundColor = 'lightblue';
ttt.pB.style.backgroundColor = 'lightblue';
}
</script>
</body>
</html>