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
Empty file added solution.md
Empty file.
32 changes: 32 additions & 0 deletions tic-tac-toe/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tic-Tac-Toe</title>
<link href="styles.css" rel="stylesheet">
</head>
<body>
<div class="title">
Tic Tac Toe
</div>
<div>
<div id="canva">
<div class="box" data-index="0"></div>
<div class="box" data-index="1"></div>
<div class="box" data-index="2"></div>
<div class="box" data-index="3"></div>
<div class="box" data-index="4"></div>
<div class="box" data-index="5"></div>
<div class="box" data-index="6"></div>
<div class="box" data-index="7"></div>
<div class="box" data-index="8"></div>
</div>
<div class="bottom">
<h1 id="player"></h3>
<button id="newGame">New Game</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
107 changes: 107 additions & 0 deletions tic-tac-toe/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
const cells = document.querySelectorAll(".box");
const chance = document.querySelector("#player");
const newButton = document.querySelector("#newGame");

let vict = 0;
let symbol;
let cellX = [];
let cellO = [];
let currentIndex = 0; // Keep track of keyboard navigation

const winningPossibilities = [
['0', '1', '2'],
['3', '4', '5'],
['6', '7', '8'],
['0', '3', '6'],
['1', '4', '7'],
['2', '5', '8'],
['0', '4', '8'],
['2', '4', '6'],
];

newButton.addEventListener("click", startGame);
document.addEventListener("keydown", handleKeyboardNavigation);


function startGame() {
newButton.blur();
symbol = "O";
cellO = [];
cellX = [];
vict = 0;
currentIndex = 0;
chance.innerHTML = `${symbol}'s turn`;

cells.forEach(cell => {
cell.innerHTML = "";
cell.classList.remove("highlight");
cell.removeEventListener("click", instantiate);
cell.addEventListener("click", instantiate);
});


}

function changePlayer() {
symbol = symbol === "O" ? "X" : "O";
chance.innerHTML = `${symbol}'s turn`;
}

function winGame(playerCells, player) {
if (winningPossibilities.some(pattern => pattern.every(index => playerCells.includes(index)))) {
chance.innerHTML = `${player} has won the game!`;
vict = 1;
return;
}
if (cellX.length + cellO.length === 9) {
chance.innerHTML = "It's a draw!";
vict = 1;
return;
}
changePlayer();
}

function instantiate(event) {
let cell = event.target;
if (cell.innerHTML !== "" || vict > 0) return; // Prevent overwriting or playing after a win

let index = cell.getAttribute("data-index"); // Get the cell index

cell.innerHTML = symbol;
if (symbol === "X") {
cellX.push(index);
cellX.sort();
} else {
cellO.push(index);
cellO.sort();
}

winGame(symbol === "X" ? cellX : cellO, symbol);
}

function handleKeyboardNavigation(event) {
if (vict > 0) return; // Stop if the game is over

const rowSize = 3;
if (event.key === "ArrowRight") {
currentIndex = (currentIndex + 1) % cells.length;
} else if (event.key === "ArrowLeft") {
currentIndex = (currentIndex - 1 + cells.length) % cells.length;
} else if (event.key === "ArrowDown") {
currentIndex = (currentIndex + rowSize) % cells.length;
} else if (event.key === "ArrowUp") {
currentIndex = (currentIndex - rowSize + cells.length) % cells.length;
} else if (event.key === "Enter") {
instantiate({ target: cells[currentIndex] }); // Fix: Ensure Enter key works
}

highlightCell();
}

function highlightCell() {
cells.forEach(cell => cell.classList.remove("highlight"));
cells[currentIndex].classList.add("highlight");
}



50 changes: 50 additions & 0 deletions tic-tac-toe/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#canva{
width: 500px;
height: 500px;
border: solid 2px black;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
justify-self: center;
}

.highlight{
border: solid 2px black;
font-size: 80px;
text-align: center;
line-height: 160px;
background-color: rgb(4, 238, 238);
}

.title{
font-size: 40px;
letter-spacing: 8px;
margin: 40px 0px;
font-weight: bolder;
font-family: 'Times New Roman', Times, serif;
text-align: center;
}

.bottom{
justify-items: center;
margin-top: 60px;
}

.box{
border: solid 2px black;
font-size: 80px;
text-align: center;
line-height: 160px;
}

#player{
font-size: 40px;;
}

button{
margin-top: 20px;
width: 200px;
height: 50px;
font-size: 30px;
background-color: greenyellow;
}
3 changes: 3 additions & 0 deletions typing-game-solution/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"liveServer.settings.port": 5501
}
22 changes: 22 additions & 0 deletions typing-game-solution/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<html>
<head>
<title>Typing game</title>
<link rel="stylesheet" href="style.css">
<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=Fondamento:ital@0;1&display=swap" rel="stylesheet">
</head>
<body>
<div>
<h1>Typing game !</h1>
<p>Practice your typing skills with a quote from Sherlock Holmes. Click **start** to begin!</p>
<p id="quote"></p>
<p id="message"></p>
</div>
<div class="typing">
<input type="text" aria-label="current word" id="typed-value" />
<button type="button" id="start">Start</button>
</div>
<script src="script.js"></script>
</body>
</html>
97 changes: 97 additions & 0 deletions typing-game-solution/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// inside script.js
// all of our quotes
const quotes = [
'When you have eliminated the impossible, whatever remains, however improbable, must be the truth.',
'There is nothing more deceptive than an obvious fact.',
'I ought to know by this time that when a fact appears to be opposed to a long train of deductions it invariably proves to be capable of bearing some other interpretation.',
'I never make exceptions. An exception disproves the rule.',
'What one man can invent another can discover.',
'Nothing clears up a case so much as stating it to another person.',
'Education never ends, Watson. It is a series of lessons, with the greatest for the last.',
'Mediocrity knows nothing higher than itself; but talent instantly recognizes genius.',
'What you do in this world is a matter of no consequence. The question is what can you make people believe you have done.',
'Crime is common. Logic is rare. Therefore it is upon the logic rather than upon the crime that you should dwell.',
];
// store the list of words and the index of the word the player is currently typing
let words = [];
let wordIndex = 0;
// the starting time
let startTime = Date.now();
// page elements
const quoteElement = document.getElementById('quote');
const messageElement = document.getElementById('message');
const typedValueElement = document.getElementById('typed-value');

// at the end of script.js
document.getElementById('start').addEventListener('click', () => {
// get a quote
typedValueElement.disabled=false;
const quoteIndex = Math.floor(Math.random() * quotes.length);
const quote = quotes[quoteIndex];
// Put the quote into an array of words
words = quote.split(' ');
// reset the word index for tracking
wordIndex = 0;

// UI updates
// Create an array of span elements so we can set a class
const spanWords = words.map(function(word) { return `<span>${word} </span>`});
// Convert into string and set as innerHTML on quote display
quoteElement.innerHTML = spanWords.join('');
// Highlight the first word
quoteElement.childNodes[0].className = 'highlight';
// Clear any prior messages
messageElement.innerText = '';

// Setup the textbox
// Clear the textbox
typedValueElement.value = '';
// set focus
typedValueElement.focus();
// set the event handler

// Start the timer
startTime = new Date().getTime();
});

// at the end of script.js
typedValueElement.addEventListener('input', getInput);



function getInput(){
// Get the current word
const currentWord = words[wordIndex];
// get the current value
const typedValue = typedValueElement.value;

if (typedValue === currentWord && wordIndex === words.length - 1) {
// end of sentence
// Display success
const elapsedTime = new Date().getTime() - startTime;
const message = `CONGRATULATIONS! You finished in ${elapsedTime / 1000} seconds.`;
messageElement.innerText = message;
typedValueElement.removeEventListener('input',getInput);
typedValueElement.disabled=true;
} else if (typedValue.endsWith(' ') && typedValue.trim() === currentWord) {
// end of word
// clear the typedValueElement for the new word
typedValueElement.value = '';
// move to the next word
wordIndex++;
// reset the class name for all elements in quote
for (const wordElement of quoteElement.childNodes) {
wordElement.className = '';
}
// highlight the new word
quoteElement.childNodes[wordIndex].className = 'highlight';
} else if (currentWord.startsWith(typedValue)) {
// currently correct
// highlight the next word
typedValueElement.className='';
typedValueElement.disabled=false;
} else {
// error state
typedValueElement.className = 'error';
}
}
62 changes: 62 additions & 0 deletions typing-game-solution/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.highlight {
background-color: rgb(7, 182, 235);
}

.error {
background-color: lightcoral;
border: red;
width: 220px;
height: 45px;
font-size: 25px;
font-weight: bolder;
}

body{
background-color: rgb(12, 2, 2);
}

h1{
font-family: 'Fondamento',serif;
font-size: 80px;
color: blueviolet;
text-align: center;
}

p{
font-family: 'Fondamento',serif;
font-size: 40px;
color: yellow;
text-align: center;
}

input {
width: 220px;
height: 45px;
font-size: 25px;
font-weight: bolder;
}

input:disabled {
width: 0px;
height: 0px;
background-color: rgb(12, 2, 2);
}

input:focus{
outline: none;
border: none;
}

button{
height: 45px;
margin-left: 30px;
border-color: white;
width: 70px;
font-size: 20px;
font-weight: bolder;
}

.typing{
margin-top: 90px;
margin-left: 40%;
}