A Pen by Larry Yuan on CodePen.
Created
July 2, 2018 01:36
-
-
Save ehhthing/83bedacfa5bc48f8f51a7abbe8fcafb0 to your computer and use it in GitHub Desktop.
Tic-Tac-Toe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Tic-Tac-Toe</title> | |
</head> | |
<body> | |
<div id="container" hidden> | |
<div id="buttons"> | |
<center> | |
<h1 class="title">Tic-Tac-Toe</h1> | |
<button class="button button-large left-margin 1v1-button">1v1</button> | |
<button class="button button-large left-margin random-button">AI</button> | |
</center> | |
</div> | |
<div id="board" hidden> | |
<button class="place" id="top-left"></button><button class="place" id="top-middle"></button><button class="place" id="top-right"></button> | |
<br> | |
<button class="place" id="middle-left"></button><button class="place" id="middle-middle"></button><button class="place" id="middle-right"></button> | |
<br> | |
<button class="place" id="bottom-left"></button><button class="place" id="bottom-middle"></button><button class="place" id="bottom-right"></button><br></div> | |
<div id="end" hidden> | |
<center><h1 class="title" id="endMessage">Player X won.</h1> | |
<button class="button button-large left-margin" id="play-again">Play Again</button></center> | |
</div> | |
</div> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var mode; | |
var player; | |
var attacks = []; | |
var defenses = []; | |
var threes = [ | |
[0, 1, 2], | |
[3, 4, 5], | |
[6, 7, 8], | |
[0, 3, 6], | |
[1, 4, 7], | |
[2, 5, 8], | |
[0, 4, 8], | |
[2, 4, 6] | |
]; | |
$(".1v1-button").click(function() { | |
showBoard(); | |
mode = "1v1"; | |
player = "X"; | |
}); | |
$(".random-button").click(function() { | |
showBoard(); | |
mode = "random"; | |
player = "X"; | |
}); | |
$(document).ready(function() { | |
$("#container").fadeIn(); | |
}); | |
function showBoard() { | |
$("#buttons").fadeOut(500); | |
setTimeout(function() { | |
$("#board").fadeIn(500); | |
}, 751); | |
$(".place").attr("data-place", ""); | |
} | |
$("#play-again").click(function() { | |
location.reload(); | |
}); | |
$(".place").click(function() { | |
setTimeout(checkGame(), 500); | |
if (mode == "1v1" && $(this).attr("data-place") === "") { | |
$(this).attr("data-place", player); | |
$(this).html(player); | |
if (player == "X") { | |
player = "O"; | |
} else if (player == "O") { | |
player = "X"; | |
} | |
setTimeout(checkGame(), 500); | |
} else if (mode == "random" && $(this).attr("data-place") === "") { | |
setTimeout(checkGame(), 500); | |
$(this).attr("data-place", player); | |
$(this).html(player); | |
if (player == "X") { | |
player = "O"; | |
betterAI(); | |
} else if (player == "O") { | |
player = "X"; | |
} | |
setTimeout(checkGame(), 500); | |
} else { | |
alert("Already Placed!"); | |
} | |
}); | |
function checkGame() { | |
var result = checkIt(); | |
if (result == "X") { | |
$("#board").fadeOut(500); | |
$("#endMessage").html("Player X Won."); | |
setTimeout(function() { | |
$("#end").fadeIn(500); | |
}, 501); | |
} | |
if (result == "O") { | |
$("#board").fadeOut(500); | |
$("#endMessage").html("Player O Won."); | |
setTimeout(function() { | |
$("#end").fadeIn(500); | |
}, 501); | |
} | |
if (result == "tie") { | |
$("#board").fadeOut(500); | |
$("#endMessage").html("There was a tie."); | |
setTimeout(function() { | |
$("#end").fadeIn(500); | |
}, 501); | |
} | |
} | |
function checkIt() { | |
if (checkBoard("X") == "tie") { | |
return "tie"; | |
} | |
if (checkBoard("X") === true) { | |
return "X"; | |
} | |
if (checkBoard("O") === true) { | |
return "O"; | |
} | |
return false; | |
} | |
function checkBoard(p) { | |
board = getGameBoard(); | |
array = []; | |
if (board[0] == p && board[1] == p && board[2] == p) { | |
return true; | |
} | |
if (board[3] == p && board[4] == p && board[5] == p) { | |
return true; | |
} | |
if (board[6] == p && board[7] == p && board[8] == p) { | |
return true; | |
} | |
if (board[0] == p && board[3] == p && board[6] == p) { | |
return true; | |
} | |
if (board[1] == p && board[4] == p && board[7] == p) { | |
return true; | |
} | |
if (board[2] == p && board[5] == p && board[8] == p) { | |
return true; | |
} | |
if (board[0] == p && board[4] == p && board[8] == p) { | |
return true; | |
} | |
if (board[2] == p && board[4] == p && board[6] == p) { | |
return true; | |
} | |
for (z = 0; z < board.length; z++) { | |
if (board[z] === "") { | |
return false; | |
} | |
} | |
return "tie"; | |
} | |
function getGameBoard() { | |
var array = []; | |
$(".place").each(function() { | |
array.push($(this).attr("data-place")); | |
}); | |
return array; | |
} | |
function getRandomInt(min, max) { | |
return Math.floor(Math.random() * (max - min + 1)) + min; | |
} | |
function random() { | |
var board = getGameBoard(); | |
var choices = []; | |
board.map(function(x, y) { | |
if (x === "") { | |
choices.push(y); | |
} | |
}); | |
var i = getRandomInt(0, choices.length - 1); | |
console.log(choices); | |
$(".place").get(choices[i]).click(); | |
setTimeout(checkGame(), 500); | |
} | |
function boardMatchPattern(pattern, player) { | |
var matches = 0; | |
var board = getGameBoard(); | |
pattern.map(function(x) { | |
if (board[x] === player) { | |
matches++; | |
} | |
}); | |
if (matches == pattern.length) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
function betterAI() { | |
setTimeout(checkGame(), 500); | |
var actions = []; | |
defenses.map(function(x) { | |
if (x.type == "3") { | |
x.pattern.map(function(xx, index) { | |
if ( | |
boardMatchPattern(xx, "X") && | |
getGameBoard()[x.action[index]] === "" | |
) { | |
actions.push({ action: x.action[index], priority: x.priority }); | |
} | |
}); | |
} | |
}); | |
attacks.map(function(x) { | |
if (x.type == "3") { | |
x.pattern.map(function(xx, index) { | |
if ( | |
boardMatchPattern(xx, "O") && | |
getGameBoard()[x.action[index]] === "" | |
) { | |
actions.push({ action: x.action[index], priority: x.priority }); | |
} | |
}); | |
} | |
/* | |
if (x.type == "empty") { | |
actions.push({ action: x.action, priority: x.priority }); | |
} | |
*/ | |
if (x.type == "available") { | |
if (getGameBoard()[x.pattern[0]] === "") { | |
actions.push({ action: x.action, priority: x.priority }); | |
} | |
} | |
if (x.type == "fullBoard") { | |
console.log(getGameBoard()) | |
console.log(x.pattern.pattern) | |
if (getGameBoard().toString() == x.pattern.pattern.toString()) { | |
actions.push({action: x.action, priority: x.priority}) | |
} else { | |
console.log(getGameBoard() == x.pattern.pattern) | |
} | |
} | |
}); | |
actions.sort(function(a, b) { | |
return b.priority - a.priority; | |
}); | |
console.log(actions); | |
if (actions.length !== 0) { | |
$(".place").get(actions[0].action).click(); | |
} else { | |
random(); | |
} | |
setTimeout(checkGame(), 500); | |
} | |
function registerAttack(pattern, action, priority) { | |
var actions = []; | |
if (pattern.type == "3") { | |
var patterns = []; | |
for (y = 0; y < threes.length; y++) { | |
var x = threes[y]; | |
var final = []; | |
for (yy = 0; yy < pattern.pattern.length; yy++) { | |
final.push(x[pattern.pattern[yy] - 1]); | |
} | |
patterns.push(final); | |
actions.push(x[action - 1]); | |
} | |
attacks.push({ | |
type: "3", | |
pattern: patterns, | |
action: actions, | |
priority: priority | |
}); | |
} | |
if (pattern.type == "empty") { | |
attacks.push({ type: "empty", action: action, priority: priority }); | |
} | |
if (pattern.type == "available") { | |
attacks.push({ | |
type: "available", | |
pattern: pattern.pattern, | |
priority: priority, | |
action: action | |
}); | |
} | |
if (pattern.type == "fullBoard") { | |
attacks.push({type: "fullBoard", pattern: pattern, action: action, priority: priority}) | |
} | |
} | |
function registerDefence(pattern, action, priority) { | |
var actions = []; | |
if (pattern.type == "3") { | |
var patterns = []; | |
for (y = 0; y < threes.length; y++) { | |
var x = threes[y]; | |
var final = []; | |
for (yy = 0; yy < pattern.pattern.length; yy++) { | |
final.push(x[pattern.pattern[yy] - 1]); | |
} | |
patterns.push(final); | |
actions.push(x[action - 1]); | |
} | |
defenses.push({ | |
type: "3", | |
pattern: patterns, | |
action: actions, | |
priority: priority | |
}); | |
} | |
} | |
registerDefence({ type: "3", pattern: [1, 3] }, 2, 2); | |
registerDefence({ type: "3", pattern: [1, 2] }, 3, 2); | |
registerDefence({ type: "3", pattern: [2, 3] }, 1, 2); | |
registerAttack({ type: "3", pattern: [1] }, 3, 1); | |
registerAttack({ type: "3", pattern: [2] }, 1, 1); | |
registerAttack({ type: "3", pattern: [3] }, 1, 1); | |
registerAttack({ type: "3", pattern: [1, 3] }, 2, 10); | |
registerAttack({ type: "3", pattern: [1, 2] }, 3, 10); | |
registerAttack({ type: "3", pattern: [2, 3] }, 1, 10); | |
//registerAttack({ type: "empty" }, 0, 10); | |
registerAttack({ type: "available", pattern: [4] }, 4, 1); | |
registerAttack({ type: "fullBoard", pattern: ["", "", "", "", "X", "", "", "", ""]}, 0, 10) | |
console.log(defenses); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* { | |
font-family: 'Dosis', sans-serif; | |
} | |
body { | |
width: 100vw; | |
height: 100vh; | |
margin: 0; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
} | |
.button { | |
background-color: white; | |
color: #3F51B5; | |
border: 2px solid #3F51B5; | |
transition: all 0.3s; | |
min-width: 15vw; | |
height: 10vh; | |
outline: 0; | |
} | |
.button-large { | |
font-size: 5vh; | |
} | |
.button-large:hover { | |
background-color: #3F51B5; | |
color: white; | |
border: 2px solid #3F51B5; | |
transition: all 0.3s; | |
} | |
.right-margin { | |
margin-right: 5px; | |
} | |
.left-margin { | |
margin-left: 5px; | |
} | |
.title { | |
font-size: 5vh; | |
} | |
.place { | |
width: 20vmin; | |
height: 20vmin; | |
font-size: 10vmin; | |
background-color: white; | |
margin: 0; | |
padding: 0; | |
border: none; | |
vertical-align: top; | |
outline: 0; | |
} | |
#top-left { | |
border-right: 2px solid black; | |
border-bottom: 2px solid black; | |
} | |
#top-middle { | |
border-bottom: 2px solid black; | |
} | |
#middle-left { | |
border-right: 2px solid black; | |
border-bottom: 2px solid black; | |
} | |
#bottom-left { | |
border-right: 2px solid black; | |
} | |
#bottom-right { | |
border-left: 2px solid black; | |
} | |
#top-right { | |
border-left: 2px solid black; | |
border-bottom: 2px solid black; | |
} | |
#middle-right { | |
border-left: 2px solid black; | |
border-bottom: 2px solid black; | |
} | |
#middle-middle { | |
border-bottom: 2px solid black; | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link href="https://fonts.googleapis.com/css?family=Dosis:400,600" rel="stylesheet" /> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment