Skip to content

Instantly share code, notes, and snippets.

@QuentinAndre
Created November 8, 2018 17:23
Show Gist options
  • Save QuentinAndre/f69be9338db73751b27bafaa95bde13d to your computer and use it in GitHub Desktop.
Save QuentinAndre/f69be9338db73751b27bafaa95bde13d to your computer and use it in GitHub Desktop.
var default_matrix = [
['V', 'H', 'W', 'X', 'S', 'C', 'E', 'P', 'T', 'E', 'R', 'C', 'R', 'S', 'P', 'S', 'J', 'T'],
['S', 'T', 'T', 'T', 'N', 'X', 'D', 'Y', 'D', 'X', 'L', 'M', 'W', 'K', 'A', 'O', 'B', 'C'],
['G', 'N', 'A', 'R', 'C', 'W', 'O', 'E', 'A', 'Y', 'T', 'R', 'S', 'V', 'L', 'V', 'G', 'J'],
['C', 'T', 'O', 'D', 'O', 'P', 'O', 'F', 'S', 'N', 'N', 'R', 'A', 'H', 'A', 'E', 'G', 'P'],
['E', 'O', 'B', 'M', 'R', 'S', 'D', 'R', 'E', 'C', 'O', 'A', 'O', 'E', 'C', 'R', 'I', 'A'],
['R', 'I', 'L', 'I', 'M', 'F', 'N', 'M', 'C', 'N', 'E', 'U', 'S', 'K', 'E', 'E', 'P', 'A'],
['J', 'E', 'N', 'O', 'A', 'O', 'N', 'O', 'O', 'M', 'S', 'N', 'I', 'T', 'K', 'I', 'U', 'H'],
['H', 'C', 'T', 'M', 'N', 'R', 'C', 'H', 'C', 'E', 'O', 'N', 'T', 'N', 'Y', 'G', 'W', 'L'],
['E', 'T', 'I', 'R', 'E', 'Y', 'H', 'O', 'H', 'M', 'G', 'T', 'I', 'D', 'H', 'N', 'L', 'N'],
['H', 'L', 'R', 'V', 'A', 'E', 'T', 'O', 'L', 'D', 'L', 'G', 'S', 'L', 'U', 'I', 'K', 'J'],
['Y', 'T', 'O', 'I', 'A', 'H', 'L', 'I', 'O', 'O', 'H', 'A', 'A', 'U', 'N', 'K', 'V', 'F'],
['W', 'G', 'L', 'D', 'B', 'D', 'C', 'M', 'I', 'T', 'R', 'W', 'E', 'E', 'C', 'X', 'E', 'W'],
['L', 'A', 'Y', 'O', 'R', 'B', 'T', 'U', 'K', 'D', 'J', 'D', 'B', 'R', 'T', 'K', 'R', 'A'],
['S', 'E', 'A', 'L', 'M', 'U', 'C', 'T', 'W', 'I', 'N', 'D', 'S', 'O', 'R', 'C', 'U', 'C'],
['Z', 'N', 'E', 'T', 'N', 'E', 'M', 'A', 'I', 'L', 'R', 'A', 'P', 'Z', 'M', 'I', 'L', 'B'],
['Z', 'T', 'H', 'R', 'O', 'N', 'E', 'B', 'P', 'A', 'T', 'R', 'O', 'N', 'A', 'G', 'E', 'W'],
['V', 'P', 'K', 'M', 'V', 'G', 'F', 'T', 'R', 'A', 'D', 'I', 'T', 'I', 'O', 'N', 'R', 'Q'],
['O', 'Z', 'A', 'C', 'G', 'R', 'N', 'T', 'A', 'O', 'Y', 'D', 'L', 'G', 'X', 'C', 'M', 'C']
];
var grid1 = [
['A', 'I', 'V', 'T', 'A', 'L', 'N', 'I', 'E', 'T', 'S', 'N', 'E', 'T', 'H', 'C', 'E', 'I', 'L'],
['G', 'N', 'E', 'T', 'H', 'E', 'R', 'L', 'A', 'N', 'D', 'S', 'N', 'P', 'V', 'A', 'A', 'P', 'D'],
['R', 'O', 'M', 'A', 'N', 'I', 'A', 'T', 'V', 'I', 'S', 'R', 'O', 'I', 'I', 'I', 'O', 'C', 'B'],
['U', 'T', 'E', 'J', 'V', 'I', 'E', 'T', 'Y', 'C', 'N', 'L', 'E', 'R', 'A', 'R', 'I', 'D', 'I'],
['O', 'V', 'P', 'M', 'J', 'J', 'S', 'C', 'O', 'B', 'A', 'A', 'T', 'C', 'T', 'P', 'N', 'E', 'G'],
['B', 'E', 'C', 'I', 'V', 'E', 'S', 'T', 'N', 'N', 'T', 'S', 'U', 'U', 'E', 'A', 'S', 'V', 'Y'],
['M', 'A', 'E', 'I', 'K', 'A', 'L', 'L', 'D', 'A', 'U', 'W', 'G', 'H', 'L', 'E', 'X', 'C', 'A'],
['E', 'G', 'J', 'N', 'L', 'A', 'T', 'V', 'O', 'A', 'R', 'A', 'B', 'R', 'T', 'B', 'R', 'Z', 'W'],
['X', 'E', 'J', 'W', 'N', 'B', 'S', 'L', 'E', 'V', 'L', 'F', 'E', 'N', 'U', 'I', 'V', 'G', 'R'],
['U', 'Y', 'P', 'D', 'I', 'V', 'U', 'S', 'A', 'E', 'A', 'Z', 'L', 'L', 'R', 'L', 'L', 'S', 'O'],
['L', 'R', 'R', 'M', 'A', 'C', 'T', 'P', 'N', 'M', 'T', 'K', 'G', 'T', 'N', 'V', 'P', 'N', 'N'],
['I', 'A', 'A', 'N', 'A', 'O', 'E', 'I', 'E', 'I', 'Y', 'A', 'I', 'J', 'N', 'S', 'K', 'D', 'J'],
['L', 'G', 'N', 'I', 'N', 'C', 'A', 'L', 'W', 'R', 'R', 'H', 'U', 'A', 'E', 'D', 'R', 'N', 'D'],
['I', 'N', 'I', 'I', 'T', 'R', 'E', 'S', 'A', 'I', 'H', 'V', 'M', 'L', 'J', 'N', 'A', 'A', 'J'],
['N', 'U', 'A', 'V', 'K', 'A', 'A', 'D', 'A', 'N', 'P', 'C', 'A', 'O', 'V', 'A', 'M', 'L', 'Y'],
['U', 'H', 'Z', 'U', 'V', 'J', 'O', 'G', 'O', 'R', 'D', 'W', 'E', 'V', 'J', 'L', 'N', 'G', 'L'],
['N', 'E', 'D', 'E', 'W', 'S', 'B', 'R', 'N', 'N', 'U', 'V', 'J', 'Z', 'T', 'E', 'E', 'N', 'A'],
['D', 'S', 'U', 'R', 'A', 'L', 'E', 'B', 'C', 'T', 'I', 'I', 'G', 'I', 'C', 'R', 'D', 'E', 'T'],
['D', 'N', 'A', 'L', 'N', 'I', 'F', 'G', 'E', 'R', 'M', 'A', 'N', 'Y', 'W', 'I', 'M', 'E', 'I']];
var words1 = ['AUSTRIA', 'BELARUS', 'BELGIUM', 'BULGARIA', 'CROATIA', 'CZECHREPUBLIC', 'DENMARK', 'ENGLAND', 'ESTONIA',
'FINLAND', 'FRANCE', 'GERMANY', 'GREECE', 'HUNGARY', 'ICELAND', 'IRELAND', 'ITALY', 'LATVIA', 'LIECHTENSTEIN',
'LITHUANIA', 'LUXEMBOURG', 'MACEDONIA', 'MALTA', 'NETHERLANDS', 'NORWAY', 'POLAND', 'PORTUGAL', 'ROMANIA',
'SCOTLAND', 'SLOVAKIA', 'SPAIN', 'SWEDEN', 'SWITZERLAND', 'UKRAINE', 'WALES'];
var grid2 = [
['K', 'P', 'E', 'N', 'C', 'I', 'L', 'C', 'A', 'D', 'N', 'E', 'G ', 'A', 'H', 'L', 'B'],
['Y', 'I', 'L', 'E', 'T', 'T', 'E', 'R', 'S', 'L', 'B', 'M', 'E', 'M', 'O', 'Y', 'T'],
['E', 'J', 'S', 'J', 'L', 'K', 'I', 'C', 'R', 'P', 'B', 'C', 'C', 'J', 'X', 'R', 'D'],
['C', 'E', 'G', 'V', 'Y', 'F', 'Q', 'X', 'H', 'L', 'M', 'M', 'O', 'K', 'E', 'A', 'M'],
['U', 'T', 'N', 'E', 'M', 'U', 'C', 'O', 'D', 'A', 'I', 'A', 'V', 'G', 'M', 'N', 'W'],
['D', 'M', 'R', 'N', 'T', 'J', 'P', 'R', 'L', 'R', 'I', 'A', 'T', 'K', 'S', 'O', 'T'],
['I', 'W', 'P', 'E', 'X', 'G', 'A', 'E', 'E', 'W', 'M', 'R', 'M', 'S', 'T', 'I', 'S'],
['A', 'Z', 'W', 'H', 'P', 'D', 'C', 'T', 'N', 'I', 'E', 'G ', 'A', 'E', 'A', 'T', 'T'],
['R', 'R', 'U', 'J', 'N', 'A', 'U', 'F', 'R', 'S', 'T', 'E', 'P', 'D', 'P', 'C', 'A'],
['Y', 'I', 'D', 'E', 'E', 'P', 'P', 'L', 'P', 'R', 'O', 'D', 'P', 'T', 'L', 'I', 'T'],
['T', 'R', 'L', 'N', 'M', 'P', 'O', 'G', 'U', 'B', 'N', 'N', 'O', 'R', 'E', 'D', 'I'],
['X', 'A', 'O', 'O', 'L', 'F', 'N', 'L', 'L', 'H', 'R', 'A', 'I', 'A', 'R', 'E', 'O'],
['C', 'H', 'C', 'V', 'F', 'I', 'E', 'O', 'C', 'X', 'R', 'H', 'N', 'V', 'D', 'T', 'N'],
['P', 'T', 'S', 'I', 'T', 'R', 'T', 'X', 'S', 'R', 'O', 'T', 'T', 'E', 'L', 'R', 'E'],
['B', 'A', 'C', 'E', 'G', 'T', 'E', 'T', 'R', 'V', 'I', 'R', 'M', 'L', 'R', 'O', 'R'],
['K', 'E', 'E', 'O', 'E', 'L', 'X', 'I', 'D', 'H', 'G', 'O', 'E', 'S', 'O', 'P', 'Y'],
['Y', 'M', 'X', 'R', 'A', 'F', 'X', 'B', 'O', 'S', 'S', 'H', 'N', 'X', 'Z', 'E', 'C'],
['L', 'X', 'C', 'A', 'V', 'H', 'U', 'A', 'E', 'R', 'I', 'S', 'T', 'B', 'T', 'R', 'X'],
['G', 'A', 'H', 'J', 'F', 'T', 'O', 'G', 'U', 'N', 'I', 'G ', 'N', 'I', 'L', 'I', 'F']
];
var words2 = ['AGENDA', 'APPOINTMENT', 'BLOTTER', 'BOSS', 'CALENDAR', 'CHAIR', 'COMPUTER', 'DESK', 'DIARY',
'DICTIONARY', 'DOCUMENT', 'FAX', 'FILING', 'LETTER', 'MAIL', 'MEETING', 'MEMO', 'NOTE', 'OFFICE', 'PAPER',
'PENCIL', 'PENS', 'PHONE', 'REPORT', 'RULER', 'SHORTHAND', 'STAMPS', 'STATIONERY', 'STAPLER', 'TRAVEL', 'XEROX'];
var default_words = [
'throne',
'palace',
'tradition',
'family',
'descent',
'royal',
'kingdom',
'prince',
'law',
'earl',
'government',
'charter',
'sovereign',
'orb',
'commons'
];
class Chronometer {
constructor() {
this.elapsed = 0;
this.timer = setInterval(() => this.tick(), 1000);
}
tick() {
this.elapsed = this.elapsed + 1;
}
getElapsed() {
return this.elapsed;
}
}
function wordsToUpperCase(words) {
for (var i = 0; i < words.length; i++) {
words[i] = words[i].toUpperCase();
}
return words;
}
class WordSearch {
constructor(o) {
let obj = o ? o : {
'words': default_words,
'wordsGrid': default_matrix,
'onFindWord': () => null,
'parentId': "mydiv"
};
this.wordsGrid = obj.wordsGrid;
this.words = wordsToUpperCase(obj.words);
this.onFindWord = obj.onFindWord;
this.rowSize = this.wordsGrid.length;
this.colSize = this.wordsGrid[0].length;
this.timeToFind = new Array(this.words.length).fill(-1);
this.matrix = this.initMatrix();
this.parent = document.getElementById(obj.parentId);
this.timer = new Chronometer();
this.drawGameArea();
this.displayScore();
}
drawGameArea() {
var scoreArea = document.createElement("h2");
var scoreLabel = document.createElement("div");
scoreLabel.id = "score";
scoreArea.append(scoreLabel);
this.parent.appendChild(scoreArea);
var gridArea = document.createElement("section");
gridArea.setAttribute("class", "ws-area");
this.drawMatrix(gridArea);
this.parent.appendChild(gridArea);
var wordsArea = document.createElement("ul");
wordsArea.setAttribute("class", "ws-words");
this.drawWordList(wordsArea);
this.parent.appendChild(wordsArea);
}
getScore() {
return this.timeToFind.map(i => i > 0 ? 1 : 0).reduce((a, b) => a + b);
}
getRemaining() {
return this.timeToFind.map(i => i > 0 ? 0 : 1).reduce((a, b) => a + b);
}
getTiming() {
return this.timeToFind.slice();
}
displayScore() {
document.getElementById("score").innerHTML = "Found " + this.getScore() + " out of " + this.words.length + " words so far.";
}
initMatrix() {
let matrix = [];
for (var row = 0; row < this.rowSize; row++) {
for (var col = 0; col < this.colSize; col++) {
var item = {
letter: this.wordsGrid[row][col], // Default value
row: row,
col: col
};
if (!matrix[row]) {
matrix[row] = [];
}
matrix[row][col] = item;
}
}
return matrix;
}
drawWordList(target) {
var words = this.words;
for (var i = 0; i < words.length; i++) {
var liEl = document.createElement('li');
liEl.id = words[i];
liEl.setAttribute('class', 'ws-word');
liEl.setAttribute("text-decoration", "none");
liEl.innerHTML = words[i];
target.appendChild(liEl);
}
}
getItem(row, col) {
return (this.matrix[row] ? this.matrix[row][col] : undefined);
}
getItems(rowFrom, colFrom, rowTo, colTo) {
var items = [];
if (rowFrom === rowTo || colFrom === colTo || Math.abs(rowTo - rowFrom) === Math.abs(colTo - colFrom)) {
var shiftY = (rowFrom === rowTo) ? 0 : (rowTo > rowFrom) ? 1 : -1,
shiftX = (colFrom === colTo) ? 0 : (colTo > colFrom) ? 1 : -1,
row = rowFrom,
col = colFrom;
items.push(this.getItem(row, col));
do {
row += shiftY;
col += shiftX;
items.push(this.getItem(row, col));
} while (row !== rowTo || col !== colTo);
}
return items;
}
drawMatrix(target) {
var rowcount = this.rowSize;
var columncount = this.colSize;
for (var row = 0; row < rowcount; row++) {
// New row
var divEl = document.createElement('div');
divEl.setAttribute('class', 'ws-row');
target.appendChild(divEl);
for (var col = 0; col < columncount; col++) {
var item = this.matrix[row][col];
var cvEl = document.createElement('canvas');
cvEl.setAttribute('class', 'ws-col');
cvEl.setAttribute('width', 25);
cvEl.setAttribute('height', 25);
// Fill text in middle center
var x = cvEl.width / 2,
y = cvEl.height / 2;
var ctx = cvEl.getContext('2d');
ctx.font = '400 18px Calibri';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillStyle = '#333'; // Text color
ctx.fillText(item.letter, x, y);
// Add event listeners
cvEl.addEventListener('mousedown', this.handleMousedown(item));
cvEl.addEventListener('mouseover', this.handleMouseover(item));
cvEl.addEventListener('mouseup', this.handleMouseup());
divEl.appendChild(cvEl);
}
}
}
handleMouseover(item) {
var that = this;
return function () {
if (that.selectFrom) {
that.selected = that.getItems(that.selectFrom.row, that.selectFrom.col, item.row, item.col);
that.clearHighlight();
for (var i = 0; i < that.selected.length; i++) {
var current = that.selected[i],
row = current.row + 1,
col = current.col + 1,
el = document.querySelector('.ws-row:nth-child(' + row + ') .ws-col:nth-child(' + col + ')');
el.className += ' ws-selected';
}
}
}
}
handleMouseup() {
var that = this;
return function () {
that.selectFrom = null;
that.clearHighlight();
that.validateSelection(that.selected);
that.selected = [];
}
}
handleMousedown(item) {
var that = this;
return function () {
that.selectFrom = item;
}
}
clearHighlight() {
var selectedEls = document.querySelectorAll('.ws-selected');
for (var i = 0; i < selectedEls.length; i++) {
selectedEls[i].classList.remove('ws-selected');
}
}
markAsFound(selected) {
for (var i = 0; i < selected.length; i++) {
var row = selected[i].row + 1,
col = selected[i].col + 1,
el = document.querySelector('.ws-row:nth-child(' + row + ') .ws-col:nth-child(' + col + ')');
el.classList.add('ws-found');
}
this.displayScore();
this.onFindWord();
}
validateSelection(selected) {
var wordSelected = '';
for (var i = 0; i < selected.length; i++) {
wordSelected += selected[i].letter;
}
var wordSelectedR = wordSelected.split('').reverse().join('');
var indexOfWord = this.words.indexOf(wordSelected);
var indexOfWordR = this.words.indexOf(wordSelectedR);
if (indexOfWord > -1) {
if (this.timeToFind[indexOfWord] === -1) {
this.timeToFind[indexOfWord] = this.timer.getElapsed();
var ele = document.getElementById(wordSelected);
ele.style.setProperty("text-decoration", "line-through");
ele.style.setProperty("color", "red");
ele.setAttribute("text-decoration", "line-through");
this.markAsFound(selected);
}
}
if (indexOfWordR > -1) {
if (this.timeToFind[indexOfWordR] === -1) {
this.timeToFind[indexOfWordR] = this.timer.getElapsed();
var ele = document.getElementById(wordSelectedR);
ele.style.setProperty("text-decoration", "line-through");
ele.style.setProperty("color", "red");
ele.setAttribute("text-decoration", "line-through");
this.markAsFound(selected);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment