-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from ridgey28/V2.0
*** New version 2.0
- Loading branch information
Showing
21 changed files
with
648 additions
and
204 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
.DS_Store | ||
node_modules | ||
bun.lockb | ||
.vscode |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"tabWidth": 2, | ||
"useTabs": false | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,35 @@ | ||
|
||
# JS-Guessing-Game | ||
A very simple HTML, CSS and JavaScript Guessing Game tutorial. Dependency free. Uses browser sessionStorage. The tutorial can be found at https://wp.me/poe8j-3uC | ||
A simple HTML, CSS and JavaScript Guessing Game tutorial. Dependency free. Uses browser sessionStorage. The tutorial can be found at https://wp.me/poe8j-3uC | ||
|
||
## New Features in V2 | ||
Rewritten in TypeScript and compiled to JavaScript. Added levels, state management and localStorage, notifications. | ||
|
||
## How to run | ||
You can run directly from the dist folder or compile from src if you want to make changes. | ||
I have installed the following: | ||
- Sass Dart CLI | ||
- TypeScript CLI | ||
- Bun to install the Bulma package | ||
|
||
## Recommends | ||
Running with VS Code live server extension. It should work on all modern browsers. | ||
Running with VS Code live server extension. It should work on all modern browsers. | ||
|
||
## Other Info | ||
Request features, Roll your own, Share and have fun! | ||
|
||
|
||
|
||
## Special Thanks | ||
|
||
[Bun](https://bun.sh/) | ||
|
||
[Bulma](https://bulma.io/) | ||
|
||
[FrontEnd Masters](https://frontendmasters.com/blog/vanilla-javascript-reactivity/) | ||
|
||
## License | ||
|
||
Add badges from: [shields.io](https://shields.io/) | ||
|
||
[![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/) |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
This favicon was generated using the following font: | ||
|
||
- Font Title: Lalezar | ||
- Font Author: Copyright 2015 by Borna Izadpanah (www.borna.design). All rights reserved. | ||
- Font Source: https://fonts.gstatic.com/s/lalezar/v14/zrfl0HLVx-HwTP82UaDyIiL0RCg.ttf | ||
- Font License: SIL Open Font License, 1.1 (http://scripts.sil.org/OFL)) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<!DOCTYPE html> | ||
<html lang="en-gb"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<meta name="color-scheme" content="light dark"> | ||
<link rel="stylesheet" href="css/style.min.css"> | ||
<title>JavaScript Guessing Game</title> | ||
<link rel="apple-touch-icon" sizes="180x180" href="images/apple-touch-icon.png"> | ||
<link rel="icon" type="image/png" sizes="32x32" href="images/favicon-32x32.png"> | ||
<link rel="icon" type="image/png" sizes="16x16" href="images/favicon-16x16.png"> | ||
<link rel="manifest" href="images/site.webmanifest"> | ||
</head> | ||
<body> | ||
<section class="hero is-fullheight"> | ||
<div class="hero-head"> | ||
<nav class="navbar"> | ||
<div class="container"> | ||
<div class="navbar-brand"> | ||
<span class="navbar-item"> | ||
<h1 class="is-size-3 has-text-weight-bold">JS Guessing Game</h1> | ||
</span> | ||
</div> | ||
</div> | ||
</nav> | ||
|
||
</div> | ||
<div class="hero-body"> | ||
<div class="container"> | ||
<h2 class="title" id="message">Pick a number</h2> | ||
<div id="btn-group" class="block"> | ||
<button id="easy" class="btn-level button is-primary is-rounded">Easy</button> | ||
<button id="medium" class="btn-level button is-primary is-rounded">Medium</button> | ||
<button id="hard" class="btn-level button is-primary is-rounded">Hard</button> | ||
</div> | ||
<form class="form" id="guess-container"> | ||
<div class="field has-addons"> | ||
<div class="control is-expanded"> | ||
<input class="input is-large" type="number" min="1" max="100" id="guess" placeholder="Number"> | ||
</div> | ||
<div class="control"> | ||
<button id="btn" class="is-large button is-link">Submit</button> | ||
</div> | ||
</div> | ||
<div>Press <kbd>Enter</kbd></div> | ||
</form> | ||
<div class="tags mt-2" id="tags">Your guesses will display here</div> | ||
</div> | ||
</div> | ||
<div class="hero-foot"> | ||
<div class="content has-text-centered"> | ||
<p class="small">Made by Tracy Ridge</p> | ||
</div> | ||
<div class="notify"></div> | ||
</div> | ||
</section> | ||
<script src="./js/js-guessing-game.js" async></script> | ||
</body> | ||
</html> |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
"use strict"; | ||
/** | ||
* | ||
* JavaScript Guesing Game V2.0.0 | ||
* Author: Tracy Ridge | ||
* URL: https://www.worldoweb.co.uk/ | ||
* Part 1 - Page URL: https://wp.me/poe8j-3uC | ||
* Part 2 - Page URL: https://wp.me/poe8j-3wO | ||
* Part 3 - Page URL: | ||
*/ | ||
/** | ||
* Manages the state of the levels | ||
*/ | ||
const max = 100; | ||
const min = 1; | ||
let currentLevel = localStorage.getItem("level"); | ||
let level_arr = ["10", "5", "2"]; | ||
let diff = currentLevel !== null && currentLevel !== void 0 ? currentLevel : "5"; | ||
const level = { | ||
_difficulty: diff, | ||
}; | ||
Object.defineProperty(level, "difficulty", { | ||
get: function () { | ||
return this._difficulty; | ||
}, | ||
set: function (value) { | ||
this._difficulty = value; | ||
}, | ||
}); | ||
/** | ||
* Shorthand Get Element By ID | ||
*/ | ||
const getID = (id) => { | ||
return document.getElementById(id); | ||
}; | ||
/** | ||
* Executes on browser load. Saves computer guess to browser session if not set. | ||
*/ | ||
window.onload = () => { | ||
const guessInput = getID("guess"); | ||
if (guessInput !== null) { | ||
guessInput.focus(); | ||
} | ||
setLevelActive(); | ||
generateComputerGuess(); | ||
}; | ||
const setLevelActive = () => { | ||
let btnLevel = document.querySelectorAll(".btn-level"); | ||
if (currentLevel !== null) { | ||
let levelIndex = level_arr.findIndex((value) => value === currentLevel); | ||
btnLevel[levelIndex].classList.add("is-active"); | ||
} | ||
else { | ||
btnLevel[1].classList.add("is-active"); | ||
localStorage.setItem("level", level._difficulty); | ||
} | ||
btnLevel.forEach((btn) => { | ||
btn.addEventListener("click", (e) => { | ||
const totalGuesses = countGuesses(); | ||
btnLevel === null || btnLevel === void 0 ? void 0 : btnLevel.forEach((btn) => btn.classList.remove("is-active")); | ||
e.target.classList.add("is-active"); | ||
let value = e.target.textContent; | ||
switch (value) { | ||
case "Easy": | ||
level._difficulty = "10"; | ||
break; | ||
case "Medium": | ||
level._difficulty = "5"; | ||
break; | ||
case "Hard": | ||
level._difficulty = "2"; | ||
break; | ||
} | ||
localStorage.setItem("level", level._difficulty); | ||
if (totalGuesses > level._difficulty) { | ||
notify("You have already had more guesses than the difficulty chosen. Choose another level or your game will end!"); | ||
} | ||
}); | ||
}); | ||
}; | ||
const generateComputerGuess = () => { | ||
let genGuess = Math.floor(Math.random() * (max - min) + min), arr = ["computer-guess", genGuess], session = getSession(arr); | ||
displayGuesses(); | ||
if (session === null) { | ||
addToSession(arr); | ||
} | ||
}; | ||
/** | ||
* Stores data in sessionStorage. Merges data if already exists | ||
*/ | ||
const addToSession = (item) => { | ||
//Check if a session is set | ||
let session = getSession(item), data = [], store = item[0], saveData = item[1], sessionData = []; | ||
data.push(saveData); | ||
// If the session return nothing | ||
if (session === null) { | ||
//create for the first time | ||
sessionData = data; | ||
} | ||
else { | ||
//grab data and merge | ||
session.push(data); | ||
sessionData = session; | ||
} | ||
sessionStorage.setItem(store, JSON.stringify(sessionData.flat())); | ||
}; | ||
/** | ||
* Get data out of session storage | ||
*/ | ||
const getSession = (item) => { | ||
var _a; | ||
let store = (_a = item[0]) !== null && _a !== void 0 ? _a : ""; | ||
const storedItem = sessionStorage.getItem(store); | ||
return storedItem !== null ? JSON.parse(storedItem) : null; | ||
}; | ||
/** | ||
* Checks the user submitted number against the generated one | ||
*/ | ||
const checkGuess = (guess) => { | ||
addToSession(guess); | ||
// Get user generated number | ||
let generatedNumber = getSession(["computer-guess", null]), message = getID("message"), total_guesses = countGuesses(); | ||
if (total_guesses < parseInt(level._difficulty)) { | ||
if (parseInt(guess[1]) !== generatedNumber[0]) { | ||
higherOrLower(message, guess[1], generatedNumber[0]); | ||
return; | ||
} | ||
else if (message !== null) { | ||
message.innerText = | ||
"Jackpot, you won. You guessed it within " + total_guesses + " tries"; | ||
} | ||
} | ||
else { | ||
notify("You lose, you have reached the maximum guesses."); | ||
} | ||
clearSession(); | ||
}; | ||
/** | ||
* Checks to see if your number matches the computer one | ||
*/ | ||
const higherOrLower = (message, num, num2) => { | ||
if (message !== null) { | ||
if (parseInt(num) > num2) { | ||
message.innerText = "You need to go lower 👇"; | ||
} | ||
else { | ||
message.innerText = "You need to go higher ☝️"; | ||
} | ||
} | ||
}; | ||
/** | ||
* Counts the user guesses | ||
*/ | ||
const countGuesses = () => { | ||
let userGuess = getSession(["user-guess", null]), guesses = userGuess !== null ? userGuess.length : 0; | ||
return guesses; | ||
}; | ||
/** | ||
* Starts a new game by clearing a session and reloading the page | ||
*/ | ||
const clearSession = () => { | ||
setTimeout(() => { | ||
sessionStorage.clear(); | ||
location.reload(); | ||
}, 5000); | ||
}; | ||
/** | ||
* Displays the user guesses in a tag format | ||
*/ | ||
const displayGuesses = () => { | ||
let guess = getSession(["user-guess", null]); | ||
let tagsElement = getID("tags"); | ||
if (guess !== null && tagsElement !== null) { | ||
tagsElement.textContent = ""; | ||
guess.forEach((item) => { | ||
let span = document.createElement("span"), text = document.createTextNode(item); | ||
span.classList.add("tag"); | ||
span.appendChild(text); | ||
tagsElement.appendChild(span); | ||
}); | ||
} | ||
}; | ||
/** | ||
* Create notifications | ||
*/ | ||
const notify = (msg) => { | ||
let notification = document.createElement("div"); | ||
let deleteButton = document.createElement("button"); | ||
deleteButton.addEventListener("click", removeNotification); | ||
deleteButton.className = "delete"; | ||
notification.className = "notification"; | ||
notification.textContent = msg; | ||
notification.prepend(deleteButton); | ||
const heroHead = document.querySelector(".notify"); | ||
if (heroHead !== null) { | ||
heroHead.appendChild(notification); | ||
} | ||
}; | ||
/** | ||
* Removes notifications | ||
*/ | ||
const removeNotification = () => { | ||
let notification = document.querySelectorAll(".notification"); | ||
notification.forEach((item) => { | ||
item.remove(); | ||
}); | ||
}; | ||
/* | ||
* Adds event listener to the submit button | ||
*/ | ||
const btnElement = getID("btn"); | ||
if (btnElement !== null) { | ||
btnElement.addEventListener("click", (e) => { | ||
e.preventDefault(); | ||
let userGuess = getID("guess"), usrArr = [], data = getSession(["user-guess", null]); | ||
if (parseInt(userGuess.value) < min || parseInt(userGuess.value) > max) { | ||
notify(`Please enter a number between ${min} and ${max}`); | ||
return; | ||
} | ||
if (userGuess !== null && userGuess.value === "") { | ||
notify("Please enter a number"); | ||
return; | ||
} | ||
if (data === null || data === void 0 ? void 0 : data.includes(userGuess.value)) { | ||
notify("Number already picked"); | ||
return; | ||
} | ||
usrArr = ["user-guess", userGuess.value]; | ||
checkGuess(usrArr); | ||
displayGuesses(); | ||
userGuess.value = ""; | ||
}); | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.