Files
Find-the-word_Eduspire/script.js
Nishita dc9985bbc8 Upload files to "/"
Word Search Stories

At Eduspire, we believe learning English should be fun, interactive, and creative. That’s why we developed Word Search Stories – a playful and educational game designed for students from grades 3 to 6. This game helps children enhance their vocabulary, spelling, reading comprehension, and pattern recognition while enjoying engaging, themed stories.

In Word Search Stories, students first select their grade level and a theme, such as Farm Life, Animals, or Space Adventure. The game then presents a colorful and interactive letter grid where children must find hidden words related to the selected theme. Words can appear horizontally, vertically, or diagonally, making the game challenging yet fun. A real-time progress tracker shows how many words have been found, while the Hint button allows students to briefly highlight one of the remaining words, encouraging learning without frustration.

Once all words are found, a short story related to the theme is unlocked. This story is presented in a playful pop-up animation, helping students connect the vocabulary they discovered with real language in context. The game is designed to be vibrant, visually appealing, and intuitive, featuring colorful cells, easy drag-and-select controls, and responsive layout that works on both desktop and touch devices.

Tech Stack:

HTML – structures the game, grid, buttons, and story popups.

CSS – adds vibrant colors, animations, and kid-friendly design.

JavaScript – handles word placement, grid logic, selection tracking, hints, and story reveal.

Optional Enhancements: Three.js for 3D effects, Web Audio API for future sound and voice-over support.

The game is fully iframe compatible, meaning it can easily be embedded into any website or digital learning platform. Its modular design separates structure (index.html), styles (style.css), and logic (script.js) for maintainability and easy collaboration.
2025-09-09 17:57:03 +00:00

222 lines
6.7 KiB
JavaScript

/* ======================
SCRIPT.JS
- Working Word Search Game with HINT button
====================== */
/* ---------- Data: words & stories ---------- */
const data = {
farm: {
3: {
words: ["COW", "HEN", "BARN", "MILK", "EGGS"],
storyTitle: "Maya and the Friendly Cow",
story: "Maya went to the barn. She saw a cow and a hen. The hen gave eggs. Maya drank warm milk and smiled."
},
4: {
words: ["FARMER", "TRACTOR", "FIELD", "CORN", "SHEEP"],
storyTitle: "The Busy Farmer",
story: "The farmer drove the tractor to the field. The sheep grazed while the farmer planted corn. Everyone helped in the barn."
}
}
};
/* ---------- Global Variables ---------- */
let gridSize = 14;
let grid = [];
let placements = [];
let wordsToFind = [];
let foundWords = new Set();
let selecting = false;
let selectedCells = [];
const gridEl = document.getElementById('grid');
const wordListEl = document.getElementById('wordList');
const progressEl = document.getElementById('progress');
const overlay = document.getElementById('overlay');
const storyText = document.getElementById('storyText');
const storyTitle = document.getElementById('storyTitle');
/* ---------- Helper: random letter ---------- */
function randLetter() {
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return letters[Math.floor(Math.random() * letters.length)];
}
/* ---------- Grid Setup ---------- */
function makeEmptyGrid(size) {
grid = Array(size).fill(null).map(() => Array(size).fill(""));
}
function placeWord(word, size) {
const dirs = [
[1, 0], [0, 1], [1, 1], [-1, 1]
];
for (let tries = 0; tries < 200; tries++) {
const dir = dirs[Math.floor(Math.random() * dirs.length)];
const row = Math.floor(Math.random() * size);
const col = Math.floor(Math.random() * size);
let r = row, c = col, ok = true;
for (let ch of word) {
if (r < 0 || r >= size || c < 0 || c >= size || (grid[r][c] && grid[r][c] !== ch)) {
ok = false; break;
}
r += dir[0]; c += dir[1];
}
if (!ok) continue;
r = row; c = col;
for (let ch of word) {
grid[r][c] = ch;
r += dir[0]; c += dir[1];
}
placements.push({ word, row, col, dir });
return true;
}
return false;
}
function fillRandom(size) {
for (let r = 0; r < size; r++) {
for (let c = 0; c < size; c++) {
if (!grid[r][c]) grid[r][c] = randLetter();
}
}
}
function renderGrid(size) {
gridEl.style.gridTemplateColumns = `repeat(${size}, 1fr)`;
gridEl.innerHTML = "";
for (let r = 0; r < size; r++) {
for (let c = 0; c < size; c++) {
const cell = document.createElement("div");
cell.className = "cell";
cell.textContent = grid[r][c];
cell.dataset.row = r;
cell.dataset.col = c;
gridEl.appendChild(cell);
}
}
}
/* ---------- Word List UI ---------- */
function updateWordListUI() {
wordListEl.innerHTML = "";
wordsToFind.forEach(w => {
const el = document.createElement("div");
el.className = "worditem";
el.textContent = w;
if (foundWords.has(w)) el.classList.add("done");
wordListEl.appendChild(el);
});
progressEl.textContent = `${foundWords.size} / ${wordsToFind.length}`;
}
/* ---------- Selection Handling ---------- */
function attachSelectionHandlers() {
gridEl.addEventListener("mousedown", e => {
if (!e.target.classList.contains("cell")) return;
selecting = true;
selectedCells = [e.target];
e.target.classList.add("sel");
});
gridEl.addEventListener("mouseover", e => {
if (!selecting || !e.target.classList.contains("cell")) return;
if (!selectedCells.includes(e.target)) {
selectedCells.push(e.target);
e.target.classList.add("sel");
}
});
document.addEventListener("mouseup", () => {
if (!selecting) return;
finalizeSelection();
selecting = false;
});
}
function finalizeSelection() {
const letters = selectedCells.map(c => c.textContent).join("");
const reverse = [...letters].reverse().join("");
const match = wordsToFind.find(w => w === letters || w === reverse);
if (match && !foundWords.has(match)) {
foundWords.add(match);
selectedCells.forEach(c => c.classList.add("found"));
updateWordListUI();
if (foundWords.size === wordsToFind.length) {
revealStory();
}
}
selectedCells.forEach(c => c.classList.remove("sel"));
selectedCells = [];
}
/* ---------- Story Popup ---------- */
function revealStory() {
overlay.classList.add("show");
storyTitle.textContent = currentStory.storyTitle;
storyText.textContent = currentStory.story;
}
function closeStory() {
overlay.classList.remove("show");
}
/* ---------- Hint Feature ---------- */
function giveHint() {
// Get words that are not yet found
const remaining = wordsToFind.filter(w => !foundWords.has(w));
if (remaining.length === 0) return;
const hintWord = remaining[Math.floor(Math.random() * remaining.length)];
const placement = placements.find(p => p.word === hintWord);
if (!placement) return;
// Highlight cells temporarily
let r = placement.row, c = placement.col;
const cells = [];
for (let ch of placement.word) {
const cell = [...gridEl.children].find(
el => parseInt(el.dataset.row) === r && parseInt(el.dataset.col) === c
);
if (cell) {
cell.classList.add("sel");
cells.push(cell);
}
r += placement.dir[0];
c += placement.dir[1];
}
// Remove highlight after 1 second
setTimeout(() => {
cells.forEach(cell => cell.classList.remove("sel"));
}, 1000);
}
/* ---------- Game Init ---------- */
let currentStory;
function generate() {
gridSize = parseInt(document.getElementById("sizeSelect").value) || 14;
const grade = parseInt(document.getElementById("gradeSelect").value);
const theme = document.getElementById("themeSelect").value;
const storyObj = data[theme]?.[grade];
if (!storyObj) {
alert("No story data for this grade & theme!");
return;
}
currentStory = storyObj;
wordsToFind = storyObj.words;
foundWords.clear();
placements = [];
makeEmptyGrid(gridSize);
wordsToFind.forEach(w => placeWord(w, gridSize));
fillRandom(gridSize);
renderGrid(gridSize);
updateWordListUI();
}
/* ---------- Button Events ---------- */
document.getElementById('newBtn').addEventListener('click', generate);
document.getElementById('hintBtn').addEventListener('click', giveHint);
document.getElementById('closeStory').addEventListener('click', closeStory);
document.getElementById('againBtn').addEventListener('click', () => { closeStory(); generate(); });
/* ---------- Init ---------- */
attachSelectionHandlers();
generate();