Public
Edited
Jan 11
Importers
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
drawRecord = (sideLength, x) => {
return htl.html.fragment `<tr>
<td style="color:${x.points ? correctColor : incorrectColor}">${x.guess}</td>
<td style="color:${x.points ? correctColor : incorrectColor}">${x.currentWord}</td>
<td>${x.currentWord.length}</td>
</tr>
`
}
Insert cell
viewof correctColor = Inputs.color({value: "#16a716"})
Insert cell
viewof incorrectColor = Inputs.color({value: "#BB0000"})
Insert cell
focus = {
//feels like there's a better way to do this
guess;
document.getElementById('guess').focus()
}
Insert cell
The `drawBoard` function was heavily inspired by one of the Plot plots in the [Visualizing The New York Times’s Mini Crossword](https://observablehq.com/@observablehq/nyt-minis). This the first "data viz" I've made with Plot (although it's mostly copy-pasted code). Cool stuff.
Insert cell
drawBoard([
{ x: 0, y: 0, letter: "d" },
{ x: 0, y: 1, letter: "e" },
{ x: 0, y: 2, letter: "d" },
{ x: 0, y: 3, letter: "_" },
{ x: 1, y: 0, letter: "e" },
{ x: 1, y: 1, letter: "_" },
{ x: 1, y: 2, letter: "t" },
{ x: 1, y: 3, letter: "_" },
{ x: 2, y: 0, letter: "f" },
{ x: 2, y: 1, letter: "_" },
{ x: 2, y: 2, letter: "l" },
{ x: 2, y: 3, letter: "a" },
{ x: 3, y: 0, letter: "_" },
{ x: 3, y: 1, letter: "a" },
{ x: 3, y: 2, letter: "_" },
{ x: 3, y: 3, letter: "c" }
], 400)
Insert cell
drawBoard = (board, width) => {
return Plot.plot({
width: width,
height: width,
marks: [
Plot.cell(board, {
// cells
x: "x",
y: "y",
stroke: "black",
strokeWidth: 3,
}),
Plot.cell(board, {
// blanks
x: "x",
y: "y",
filter: (d) => d.letter === "_",
stroke: "black",
fill: "black"
}),
Plot.text(board, {
x: "x",
y: "y",
text: "letter",
fill: "black",
fontSize: width / 10
})
],
x: { type: "band", axis: false, padding: 0 },
y: { type: "band", axis: false, padding: 0 },
})
}
Insert cell
## Game Logic:
Insert cell
emptyBoard = () => {
const board = []
const rows = [...Array(4).keys()]
const cols = [...Array(4).keys()]
for (const i of rows) {
for (const j of cols) {
board.push({x: i, y: j})
}
}
return board
}
Insert cell
boardIndex = (x,y) => 4 * x + y
Insert cell
getNeighbors = (x, y, board) => {
let boardMax = Math.sqrt(board.length) - 1
const neighbors = [
[x - 1, y - 1], [x - 1, y], [x - 1, y + 1],
[x , y - 1], , [x, y + 1],
[x + 1, y - 1], [x + 1, y], [x + 1, y + 1]
]
return neighbors.filter(([x,y]) => !(x < 0 || x > boardMax || y < 0 || y > boardMax))
}
Insert cell
getOpenNeighbors = (x, y, board) => {
const neighbors = getNeighbors(x,y, board)
return neighbors.map(([x, y]) => board[boardIndex(x,y)])
.filter(square => !("letter" in square))
}
Insert cell
recursiveStep = {
const step = (string, board, lastX, lastY) => {

let neighbors = getOpenNeighbors(lastX, lastY, board)
if (neighbors.length === 0) return board
// pick a random neighor
let i = Math.floor(Math.random() * neighbors.length)
const next = neighbors[i]
next.letter = string[0]

if (string.length > 1) {
return step(string.slice(1), board, next.x, next.y)
}
return board
}
return step
}
Insert cell
fillBoard = (string) => {
let board = emptyBoard()
// place blanks:
const nBlanks = board.length - string.length
const findRandomOpen = board => {
let i = Math.floor(Math.random() * board.length)
if (!("letter" in board[i])) {
return board[i]
} else {
return findRandomOpen(board)
}
}
for (let i = 0; i < nBlanks; i++) {
let square = findRandomOpen(board)
square.letter = "_"
}
// random start
let square = findRandomOpen(board)
square.letter = string[0]
return recursiveStep(string.slice(1), board, square.x, square.y)
}
Insert cell
retryFill = (word) => {
const isFull = board => board.filter(square => "letter" in square).length === 16
let x = fillBoard(word)
while (!isFull(x)) {
x = fillBoard(word)
}
return x
}
Insert cell
pickWord = (min, max) => {
const validWords = words.filter(x => x.length <= max && x.length >= min)
const i = Math.floor(Math.random() * validWords.length)
const word = validWords[i].toUpperCase()
return word
}
Insert cell
handleEnter = (guess) => {
const isGoodGuess = guess.toUpperCase() === currentWord
const points = isGoodGuess ? 1 : 0

let scoreAfter = score + points
mutable score = scoreAfter
const ts = new Date()
log({guess: guess.toUpperCase(), currentWord, isGoodGuess, currentBoard, points, score})
mutable currentWord = pickWord(wordLengthBounds[0], wordLengthBounds[1])
}
Insert cell
Insert cell
mutable currentWord = pickWord(wordLengthBounds[0], wordLengthBounds[1])
Insert cell
currentBoard = retryFill(currentWord)
Insert cell
mutable score = {
return 0;
}
Insert cell
log = (data) => {
mutable history = [data, ...history]
}
Insert cell
mutable history = []
Insert cell
Insert cell
import {words} from '@a-lexwein/find-a-big-word'
Insert cell
import {rangeSlider} from '@mootari/range-slider@1312'
Insert cell
using the following three vals, I want a webpage that displays the svg results of drawBoard(retryFill(getRandomWord), 800)

import { retryFill } from "https://esm.town/v/alexwein/gridRetryFill";
import { getRandomWord } from "https://esm.town/v/alexwein/getRandomWord";
import { drawBoard } from "https://esm.town/v/alexwein/drawBoard";
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more