initial commit
This commit is contained in:
commit
2903155df6
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
wordlist.js
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "english-words"]
|
||||
path = english-words
|
||||
url = https://github.com/dwyl/english-words
|
12
Makefile
Normal file
12
Makefile
Normal file
@ -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
|
||||
|
1
english-words
Submodule
1
english-words
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 22d7c41119076750a96fca2acd664ed994cc0a75
|
160
game.js
Normal file
160
game.js
Normal file
@ -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()
|
25
index.html
Normal file
25
index.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!doctype html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>word guessing game: infinite</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>word guessing game</h1>
|
||||
|
||||
<div id="game_container">
|
||||
you need javascript enabled to play this game
|
||||
<div id="letter_grid">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
built with ❤ and adequate amounts of care by
|
||||
<a href="https://alv.cx">alv</a>
|
||||
</p>
|
||||
|
||||
<script type="application/javascript" src="wordlist.js"></script>
|
||||
<script type="application/javascript" src="game.js"></script>
|
||||
</body>
|
31
scripts/gen_wordlist.py
Executable file
31
scripts/gen_wordlist.py
Executable file
@ -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)
|
47
styles.css
Normal file
47
styles.css
Normal file
@ -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)}
|
Loading…
Reference in New Issue
Block a user