Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
30 changes: 30 additions & 0 deletions tictactoe/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tic Tac Toe</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Intel+One+Mono:ital,wght@0,300..700;1,300..700&family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="title"><h1><span>Tic</span> Tac <span>Toe</span></h1></div>
<div id="middle">
<div class="game">
<button id="1" onclick="pressed(1)"></button>
<button id="2" onclick="pressed(2)"></button>
<button id="3" onclick="pressed(3)"></button>
<button id="4" onclick="pressed(4)"></button>
<button id="5" onclick="pressed(5)"></button>
<button id="6" onclick="pressed(6)"></button>
<button id="7" onclick="pressed(7)"></button>
<button id="8" onclick="pressed(8)"></button>
<button id="9" onclick="pressed(9)"></button>
</div>
<button id="restart" onclick="changeStartTurn()">Restart</button>
</div>
<script src="script.js"></script>
</body>
</html>
131 changes: 131 additions & 0 deletions tictactoe/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
let startingTurn = true;
let excluded = [];
let userMoves = [];
let computerMoves = [];

// Buttons
const cell1 = document.getElementById("1");
const cell2 = document.getElementById("2");
const cell3 = document.getElementById("3");
const cell4 = document.getElementById("4");
const cell5 = document.getElementById("5");
const cell6 = document.getElementById("6");
const cell7 = document.getElementById("7");
const cell8 = document.getElementById("8");
const cell9 = document.getElementById("9");

// ID to element map for convenience
const cells = {
1: cell1, 2: cell2, 3: cell3,
4: cell4, 5: cell5, 6: cell6,
7: cell7, 8: cell8, 9: cell9
};

// Reset and change who starts
const changeStartTurn = () => {
startingTurn = !startingTurn;
excluded = [];
userMoves = [];
computerMoves = [];

for (let i = 1; i <= 9; i++) {
cells[i].innerText = "";
cells[i].disabled = false;
}

if (!startingTurn) {
setTimeout(computerPress, 300);
}
};

// When user presses
const pressed = (cellNumber) => {
if (excluded.includes(cellNumber)) return;

cells[cellNumber].innerText = "X";
cells[cellNumber].disabled = true;
excluded.push(cellNumber);
userMoves.push(cellNumber);

if (checkWin(userMoves)) {
alert("You win!");
disableAll();
return;
}

if (excluded.length === 9) {
alert("Draw!");
return;
}

setTimeout(computerPress, 500);
};

// When computer plays
const computerPress = () => {
let move = determineDanger();

if (!move) move = getRandomExcluding(excluded);
if (!move) return;

cells[move].innerText = "O";
cells[move].disabled = true;
excluded.push(move);
computerMoves.push(move);

if (checkWin(computerMoves)) {
alert("Computer wins!");
disableAll();
}
};

// Checks for win
const checkWin = (moves) => {
const 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]
];
return wins.some(combo => combo.every(n => moves.includes(n)));
};

// Try to block user
const determineDanger = () => {
const 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]
];

for (let combo of wins) {
const userHits = combo.filter(c => userMoves.includes(c));
const empty = combo.filter(c => !excluded.includes(c));
if (userHits.length === 2 && empty.length === 1) {
return empty[0];
}
}

return null;
};

// Random move
function getRandomExcluding(excluded) {
let available = [];
for (let i = 1; i <= 9; i++) {
if (!excluded.includes(i)) {
available.push(i);
}
}
if (available.length === 0) return null;
return available[Math.floor(Math.random() * available.length)];
}

// Disable all buttons
function disableAll() {
for (let i = 1; i <= 9; i++) {
cells[i].disabled = true;
}
}



68 changes: 68 additions & 0 deletions tictactoe/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
html{
font-family: "Open Sans", sans-serif;
font-optical-sizing: auto;
font-weight: <weight>;
font-style: normal;
font-variation-settings:
"wdth" 100;
}

body{
background:#E0E1DD;
color:#0D1B2A;
}

#title{
display:flex;
width:100%;
align-items:center;
justify-content: center;
color:#778DA9;
}

#middle{
display:flex;
flex-direction:column;
width:100%;
align-items:center;
justify-content: center;
margin-top:5em;
}

.game{
display:grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap:0.5em;
width:20em;
height:20em;
align-items:center;
justify-content: center;
}

button{
background:#415A77;
border:none;
display:flex;
align-items: center;
justify-content: center;
padding:1em;
height:100%;
width:100%;
color:#E0E1DD;
font-size:1.5em;
}

button:hover{
background:#0D1B2A;
cursor:pointer;
}

span{
color:#415A77 !important;
}

#restart{
margin-top: 5em;
width:30rem;
}