How I Built a Spinning Schulte Table Game
Every developer has that moment: you're scrolling through X at 11 PM and see someone post a tiny game they made over the weekend. "I could do that," you think. But then Sunday comes and goes, and you never start.
I decided to stop just thinking about it. Over one weekend, I built Spinning Schulte Table — a brain-training focus game that runs entirely in the browser. No React, no Three.js, no build step. Just HTML, CSS, and vanilla JavaScript.
Here's how I did it.
What is a Schulte Table?
If you've never heard of it, the Schulte table is a classic attention-training exercise. You get a grid of numbers (say, 1–100) scattered randomly, and your job is to tap them in order: 1, 2, 3, … all the way to 100. A timer tracks how long it takes.
It's used in psychology and even pilot training to improve peripheral vision and sustained focus.
My twist: the whole table slowly rotates while you tap. Now your eyes have to track moving targets, which adds an extra layer of challenge.
The core idea
The game has three parts:
Generate a grid — scatter numbers randomly on the screen
Rotate the container — apply a CSS animation that slowly spins the whole board
Track taps — verify the player taps numbers in the correct order
Let me break each down.
Generating the number grid
The simplest approach: create an array of numbers 1 through N, shuffle it, then render each one as a positioned element.
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
function generateNumbers(size) {
const total = size * size;
const numbers = Array.from({ length: total }, (_, i) => i + 1);
return shuffle(numbers);
}
For positioning, I used absolute positioning inside a circular container. Each number gets a random angle and radius, then I calculated its x/y coordinates:
function positionNumber(index, total, centerX, centerY) {
const angle = (index / total) * Math.PI * 2;
const radius = 80 + Math.random() * 120;
const x = centerX + Math.cos(angle) * radius;
const y = centerY + Math.sin(angle) * radius;
return { x, y };
}
This creates a spiral-like scatter instead of a rigid grid, which makes it visually interesting and actually harder (numbers aren't in predictable positions).
The rotation trick
This was easier than I expected. I just wrapped all the numbers in one container div and applied a CSS animation:
.game-board {
position: relative;
width: 500px;
height: 500px;
animation: rotate 60s linear infinite;
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
That's it. One CSS keyframe animation and the whole board spins slowly. The player has to track each number as it moves around the circle.
Tracking taps
Each number element listens for clicks. When tapped, I check if it's the next expected number:
let nextNumber = 1;
let mistakes = 0;
function handleNumberTap(value, element) {
if (value === nextNumber) {
element.classList.add('correct');
nextNumber++;
updateNextDisplay();
if (nextNumber > totalNumbers) { finishGame(); } } else {
mistakes++;
element.classList.add('mistake');
setTimeout(() => element.classList.remove('mistake'), 500);
}
}
A timer starts on the first tap and stops when you reach the last number.
What I learned
Vanilla JS is enough. You don't need a framework for a game this simple. The hardest part was positioning, not the logic.
CSS animations are powerful. One keyframe rule gave me the entire "spinning" effect.
Keep scope tiny. I could have added sound effects, accounts, achievements, and multiplayer. I didn't. I shipped one mechanic, polished it, and published.
Try it
The game is live, free to play directly in your browser:
👉 Spinning Schulte Table
No download or sign-up required. Open it, tap numbers in order, and see how fast you can finish while the board spins. Let me know your best time in the comments!
Note: this demo is hosted locally on my PC, so please be patient if there is a connection hiccup.What's next
I'm planning to add:
Difficulty levels (3×3 up to 10×10)
A leaderboard
Daily challenges
If you've built a tiny browser game with vanilla JS, I'd love to hear your approach. Feel free to drop a link in the comments!
原文:https://www.a8q9.cn/en/article/how-i-built-a-spinning-schulte-table-game-3e05c6.html