The provided code is a JavaScript implementation of a word search game. Let’s break it down and explain each part in detail:
- Event Listener:
document.addEventListener('DOMContentLoaded', init);
This code attaches an event listener to theDOMContentLoaded
event, which fires when the initial HTML document has been completely loaded and parsed. The event listener calls theinit
function when the event is triggered. - Object Declarations:
const eles = {}; const myWords = ['cat', 'dog', 'mouse', 'bird', 'horse', 'donkey', 'frog', 'rabbit', 'snake']; const game = { r: 5, c: 5, w: 100, x: '', y: '', arr: [], placedWords: [], boardArray: [] };
eles
is an empty object that will store references to various DOM elements.myWords
is an array of words that will be placed in the word search grid.game
is an object that stores game-related data, such as the number of rows (r
) and columns (c
) in the grid, the width (w
) of each cell, and various arrays (arr
,placedWords
,boardArray
) for storing game state.
- Initialization Function:
function init() { // DOM element references eles.gameArea = document.querySelector('.gameArea'); eles.gridContainer = document.createElement('div'); eles.message = document.createElement('div'); eles.myList = document.createElement('div'); eles.btn = document.createElement('button'); eles.gridSize = document.createElement('input'); // Styling and classes eles.gridContainer.style.margin = 'auto'; eles.gridContainer.classList.add('gridContainer'); eles.myList.classList.add('myList'); // Appending elements to the game area eles.gameArea.append(eles.message); eles.gameArea.append(eles.gridSize); eles.gameArea.append(eles.btn); eles.gameArea.append(eles.gridContainer); eles.gameArea.append(eles.myList); // Setting attributes and content eles.gridSize.setAttribute('type', 'number'); eles.gridSize.setAttribute('max', '20'); eles.gridSize.setAttribute('min', '2'); eles.btn.textContent = 'Click to Start'; eles.gridSize.value = 5; // Event listener for starting the game eles.btn.addEventListener('click', startGame); log('Click Start to Start the Game. Select the number of cells for the game grid.'); }
Theinit
function is responsible for setting up the initial state of the game. It retrieves references to DOM elements, sets their attributes and content, and attaches event listeners where necessary. - Game Start Function:
function startGame() { eles.gridSize.style.display = 'none'; eles.btn.style.display = 'none'; // Updating game dimensions and grid container width game.r = Number(eles.gridSize.value); game.c = Number(eles.gridSize.value); eles.gridContainer.style.width = (game.c * game.w + 50) + 'px'; // Resetting game-related arrays and variables game.x = ''; game.y = ''; game.boardArray.length = 0; game.arr.length = 0; game.arr.length = game.r * game.c; game.placedWords.length = 0; // Filling the game array with placeholder values for (let i = 0; i < game.arr.length; i++) { game.arr[i] = '-'; } // Generating CSS grid properties based on game dimensions for (let xx = 0; xx < game.r; xx++) { game.x += ' auto ' } for (let yy = 0; yy < game.r; yy++) { game.y += ' auto ' } eles.gridContainer.style.gridTemplateColumns = game.x; eles.gridContainer.style.gridTemplateRows = game.y; // Placing words in the game grid myWords.forEach((val, index) => { let temp = placeWord(val); if (temp) { game.placedWords.push({ word: val, pos: temp }); } }); // Adding random letters to empty cells in the grid addLetters(); // Building the game board buildBoard(); // Building the list of words eles.myList.innerHTML = ''; game.placedWords.forEach((w) => { w.ele = document.createElement('div'); w.ele.textContent = w.word; w.ele.arr = w.pos; eles.myList.append(w.ele); }); console.log(game); }
ThestartGame
function is called when the user clicks the “Click to Start” button. It prepares the game grid by setting dimensions, generating CSS grid properties, placing words, adding letters to empty cells, and building the game board and word list. - Letter Adding Function:
function addLetters() { for (let i = 0; i < game.arr.length; i++) { if (game.arr[i] == '-') { game.arr[i] = randomLetter(); } } }
TheaddLetters
function fills empty cells in the game grid with random letters generated by therandomLetter
function. - Random Letter Function:
function randomLetter() { return 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.toLowerCase().split('')[Math.floor(Math.random() * 26)]; }
TherandomLetter
function returns a random lowercase letter from the alphabet. - Word Placement Function:
function placeWord(word) { let placedOkay = false; let cnt = 100; word = (Math.random() > 0.5) ? word : word.split('').reverse().join(''); while (!placedOkay && cnt > 0) { cnt--; let pos = { col: 0, row: 0 }; let dir = (Math.random() > 0.5) ? true : false; if (dir && word.length <= game.c) { pos.col = findStartPos(word.length, game.c); pos.row = Math.floor(Math.random() * game.r); placedOkay = xPlace(pos, word); } else if (!dir && word.length <= game.r) { pos.row = findStartPos(word.length, game.r); pos.col = Math.floor(Math.random() * game.c); placedOkay = yPlace(pos, word); } } return placedOkay; }
TheplaceWord
function is responsible for placing a given word in the game grid. It randomly determines a direction (horizontal or vertical) and starting position for the word, and then checks if the word can be placed without overlapping with other words. ThexPlace
andyPlace
functions handle the actual placement in the horizontal and vertical directions, respectively. - Word Placement Functions (Horizontal and Vertical):
function xPlace(cor, word) { let start = (cor.row * game.c) + cor.col; let okayCounter = 0; let indexPlaced = []; for (let i = 0; i < word.length; i++) { if (game.arr[start + i] == '-') { okayCounter++; } } if (okayCounter == word.length) { for (let i = 0; i < word.length; i++) { if (game.arr[start + i] == '-') { game.arr[start + i] = word[i]; indexPlaced.push(start + i); } } return indexPlaced; } return false; } function yPlace(cor, word) { let start = (cor.row * game.c) + cor.col; let okayCounter = 0; let indexPlaced = []; for (let i = 0; i < word.length; i++) { if (game.arr[start + (i * game.c)] == '-') { okayCounter++; } } if (okayCounter == word.length) { for (let i = 0; i < word.length; i++) { if (game.arr[start + (i * game.c)] == '-') { game.arr[start + (i * game.c)] = word[i]; indexPlaced.push(start + (i * game.c)); } } return indexPlaced; } return false; }
ThexPlace
andyPlace
functions handle the actual placement of a word in the game grid in the horizontal and vertical directions, respectively. They check if the cells where the word will be placed are empty ('-'
) and then replace those cells with the corresponding letters of the word. - Start Position Calculation Function:
function findStartPos(wordVal, totalVal) { return Math.floor(Math.random() * (totalVal - wordVal + 1)); }
ThefindStartPos
function generates a random starting position for a word, ensuring that the word does not go beyond the specified grid dimensions. - Board Building Function:
function buildBoard() { eles.gridContainer.innerHTML = ''; game.arr.forEach((ele, index) => { let div = document.createElement('div'); div.textContent = ele; div.classList.add('grid-item'); eles.gridContainer.append(div); div.addEventListener('click', (e) => { console.log(index); console.log(game.arr[index]); game.boardArray[index] = true; let checker = { found: 0, word: '' }; game.placedWords.forEach((w) => { if (w.pos.includes(index)) { checker.found++; checker.word = w.word; } }); if (checker.found > 0) { div.style.backgroundColor = 'green'; } else { div.style.backgroundColor = 'red'; } foundChecker(); }); }); }
ThebuildBoard
function is responsible for creating and appending grid items to the game grid container. It also attaches a click event listener to each grid item that logs information about the clicked cell and checks if any word is found at that position. - Word Checking Function:
function foundChecker() { game.placedWords.forEach((w, ind) => { let checker = 0; game.boardArray.forEach((val, index) => { if (w.pos.includes(index)) { checker++; } }); if (checker == w.word.length) { w.ele.style.color = 'red'; w.ele.style.textDecoration = 'line-through'; game.placedWords.splice(ind, 1); } }); if (game.placedWords.length == 0) { console.log('Game Over!'); } }
ThefoundChecker
function checks if all the letters of a word have been found in the game grid. If a word is found, its corresponding word list element is marked as completed by changing its color and adding a line-through text decoration. The function also checks if all words have been found, indicating that the game is over. - Logging Function:
function log(txt) { eles.message.textContent = txt; }
Thelog
function updates the game message element with the provided text.
This code sets up a word search game by generating a grid, placing words randomly in the grid, and allowing the user to click on cells to find the placed words. Once all the words have been found, the game ends.
HTML
<!doctype html>
<html>
<head><title>WordSearch</title>
<link rel="stylesheet" href="style.css">
<script src="app3.js"></script>
</head>
<body>
<div class="gameArea"></div>
</body>
</html>
CSS
.gameArea {
text-align: center;
margin: auto;
}
.grid-item {
border: 1px solid black;
padding:20px;
font-size: 2em;
text-align: center;
cursor:grab;
}
.grid-item:hover{
background-color: lightsteelblue;
}
button{
padding:10px;
text-align: center;
color:white;
background-color: red;
font-size: 2em;
}
.myList, input[type="number"]{
text-align: center;
font-size: 2em;
}
input[type="number"]{
width:50px;
}
.gridContainer{
display: grid;
/* grid-template-columns: auto auto auto auto auto;
grid-template-rows: auto auto auto auto auto; */
}
JavaScript
document.addEventListener('DOMContentLoaded',init);
const eles = {};
//const myWords = ['zzzzz'];
const myWords = ['cat','dog','mouse','bird','horse','donkey','frog','rabbit','snake'];
const game = {r:5,c:5,w:100,x:'',y:'',arr:[],placedWords:[],boardArray:[]};
function init(){
eles.gameArea = document.querySelector('.gameArea');
eles.gridContainer = document.createElement('div');
eles.gridContainer.style.margin = 'auto';
eles.message = document.createElement('div');
eles.gridContainer.classList.add('gridContainer');
eles.myList = document.createElement('div');
eles.btn = document.createElement('button');
eles.gridSize = document.createElement('input');
eles.myList.classList.add('myList');
//eles.gameArea.textContent = "Game Ready";
eles.gameArea.append(eles.message);
eles.gameArea.append(eles.gridSize);
eles.gameArea.append(eles.btn);
eles.gameArea.append(eles.gridContainer);
eles.gameArea.append(eles.myList);
eles.gridSize.setAttribute('type','number');
eles.gridSize.setAttribute('max','20');
eles.gridSize.setAttribute('min','2');
log('Click Start to Start the Game. Select the number of cells for the game grid.');
eles.btn.textContent = 'Click to Start';
eles.gridSize.value = 5;
eles.btn.addEventListener('click',startGame);
//console.log(eles);
}
function startGame(){
log('Select the grid letters');
eles.gridSize.style.display = 'none';
eles.btn.style.display = 'none';
game.r = Number(eles.gridSize.value); //rows
game.c = Number(eles.gridSize.value); //cols
eles.gridContainer.style.width = (game.c * game.w +50) +'px';
game.x = '';
game.y = '';
game.boardArray.length = 0;
game.arr.length = 0;
game.arr.length = game.r * game.c;
game.placedWords.length = 0;
for(let i=0;i<game.arr.length;i++){
game.arr[i] = '-';
}
for(let xx=0;xx<game.r;xx++){ game.x += ' auto '}
for(let yy=0;yy<game.r;yy++){ game.y += ' auto '}
//console.log(game);
eles.gridContainer.style.gridTemplateColumns = game.x;
eles.gridContainer.style.gridTemplateRows = game.y;
myWords.forEach((val,index)=>{
let temp = placeWord(val);
if(temp){
game.placedWords.push({
word:val,pos:temp
});
}
})
addLetters();
buildBoard();
eles.myList.innerHTML = ''; //build list of words
game.placedWords.forEach((w)=>{
w.ele = document.createElement('div');
w.ele.textContent = w.word;
w.ele.arr = w.pos;
eles.myList.append(w.ele);
})
console.log(game);
}
function addLetters(){
for(let i=0;i<game.arr.length;i++){
if(game.arr[i]=='-'){
game.arr[i]=randomLetter();
}
}
}
function randomLetter(){
return 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.toLowerCase().split('')[Math.floor(Math.random()*26)]
}
function placeWord(word){
//console.log(word);
let placedOkay = false;
let cnt = 100;
word = (Math.random() > 0.5) ? word : word.split('').reverse().join('');
//console.log(word);
while(!placedOkay && cnt > 0){
cnt--;
let pos = {col:0,row:0}
let dir = (Math.random() > 0.5) ? true : false;
if(dir && word.length <= game.c){
pos.col = findStartPos(word.length,game.c);
pos.row = Math.floor(Math.random() * game.r);
placedOkay = xPlace(pos,word);
}else if(!dir && word.length <= game.r){
pos.row = findStartPos(word.length,game.r);
pos.col = Math.floor(Math.random() * game.c);
placedOkay = yPlace(pos,word);
}
}
return placedOkay;
}
function yPlace(cor,word){
let start = (cor.row * game.c) + cor.col;
let okayCounter = 0;
let indexPlaced = [];
for(let i=0;i<word.length;i++){
if(game.arr[start+(i*game.c)]=='-'){
okayCounter++;
}
}
if(okayCounter == word.length){
for(let i=0;i<word.length;i++){
if(game.arr[start+(i*game.c)]=='-'){
game.arr[start+(i*game.c)] = word[i];
indexPlaced.push(start+(i*game.c));
}
}
return indexPlaced;
}
return false;
}
function xPlace(cor,word){
let start = (cor.row * game.c) + cor.col;
let okayCounter = 0;
let indexPlaced = [];
for(let i=0;i<word.length;i++){
if(game.arr[start+i]=='-'){
okayCounter++;
}
}
if(okayCounter == word.length){
for(let i=0;i<word.length;i++){
if(game.arr[start+i]=='-'){
game.arr[start+i] = word[i];
indexPlaced.push(start+i);
}
}
return indexPlaced;
}
return false;
}
function findStartPos(wordVal,totalVal){
return Math.floor(Math.random()*(totalVal - wordVal + 1))
}
function buildBoard(){
eles.gridContainer.innerHTML = '';
game.arr.forEach((ele,index)=>{
let div = document.createElement('div');
div.textContent = ele;
div.classList.add('grid-item');
eles.gridContainer.append(div);
div.addEventListener('click',(e)=>{
console.log(index);
console.log(game.arr[index]);
game.boardArray[index] = true;
let checker = {found:0,word:''};
game.placedWords.forEach((w)=>{
if(w.pos.includes(index)){
checker.found++;
checker.word = w.word;
}
})
if(checker.found>0){
div.style.backgroundColor = 'green';
}else{
div.style.backgroundColor = 'red';
}
foundChecker();
})
})
}
function foundChecker(){
game.placedWords.forEach((w,ind)=>{
let checker = 0;
game.boardArray.forEach((val,index)=>{
if(w.pos.includes(index)){
checker++;
}
})
if(checker==w.word.length){
w.ele.style.color = "red";
w.ele.style.textDecoration = 'line-through';
};
})
checkWinner();
}
function log(mes){
eles.message.innerHTML = mes;
}
function checkWinner(){
let counter = 0 ;
game.placedWords.forEach((w,ind)=>{
if(w.ele.style.textDecoration=='line-through'){
counter++;
}
})
log(game.placedWords.length - counter + ' Words left');
if((game.placedWords.length - counter)==0 || game.placedWords.length == 0){
log('You Won<br>Click button to start Again');
eles.gridSize.style.display = 'inline-block';
eles.btn.style.display = 'inline-block';
}
}