commit 2903155df6cdf17f1ce0e1b52d508fd851779a67 Author: Alvie Rahman Date: Thu Jan 27 18:36:45 2022 +0000 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8b0792d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +wordlist.js diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..d447f22 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "english-words"] + path = english-words + url = https://github.com/dwyl/english-words diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d0f5fbe --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +wordlist.js: english-words + scripts/gen_wordlist.py english-words/words.txt 5 > wordlist.js + +english-words: .SUBMODULES + +clean: + rm -rf wordlist.js + +.SUBMODULES: + git submodule init + git submodule update + diff --git a/english-words b/english-words new file mode 160000 index 0000000..22d7c41 --- /dev/null +++ b/english-words @@ -0,0 +1 @@ +Subproject commit 22d7c41119076750a96fca2acd664ed994cc0a75 diff --git a/game.js b/game.js new file mode 100644 index 0000000..d2f1c65 --- /dev/null +++ b/game.js @@ -0,0 +1,160 @@ +// global constants +const gridWidth = 5 +const gridHeight = 6 +const word = wordlist[Math.floor(Math.random()*wordlist.length)]; + +// global state variables +var gameCompleted = null + +// HTML items +const gameContainer = document.getElementById("game_container") +const gridItems = [] + +// helper functions +const gridItemId = (row, column) => "grid_item_" + row + "_" + column +const getGridRow = (row) => gridItems[row] +const getGridItem = (row, column) => gridItems[row].items[column] +const isLetter = string => /^[a-zA-Z]$/.test(string) + + +function setGridLetter(row, column, letter) { + console.log([row, column]) + console.log(letter) + + getGridItem(row, column).letter = letter + getGridItem(row, column).HTMLItem.getElementsByClassName("grid_item_p")[0].innerHTML = letter !== null ? letter : "" +} + + +function checkGridRow() { + var [row, _ ] = findCurrentLetterPosition() + var rowWord = '' + getGridRow(row).items.forEach(item => rowWord += item.letter) + + console.log(rowWord) + if (!wordlist.includes(rowWord)) return + + var correct_letters = 0 + var dedupword = word + + for (var column = 0; column < gridWidth; column++) { + gridItem = getGridItem(row, column) + // letters are removed from dedupword as letters are matched + if (gridItem.letter === null) return + + if (gridItem.letter === word[column]) { + gridItem.HTMLItem.classList.add('grid_correct') + correct_letters += 1 + } else if (dedupword.includes(gridItem.letter)) { + gridItem.HTMLItem.classList.add('grid_present') + } else { + gridItem.HTMLItem.classList.add('grid_wrong') + } + + dedupword = dedupword.replace(gridItem.letter, '') + console.log(gridItem.letter) + console.log(dedupword) + + if (correct_letters == gridWidth) gameCompleted = true + } + + getGridRow(row).complete = true + if (row === gridHeight-1) gameCompleted = true +} + + +function init(){ + // clear game div + gameContainer.innerHTML = "" + // build letter grid and populate gridItems + const letterGrid = document.createElement("div") + letterGrid.setAttribute("id", "letter_grid") + + for (var row = 0; row < gridHeight; row++) { + var gridRow = document.createElement('div') + gridRow.classList.add('grid_row') + gridItems.push({ + items: [], + complete: false, + }) + for (var column = 0; column < gridWidth; column++) { + var gridItem = document.createElement('div') + gridItem.classList.add('grid_item') + gridItem.setAttribute('id', gridItemId(row, column)) + + var gridItemP = document.createElement('p') + gridItemP.classList.add('grid_item_p') + gridItem.appendChild(gridItemP) + gridRow.appendChild(gridItem) + + gridItems[row].items.push({ + HTMLItem: gridItem, + letter: null, + correct: null + }) + } + letterGrid.appendChild(gridRow) + } + + gameContainer.appendChild(letterGrid) + gameCompleted = false +} + + +function findNextLetterPosition() { + for (var row = 0; row < gridHeight; row++) { + for (var column = 0; column < gridWidth; column++) { + if (getGridItem(row, column).letter === null) return [row, column] + } + } +} + + +function findCurrentLetterPosition() { + var lastRow = 0 + var lastColumn = 0 + + for (var row = 0; row < gridHeight; row++) { + for (var column = 0; column < gridWidth; column++) { + if (getGridItem(row, column).letter === null) return [lastRow, lastColumn] + lastRow = row + lastColumn = column + } + } + return [lastRow, lastColumn] +} + + +function setNextLetter(key) { + if (gameCompleted) return + + var [currentRow, currentColumn] = findCurrentLetterPosition() + if (key.code === "Backspace") { + if (currentColumn === -1 || getGridRow(currentRow).complete) return + + setGridLetter(currentRow, currentColumn, null) + return + } + + if (key.code === "Enter") { + checkGridRow() + } + + if (isLetter(key.key)) { + if (key.altKey || key.ctrlKey || key.metaKey) return + var [nextRow, nextColumn] = findNextLetterPosition() + if (currentRow !== nextRow && !getGridRow(currentRow).complete) return + setGridLetter(nextRow, nextColumn, key.key) + return + } +} + + +// create event listeners +document.addEventListener('keyup', (e) => { + console.log(e) + setNextLetter(e) +}) + + +init() \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..5e4e342 --- /dev/null +++ b/index.html @@ -0,0 +1,25 @@ + + + + + +word guessing game: infinite + + +

word guessing game

+ +
+ you need javascript enabled to play this game +
+ +
+
+ +

+ built with ❤ and adequate amounts of care by + alv +

+ + + + diff --git a/scripts/gen_wordlist.py b/scripts/gen_wordlist.py new file mode 100755 index 0000000..7f798fc --- /dev/null +++ b/scripts/gen_wordlist.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +import sys +import json + + +def get_args(): + """ Get command line arguments """ + + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('wordlist') + parser.add_argument('word_length', type=int) + return parser.parse_args() + + +def main(args): + """ Entry point for script """ + with open(args.wordlist) as fp: + words = [ word.lower() for word in fp.read().split('\n') if len(word) == args.word_length and word.isalpha() ] + + print(f"wordlist = {json.dumps(words)}") + + return 0 + + +if __name__ == '__main__': + try: + sys.exit(main(get_args())) + except KeyboardInterrupt: + sys.exit(0) diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..3ecc916 --- /dev/null +++ b/styles.css @@ -0,0 +1,47 @@ +@import url("https://alv.cx/styles.css"); + +:root { + --default-bg: #fefefe; + --dark-bg: #b8b8b8; + --selected-bg: #383838; + --default-fg: #454545; + --red: #ab4642; + --orange: #dc9656; + --yellow: #f7ca88; + --green: #a1b56c; + --teal: #86c1b9; + --blue: #7cafc2; + --purple: #ba8baf; + --brown: #a16946; +} + +#letter_grid { + width: fit-content; + margin: 0 auto; +} + +.grid_row { + display: flex; + flex-direction: row; +} + +.grid_item { + width: 3em; + height: 3em; + display: flex; + justify-content: center; + align-items: center; + border: 0.2em solid var(--dark-bg); + margin: 1em; + text-transform: uppercase; + font-weight: 800; +} + +.grid_item * { + text-align: center; + margin: 0; +} + +.grid_correct { background-color: var(--green)} +.grid_present { background-color: var(--yellow)} +.grid_wrong { background-color: var(--brown)} \ No newline at end of file