diff --git a/README.md b/README.md index 791b22b..0ed1a8a 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,14 @@ It is mobile and desktop friendly, and is written in pure vanilla JavaScript. After words clear, does not re-fill the board, try to get the highest score! ## Endless Mode -After clearing words, board will re-fill with more and more letters! +After clearing words, board will re-fill with more and more letters! ## Blitz Mode -Only get 90 seconds to get as high of a score as you can! +Only get 90 seconds to get as high of a score as you can! +# Development + +You can open the files manually, or if you'd like to mimic a static web server, run the command below: +``` +npx serve +``` diff --git a/blitz.html b/blitz.html index 3a82f24..f0920ea 100644 --- a/blitz.html +++ b/blitz.html @@ -10,6 +10,7 @@ content="https://user-images.githubusercontent.com/1131494/156868819-573c8853-ad4b-4c30-8594-cb80e9eb1a91.jpg" /> + diff --git a/blitz.js b/blitz.js index 940a951..b6ada7a 100644 --- a/blitz.js +++ b/blitz.js @@ -20,163 +20,6 @@ let seed = const logger = getLogger({ mode: "Blitz", seed }); -function random() { - var x = Math.sin(seed++) * 10000; - return x - Math.floor(x); -} - -const randomLetter = () => characters[Math.floor(random() * characters.length)]; - -const addLetterBubble = (row, col) => { - const posX = row * 60; - const posY = col * 60; - const element = document.createElement("div"); - element.classList.add("letter-item"); - element.onclick = ({ target: { innerText } }) => { - handleKeyDown({ key: innerText.toLowerCase() }); - }; - element.dataset.row = row; - element.dataset.col = col; - - element.style.left = posX; - element.style.top = posY; - element.innerText = randomLetter(); - letterGridElement.appendChild(element); -}; - -const buildGrid = () => { - for (let row = 0; row < rows; row++) { - for (let col = 0; col < cols; col++) { - addLetterBubble(row, col); - } - } -}; - -const shuffleGrid = () => { - const allLetters = [...document.querySelectorAll(".letter-item")]; - - let currentIndex = allLetters.length; - let randomIndex; - - // While there remain elements to shuffle... - while (currentIndex !== 0) { - // Pick a remaining element... - randomIndex = Math.floor(random() * currentIndex); - currentIndex--; - - // And swap it with the current element. - [allLetters[currentIndex], allLetters[randomIndex]] = [ - allLetters[randomIndex], - allLetters[currentIndex], - ]; - } - - allLetters.forEach((letter, index) => { - const row = Math.floor(index / 5); - const col = Math.floor(index % 5); - letter.style.left = row * 60; - letter.style.top = col * 60; - - letter.dataset.row = row; - letter.dataset.col = col; - }); -}; - -const unselectLetters = () => { - const allLetters = document.querySelectorAll(".letter-item"); - allLetters.forEach((elements) => elements.classList.remove("on")); -}; - -const clearWord = () => { - [...wordInputWrapperElement.children].forEach((letterElement) => { - wordInputWrapperElement.removeChild(letterElement); - }); - word = ""; -}; - -const markAsBadWord = () => { - const allLetters = document.querySelectorAll(".letter-typed"); - allLetters.forEach((letterElement) => { - letterElement.classList.remove("added"); - letterElement.classList.add("rejected"); - }); - setTimeout(() => { - const allLetters = document.querySelectorAll(".letter-typed"); - allLetters.forEach((letterElement) => { - letterElement.classList.remove("rejected"); - }); - }, 150); -}; - -const adjacentItemsNotInChain = (chain) => { - const lastItem = chain[chain.length - 1]; - const { row, col } = lastItem.dataset; - const allLetters = document.querySelectorAll(".letter-item"); - let arrayReturn = []; - allLetters.forEach((element) => { - const { row: elementRow, col: elementCol } = element.dataset; - const elementIsAdjacent = - Math.abs(row - elementRow) <= 1 && Math.abs(col - elementCol) <= 1; - const elementIsInChain = chain.includes(element); - if (!elementIsInChain && elementIsAdjacent) { - arrayReturn.push(element); - } - }); - return arrayReturn; -}; - -const evaluateWordElements = () => { - if (!word) { - wordChains = []; - return; - } - const allLetters = document.querySelectorAll(".letter-item"); - if (word[0]) { - // get first letter - allLetters.forEach((element) => { - const isKey = element.innerText == word[0].toUpperCase(); - if (isKey) { - wordChains.push([element]); - } - }); - } - - for (charIndex in word) { - if (charIndex == 0) { - continue; // already done above - } - for (chainArrayIndex in wordChains) { - const chainArray = wordChains[chainArrayIndex]; - const itemsWithCharacter = ( - (chainArray.length > 0 && adjacentItemsNotInChain(chainArray)) || - [] - ).filter((element) => { - const hasCharacter = element.innerText == word[charIndex].toUpperCase(); - return hasCharacter; - }); - if (itemsWithCharacter.length === 0) { - // there are no new items, we should remove this list - wordChains[chainArrayIndex] = []; - } else if (itemsWithCharacter.length === 1) { - // there is only a single addition, we should just add to existing list - chainArray.push(itemsWithCharacter[0]); - } else { - itemsWithCharacter.forEach((newTailElement) => { - wordChains.push([...chainArray, newTailElement]); - }); - } - } - } - // filter bad sizes - wordChains = wordChains.filter((chains) => chains.length === word.length); - // actually change style of those elements; - for (chain of wordChains) { - for (element of chain) { - element.classList.add("on"); - } - } -}; - const dropLetters = () => { const allLetters = document.querySelectorAll(".letter-item"); allLetters.forEach((element) => { @@ -217,27 +60,6 @@ const dropLetters = () => { } }; -const addLetterTyped = (key) => { - const newLetter = document.createElement("div"); - newLetter.classList.add("letter-typed"); - newLetter.classList.add("added"); - newLetter.innerText = key; - newLetter.onclick = (event) => { - const wordArray = word.split(""); - const element = event.target; - const elementIndex = [...element.parentElement.children].findIndex( - (item) => item === element - ); - element.parentElement.removeChild(element); - wordArray.splice(elementIndex, 1); - word = wordArray.join(""); - unselectLetters(); - evaluateWordElements(); - }; - wordInputWrapperElement.appendChild(newLetter); - word += key; -}; - const handleKeyDown = ({ key }) => { const numberOfLetters = wordInputWrapperElement.children.length; if (timer === 0) { diff --git a/common.js b/common.js new file mode 100644 index 0000000..aae2c17 --- /dev/null +++ b/common.js @@ -0,0 +1,181 @@ +function random() { + var x = Math.sin(seed++) * 10000; + return x - Math.floor(x); +} + +const randomLetter = () => characters[Math.floor(random() * characters.length)]; + +const buildGrid = () => { + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + addLetterBubble(row, col); + } + } +}; + +const unselectLetters = () => { + const allLetters = document.querySelectorAll(".letter-item"); + allLetters.forEach((elements) => elements.classList.remove("on")); +}; + +const clearWord = () => { + [...wordInputWrapperElement.children].forEach((letterElement) => { + wordInputWrapperElement.removeChild(letterElement); + }); + word = ""; +}; + +const shuffleGrid = () => { + const allLetters = [...document.querySelectorAll(".letter-item")]; + + let currentIndex = allLetters.length; + let randomIndex; + + // While there remain elements to shuffle... + while (currentIndex !== 0) { + // Pick a remaining element... + randomIndex = Math.floor(random() * currentIndex); + currentIndex--; + + // And swap it with the current element. + [allLetters[currentIndex], allLetters[randomIndex]] = [ + allLetters[randomIndex], + allLetters[currentIndex], + ]; + } + + // figure out the size of the box so that we don't end + // up with islands of letters + const boxSize = Math.ceil(Math.sqrt(allLetters.length)); + allLetters.forEach((letter, index) => { + const row = Math.floor(index / boxSize); + const col = Math.floor(index % boxSize); + letter.style.left = row * 60; + letter.style.top = col * 60; + + letter.dataset.row = row; + letter.dataset.col = col; + }); +}; + +const addLetterBubble = (row, col) => { + const posX = row * 60; + const posY = col * 60; + const element = document.createElement("div"); + element.classList.add("letter-item"); + element.onclick = ({ target: { innerText } }) => { + handleKeyDown({ key: innerText.toLowerCase() }); + }; + element.dataset.row = row; + element.dataset.col = col; + + element.style.left = posX; + element.style.top = posY; + element.innerText = randomLetter(); + letterGridElement.appendChild(element); +}; + +const markAsBadWord = () => { + const allLetters = document.querySelectorAll(".letter-typed"); + allLetters.forEach((letterElement) => { + letterElement.classList.remove("added"); + letterElement.classList.add("rejected"); + }); + setTimeout(() => { + const allLetters = document.querySelectorAll(".letter-typed"); + allLetters.forEach((letterElement) => { + letterElement.classList.remove("rejected"); + }); + }, 150); +}; + +const adjacentItemsNotInChain = (chain) => { + const lastItem = chain[chain.length - 1]; + const { row, col } = lastItem.dataset; + const allLetters = document.querySelectorAll(".letter-item"); + let arrayReturn = []; + allLetters.forEach((element) => { + const { row: elementRow, col: elementCol } = element.dataset; + const elementIsAdjacent = + Math.abs(row - elementRow) <= 1 && Math.abs(col - elementCol) <= 1; + const elementIsInChain = chain.includes(element); + if (!elementIsInChain && elementIsAdjacent) { + arrayReturn.push(element); + } + }); + return arrayReturn; +}; + +// highlight letters that are being typed +const evaluateWordElements = () => { + if (!word) { + wordChains = []; + return; + } + const allLetters = document.querySelectorAll(".letter-item"); + if (word[0]) { + // get first letter + allLetters.forEach((element) => { + const isKey = element.innerText == word[0].toUpperCase(); + if (isKey) { + wordChains.push([element]); + } + }); + } + + for (charIndex in word) { + if (charIndex == 0) { + continue; // already done above + } + for (chainArrayIndex in wordChains) { + const chainArray = wordChains[chainArrayIndex]; + const itemsWithCharacter = ( + (chainArray.length > 0 && adjacentItemsNotInChain(chainArray)) || + [] + ).filter((element) => { + const hasCharacter = element.innerText == word[charIndex].toUpperCase(); + return hasCharacter; + }); + if (itemsWithCharacter.length === 0) { + // there are no new items, we should remove this list + wordChains[chainArrayIndex] = []; + } else if (itemsWithCharacter.length === 1) { + // there is only a single addition, we should just add to existing list + chainArray.push(itemsWithCharacter[0]); + } else { + itemsWithCharacter.forEach((newTailElement) => { + wordChains.push([...chainArray, newTailElement]); + }); + } + } + } + // filter bad sizes + wordChains = wordChains.filter((chains) => chains.length === word.length); + // actually change style of those elements; + for (chain of wordChains) { + for (element of chain) { + element.classList.add("on"); + } + } +}; + +const addLetterTyped = (key) => { + const newLetter = document.createElement("div"); + newLetter.classList.add("letter-typed"); + newLetter.classList.add("added"); + newLetter.innerText = key; + newLetter.onclick = (event) => { + const wordArray = word.split(""); + const element = event.target; + const elementIndex = [...element.parentElement.children].findIndex( + (item) => item === element + ); + element.parentElement.removeChild(element); + wordArray.splice(elementIndex, 1); + word = wordArray.join(""); + unselectLetters(); + evaluateWordElements(); + }; + wordInputWrapperElement.appendChild(newLetter); + word += key; +}; diff --git a/daily.js b/daily.js index 48afdb5..cbad7b9 100644 --- a/daily.js +++ b/daily.js @@ -22,164 +22,7 @@ let seed = Number( }${date.getDay() >= 10 ? date.getDay() : "0" + date.getDay()}` ); -function random() { - var x = Math.sin(seed++) * 10000; - return x - Math.floor(x); -} - -const randomLetter = () => characters[Math.floor(random() * characters.length)]; - -const addLetterBubble = (row, col) => { - const posX = row * 60; - const posY = col * 60; - const element = document.createElement("div"); - element.classList.add("letter-item"); - element.onclick = ({ target: { innerText } }) => { - handleKeyDown({ key: innerText.toLowerCase() }); - }; - element.dataset.row = row; - element.dataset.col = col; - - element.style.left = posX; - element.style.top = posY; - element.innerText = randomLetter(); - letterGridElement.appendChild(element); -}; - -const buildGrid = () => { - for (let row = 0; row < rows; row++) { - for (let col = 0; col < cols; col++) { - addLetterBubble(row, col); - } - } -}; - -const shuffleGrid = () => { - const allLetters = [...document.querySelectorAll(".letter-item")]; - - let currentIndex = allLetters.length; - let randomIndex; - - // While there remain elements to shuffle... - while (currentIndex !== 0) { - // Pick a remaining element... - randomIndex = Math.floor(random() * currentIndex); - currentIndex--; - - // And swap it with the current element. - [allLetters[currentIndex], allLetters[randomIndex]] = [ - allLetters[randomIndex], - allLetters[currentIndex], - ]; - } - - const boxSize = Math.ceil(Math.sqrt(allLetters.length)); - allLetters.forEach((letter, index) => { - const row = Math.floor(index / boxSize); - const col = Math.floor(index % boxSize); - letter.style.left = row * 60; - letter.style.top = col * 60; - - letter.dataset.row = row; - letter.dataset.col = col; - }); -}; - -const unselectLetters = () => { - const allLetters = document.querySelectorAll(".letter-item"); - allLetters.forEach((elements) => elements.classList.remove("on")); -}; - -const clearWord = () => { - [...wordInputWrapperElement.children].forEach((letterElement) => { - wordInputWrapperElement.removeChild(letterElement); - }); - word = ""; -}; - -const markAsBadWord = () => { - const allLetters = document.querySelectorAll(".letter-typed"); - allLetters.forEach((letterElement) => { - letterElement.classList.remove("added"); - letterElement.classList.add("rejected"); - }); - setTimeout(() => { - const allLetters = document.querySelectorAll(".letter-typed"); - allLetters.forEach((letterElement) => { - letterElement.classList.remove("rejected"); - }); - }, 150); -}; - -const adjacentItemsNotInChain = (chain) => { - const lastItem = chain[chain.length - 1]; - const { row, col } = lastItem.dataset; - const allLetters = document.querySelectorAll(".letter-item"); - let arrayReturn = []; - allLetters.forEach((element) => { - const { row: elementRow, col: elementCol } = element.dataset; - const elementIsAdjacent = - Math.abs(row - elementRow) <= 1 && Math.abs(col - elementCol) <= 1; - const elementIsInChain = chain.includes(element); - if (!elementIsInChain && elementIsAdjacent) { - arrayReturn.push(element); - } - }); - return arrayReturn; -}; - -const evaluateWordElements = () => { - if (!word) { - wordChains = []; - return; - } - const allLetters = document.querySelectorAll(".letter-item"); - if (word[0]) { - // get first letter - allLetters.forEach((element) => { - const isKey = element.innerText == word[0].toUpperCase(); - if (isKey) { - wordChains.push([element]); - } - }); - } - - for (charIndex in word) { - if (charIndex == 0) { - continue; // already done above - } - for (chainArrayIndex in wordChains) { - const chainArray = wordChains[chainArrayIndex]; - const itemsWithCharacter = ( - (chainArray.length > 0 && adjacentItemsNotInChain(chainArray)) || - [] - ).filter((element) => { - const hasCharacter = element.innerText == word[charIndex].toUpperCase(); - return hasCharacter; - }); - if (itemsWithCharacter.length === 0) { - // there are no new items, we should remove this list - wordChains[chainArrayIndex] = []; - } else if (itemsWithCharacter.length === 1) { - // there is only a single addition, we should just add to existing list - chainArray.push(itemsWithCharacter[0]); - } else { - itemsWithCharacter.forEach((newTailElement) => { - wordChains.push([...chainArray, newTailElement]); - }); - } - } - } - // filter bad sizes - wordChains = wordChains.filter((chains) => chains.length === word.length); - // actually change style of those elements; - for (chain of wordChains) { - for (element of chain) { - element.classList.add("on"); - } - } -}; - +// different from blitz or endless because we don't re-add letters const dropLetters = () => { const allLetters = document.querySelectorAll(".letter-item"); allLetters.forEach((element) => { @@ -197,27 +40,6 @@ const dropLetters = () => { }); }; -const addLetterTyped = (key) => { - const newLetter = document.createElement("div"); - newLetter.classList.add("letter-typed"); - newLetter.classList.add("added"); - newLetter.innerText = key; - newLetter.onclick = (event) => { - const wordArray = word.split(""); - const element = event.target; - const elementIndex = [...element.parentElement.children].findIndex( - (item) => item === element - ); - element.parentElement.removeChild(element); - wordArray.splice(elementIndex, 1); - word = wordArray.join(""); - unselectLetters(); - evaluateWordElements(); - }; - wordInputWrapperElement.appendChild(newLetter); - word += key; -}; - const handleKeyDown = ({ key }) => { const numberOfLetters = wordInputWrapperElement.children.length; if (gameEnd) { diff --git a/endless.html b/endless.html index 8dee552..2605586 100644 --- a/endless.html +++ b/endless.html @@ -10,6 +10,7 @@ content="https://user-images.githubusercontent.com/1131494/156868819-573c8853-ad4b-4c30-8594-cb80e9eb1a91.jpg" /> + diff --git a/endless.js b/endless.js index 8894ff0..981e256 100644 --- a/endless.js +++ b/endless.js @@ -20,163 +20,6 @@ let seed = const logger = getLogger({ mode: "Endless", seed }); -function random() { - var x = Math.sin(seed++) * 10000; - return x - Math.floor(x); -} - -const randomLetter = () => characters[Math.floor(random() * characters.length)]; - -const addLetterBubble = (row, col) => { - const posX = row * 60; - const posY = col * 60; - const element = document.createElement("div"); - element.classList.add("letter-item"); - element.onclick = ({ target: { innerText } }) => { - handleKeyDown({ key: innerText.toLowerCase() }); - }; - element.dataset.row = row; - element.dataset.col = col; - - element.style.left = posX; - element.style.top = posY; - element.innerText = randomLetter(); - letterGridElement.appendChild(element); -}; - -const buildGrid = () => { - for (let row = 0; row < rows; row++) { - for (let col = 0; col < cols; col++) { - addLetterBubble(row, col); - } - } -}; - -const shuffleGrid = () => { - const allLetters = [...document.querySelectorAll(".letter-item")]; - - let currentIndex = allLetters.length; - let randomIndex; - - // While there remain elements to shuffle... - while (currentIndex !== 0) { - // Pick a remaining element... - randomIndex = Math.floor(random() * currentIndex); - currentIndex--; - - // And swap it with the current element. - [allLetters[currentIndex], allLetters[randomIndex]] = [ - allLetters[randomIndex], - allLetters[currentIndex], - ]; - } - - allLetters.forEach((letter, index) => { - const row = Math.floor(index / 5); - const col = Math.floor(index % 5); - letter.style.left = row * 60; - letter.style.top = col * 60; - - letter.dataset.row = row; - letter.dataset.col = col; - }); -}; - -const unselectLetters = () => { - const allLetters = document.querySelectorAll(".letter-item"); - allLetters.forEach((elements) => elements.classList.remove("on")); -}; - -const clearWord = () => { - [...wordInputWrapperElement.children].forEach((letterElement) => { - wordInputWrapperElement.removeChild(letterElement); - }); - word = ""; -}; - -const markAsBadWord = () => { - const allLetters = document.querySelectorAll(".letter-typed"); - allLetters.forEach((letterElement) => { - letterElement.classList.remove("added"); - letterElement.classList.add("rejected"); - }); - setTimeout(() => { - const allLetters = document.querySelectorAll(".letter-typed"); - allLetters.forEach((letterElement) => { - letterElement.classList.remove("rejected"); - }); - }, 150); -}; - -const adjacentItemsNotInChain = (chain) => { - const lastItem = chain[chain.length - 1]; - const { row, col } = lastItem.dataset; - const allLetters = document.querySelectorAll(".letter-item"); - let arrayReturn = []; - allLetters.forEach((element) => { - const { row: elementRow, col: elementCol } = element.dataset; - const elementIsAdjacent = - Math.abs(row - elementRow) <= 1 && Math.abs(col - elementCol) <= 1; - const elementIsInChain = chain.includes(element); - if (!elementIsInChain && elementIsAdjacent) { - arrayReturn.push(element); - } - }); - return arrayReturn; -}; - -const evaluateWordElements = () => { - if (!word) { - wordChains = []; - return; - } - const allLetters = document.querySelectorAll(".letter-item"); - if (word[0]) { - // get first letter - allLetters.forEach((element) => { - const isKey = element.innerText == word[0].toUpperCase(); - if (isKey) { - wordChains.push([element]); - } - }); - } - - for (charIndex in word) { - if (charIndex == 0) { - continue; // already done above - } - for (chainArrayIndex in wordChains) { - const chainArray = wordChains[chainArrayIndex]; - const itemsWithCharacter = ( - (chainArray.length > 0 && adjacentItemsNotInChain(chainArray)) || - [] - ).filter((element) => { - const hasCharacter = element.innerText == word[charIndex].toUpperCase(); - return hasCharacter; - }); - if (itemsWithCharacter.length === 0) { - // there are no new items, we should remove this list - wordChains[chainArrayIndex] = []; - } else if (itemsWithCharacter.length === 1) { - // there is only a single addition, we should just add to existing list - chainArray.push(itemsWithCharacter[0]); - } else { - itemsWithCharacter.forEach((newTailElement) => { - wordChains.push([...chainArray, newTailElement]); - }); - } - } - } - // filter bad sizes - wordChains = wordChains.filter((chains) => chains.length === word.length); - // actually change style of those elements; - for (chain of wordChains) { - for (element of chain) { - element.classList.add("on"); - } - } -}; - const dropLetters = () => { const allLetters = document.querySelectorAll(".letter-item"); allLetters.forEach((element) => { @@ -217,27 +60,6 @@ const dropLetters = () => { } }; -const addLetterTyped = (key) => { - const newLetter = document.createElement("div"); - newLetter.classList.add("letter-typed"); - newLetter.classList.add("added"); - newLetter.innerText = key; - newLetter.onclick = (event) => { - const wordArray = word.split(""); - const element = event.target; - const elementIndex = [...element.parentElement.children].findIndex( - (item) => item === element - ); - element.parentElement.removeChild(element); - wordArray.splice(elementIndex, 1); - word = wordArray.join(""); - unselectLetters(); - evaluateWordElements(); - }; - wordInputWrapperElement.appendChild(newLetter); - word += key; -}; - const handleKeyDown = ({ key }) => { const numberOfLetters = wordInputWrapperElement.children.length; if ((key === "Backspace" || key === "del") && numberOfLetters > 0) { diff --git a/index.html b/index.html index f4eeef2..f8e472b 100644 --- a/index.html +++ b/index.html @@ -10,6 +10,7 @@ content="https://user-images.githubusercontent.com/1131494/156868819-573c8853-ad4b-4c30-8594-cb80e9eb1a91.jpg" /> +