var w,h,g,g2,my={};function wordsearchMain(){var version='0.52';w=675;h=500;my.hiTiles=[] my.drag={onQ:false,x:0,y:0} my.bd=[];my.opt={wd:12,ht:12,wordN:15,overlapTgt:2,maxAttempts:3,fill:'match',case:'up',dirType:'wasdqezx',dict:'math'} my.cases={up:{type:'up',name:'UPPER'},low:{type:'low',name:'lower'},title:{type:'title',name:'Title'},rand:{type:'rand',name:'rANdoM'},vary:{type:'vary',name:'vARiATIons'}} my.dicts={math:{name:'Mathematics',type:'file',url:'math-large.txt',words:''},measure:{name:'Measurement',type:'file',url:'measure.txt',words:''},time:{name:'Time',type:'file',url:'time.txt',words:''},seasons:{name:'Seasons',type:'file',url:'seasons.txt',words:''},money:{name:'Money',type:'file',url:'money.txt',words:''},shapes:{name:'Shapes',type:'file',url:'shapes.txt',words:''},comp:{name:'Computers',type:'file',url:'computers.txt',words:''},energy:{name:'Energy',type:'file',url:'energy.txt',words:''},elements:{name:'Elements',type:'file',url:'elements.txt',words:''},science:{name:'Science',type:'file',url:'science.txt',words:''},plants:{name:'Plants',type:'file',url:'plants.txt',words:''},happy:{name:'Happy',type:'file',url:'happy.txt',words:''},positive:{name:'Positive',type:'file',url:'positive.txt',words:''},dogs:{name:'Dogs',type:'file',url:'dogs.txt',words:''},pals:{name:'Palindromes',type:'file',url:'palindromes.txt',words:''},country:{name:'Countries',type:'file',url:'country.txt',words:''},adjectives:{name:'Adjectives',type:'file',url:'adjectives.txt',words:''},adverbs:{name:'Adverbs',type:'file',url:'adverbs.txt',words:''},verbs:{name:'Verbs',type:'file',url:'verbs.txt',words:''},preps:{name:'Prepositions',type:'file',url:'prepositions.txt',words:''},prons:{name:'Pronouns',type:'file',url:'pronouns.txt',words:''},cons:{name:'Conjunctions',type:'file',url:'conjunctions.txt',words:''},num:{name:'Numbers',type:'num',url:'',words:''},rand:{name:'Random Letters',type:'ltr',url:'',words:''},} my.fills={alpha:{type:'alpha',name:'Letters'},match:{type:'match',name:'Similar Letters'},blank:{type:'blank',name:'Blanks'}} my.dirTypes={ds:{dirStr:'ds',name:'Down, right'},wasd:{dirStr:'wasd',name:'Up,down,left,right'},qezx:{dirStr:'qezx',name:'Diagonals'},wasdqezx:{dirStr:'wasdqezx',name:'All'}} my.dirs={d:{id:'d',name:'horizontal',move:{x:1,y:0},dir:'right',compass:'E'},a:{id:'a',name:'horizontalBack',move:{x:-1,y:0},dir:'left',compass:'W'},s:{id:'s',name:'vertical',move:{x:0,y:1},dir:'down',compass:'S'},w:{id:'w',name:'verticalUp',move:{x:0,y:-1},dir:'up',compass:'N'},x:{id:'x',name:'diagonal',move:{x:1,y:1},dir:'',compass:'SE'},e:{id:'e',name:'diagonalUp',move:{x:1,y:-1},dir:'',compass:'NE'},q:{id:'q',name:'diagonalBack',move:{x:-1,y:-1},dir:'',compass:'NW'},z:{id:'z',name:'diagonalUpBack',move:{x:-1,y:1},dir:'',compass:'SW'},} my.presets={short:{name:'Short',cols:6,rows:6,diff:1,dict:'images/dict-short.txt'},sml:{name:'Small',cols:6,rows:6,diff:1,dict:'images/dict-short.txt'},med:{name:'Medium',cols:6,rows:6,diff:1,dict:'images/dict-short.txt'},wide:{name:'Wide',cols:6,rows:6,diff:1,dict:'images/dict-short.txt'},lrg:{name:'Large',cols:6,rows:6,diff:1,dict:'images/dict-short.txt'},num:{name:'Numbers',cols:6,rows:6,diff:1,dict:'images/dict-short.txt'},} my.clrs=["#0000ff","#00ff00","#ff8800","#660066","#99ff00","#0099ff","#00ff99","#9900ff","#ff0099","#006666","#666600","#990000","#009999","#ff9900","#ff0000","#003399","#ff00ff","#993333","#330099"];my.clrN=0 var s='';my.imgHome=(document.domain=='localhost')?'/mathsisfun/images/':'/images/' my.sndHome=(document.domain=='localhost')?'/mathsisfun/images/sounds/':'/images/sounds/' s+='';s+='';s+='';s+='';my.snds=[];my.soundQ=true s+='' s+='
';s+='
' s+='
Title
' s+='
' s+='
' s+='' s+='' my.snds=[];my.soundQ=true s+='   ' s+=soundBtnHTML() s+='
' s+='
';s+='';s+='';s+=optPopHTML();s+='
';s+='
© 2019 MathsIsFun.com v'+version+'
';s+='
';s+='
';s+='';document.write(s);var el=document.getElementById('canvas1');var ratio=3;el.width=window.innerWidth*ratio el.height=window.innerHeight*ratio g=el.getContext("2d");g.setTransform(ratio,0,0,ratio,0,0);var el2=document.getElementById('canvas2');el2.width=window.innerWidth*ratio el2.height=window.innerHeight*ratio g2=el2.getContext("2d");g2.setTransform(ratio,0,0,ratio,0,0);el2.addEventListener('mousedown',function(ev){mouseDown(ev)}) el2.addEventListener('mouseup',function(){mouseUp()}) el2.addEventListener('touchstart',function(ev){var touch=ev.targetTouches[0];ev.clientX=touch.clientX;ev.clientY=touch.clientY;ev.touchQ=true;mouseDown(ev)}) el2.addEventListener('touchend',function(ev){mouseUp(ev)}) el2.addEventListener('mousemove',function(ev){mouseMove(ev)}) el2.addEventListener('touchmove',function(ev){console.log('touchmove') var touch=ev.targetTouches[0];ev.clientX=touch.clientX;ev.clientY=touch.clientY;ev.touchQ=true;mouseMove(ev)}) my.wordStr='angle,area,Apex,Calculate,centimetre,Circle,Cone,decimal,degrees,diameter,Digit,equation,equilateral,Estimate,factor,Fraction,Hexagon,integer,isosceles,litre,multiple,negative,Pentagon,positive,prime,Prism,quotient,radius,Random,Spiral,times,Volume,Zero' radioSet('fill',my.opt.fill) radioSet('case',my.opt.case) radioSet('dirType',my.opt.dirType) radioSet('dict',my.opt.dict) optPop()} function dictLoad(){console.log('dictLoad',my.opt.dict) var url=my.imgHome+'words/'+my.opt.dict.url var rawFile=new XMLHttpRequest();rawFile.open("GET.html",url,true);rawFile.onreadystatechange=function(){if(rawFile.readyState===4){if(rawFile.status===200||rawFile.status==0){my.opt.dict.words=rawFile.responseText if(my.opt.dict.words.length==0)my.opt.dict.words=my.wordStr gameNew()}}} rawFile.send(null);} function tileAt(x,y){var xn=Math.floor((x-my.borderLt)/my.boxWd) var yn=Math.floor((y-my.borderTp)/my.boxWd) if(xn<0)return null if(yn<0)return null if(xn>=my.opt.wd)return null if(yn>=my.opt.ht)return null if(my.bd.length==0)return null return my.bd[xn][yn]} function boxLeft(xn){return my.borderLt+my.boxWd*xn} function boxTop(yn){return my.borderTp+my.boxWd*yn} function mouseDown(ev){console.log('mouseDown') var rect=g.canvas.getBoundingClientRect();var x=ev.clientX-rect.left var y=ev.clientY-rect.top var tile=tileAt(x,y) my.tileFrom=tile my.tileTo=tile my.drag.onQ=true my.drag.x=x my.drag.y=y ev.preventDefault() console.log('mousedown',my.drag)} function mouseMove(ev){if(!my.drag.onQ)return var rect=g.canvas.getBoundingClientRect();var x=ev.clientX-rect.left var y=ev.clientY-rect.top g.clearRect(0,0,g.canvas.width,g.canvas.height) g.strokeStyle='black' g.beginPath() g.moveTo(my.drag.x,my.drag.y) g.lineTo(x,y) g.stroke() var tile=tileAt(x,y) if(my.tileFrom==null)return;my.tileTo=tile wordHilite(my.tileFrom,my.tileTo);ev.preventDefault();} function mouseUp(){my.drag.onQ=false tilesHiliteClear() g.clearRect(0,0,g.canvas.width,g.canvas.height) var found=wordHilite(my.tileFrom,my.tileTo) if(found==undefined)return tilesHiliteClear() var foundn=-1 for(var i=0;i=my.clrs.length)my.clrN=0 g2.lineWidth=my.boxWd*0.9 g2.lineCap="round" g2.beginPath() g2.moveTo(boxLeft(my.tileFrom.xn)+my.boxWd/2,boxTop(my.tileFrom.yn)+my.boxWd/2) g2.lineTo(boxLeft(my.tileTo.xn)+my.boxWd/2,boxTop(my.tileTo.yn)+my.boxWd/2) g2.stroke() if(my.words.length==0){soundPlay('sndWin') winAnim()}} function parseWords(s){var LF=String.fromCharCode(10);var CR=String.fromCharCode(13);s=s.split(CR+LF).join(",");s=s.split(CR).join(",");s=s.split(LF).join(",");var words=s.split(",") words.sort() var goods=[] var prevWord='' var regex=new RegExp(/^[a-zA-Z0-9 ]+$/i);for(var i=0;i20)continue if(word==prevWord)continue prevWord=word word=word.toLowerCase() if(!regex.test(word))continue goods.push(word)} console.log('goods',words.length,goods.length) console.log('goods',goods.join(',')) return goods} function randomNums(){var maxLen=Math.min(my.opt.wd,my.opt.ht,10);console.log("maxLen="+maxLen);var words=[] for(var i=0;i<50;i++){var len=randomInt(4,maxLen+1);words.push(randomNum(len,true));} return words} function randomNum(digits,decQ){var s="";for(var i=0;i0){var index=Math.floor(Math.random()*ctr);ctr--;var temp=arr[ctr];arr[ctr]=arr[index];arr[index]=temp;} return arr;} function gameNew(){switch(my.opt.dict.type){case 'file':if(my.opt.dict.words.length==0){dictLoad() return} break case 'num':my.opt.dict.words=randomNums().join(',') break case 'ltr':my.opt.dict.words=randomStrings().join(',') break default:console.log('Dont know how to load the words')} document.getElementById('title').innerHTML=my.opt.dict.name var dh=Math.max(document.documentElement.clientHeight,window.innerHeight||0) var dw=Math.max(document.documentElement.clientWidth,window.innerWidth||0) my.vmin=Math.min(dh,dw)/100 console.log('my.vmin',my.vmin) my.borderTp=11*my.vmin my.borderLt=1*my.vmin g.clearRect(0,0,g.canvas.width,g.canvas.height) g2.clearRect(0,0,g2.canvas.width,g2.canvas.height) var div=document.getElementById("board");while(div.firstChild){div.removeChild(div.firstChild);} my.opt.orientations=my.opt.dirType.dirStr.split('') console.log('my.opt',my.opt) var words=parseWords(my.opt.dict.words) shuffle(words) var fwords=(my.opt.case=='vary')?wordsVar(words):wordsFilter(words,my.opt.wordN*4) var p=new Puzzle() var puzzle=p.fill(fwords);console.log('puzzle:',puzzle);my.bdSz=my.opt.wd my.boxWd=Math.min(15,70/Math.max(my.opt.wd,my.opt.ht))*my.vmin console.log('my',my) my.bd=[] for(var i=0;i1){if(Math.pow(word.length,2)>=my.opt.wordN){var wordComb=wordCapComb(word) shuffle(wordComb) return wordComb.slice(0,my.opt.wordN)}}}} function wordsFilter(words,maxN){var wordCount=0;var maxLen=Math.max(my.opt.ht,my.opt.wd) var currWords=[];console.log('maxLen',maxLen,my.opt) for(var i=0;i1&&word.length<=maxLen){switch(my.opt.case.type){case 'up':word=word.toUpperCase() break case 'low':word=word.toLowerCase() break case 'title':word=word.charAt(0).toUpperCase()+word.slice(1) break case 'rand':var wordRand='' for(var j=0;j=maxN)break;}} console.log('currWords',currWords) return currWords} function wordCapComb(str){var n=str.length var arr=[] for(var i=0;i<(1<'} s+='' s+='
' for(var i=0;i'} s+='
' var div=document.getElementById('words') div.innerHTML=s} function tilesHiliteClear(){for(var i=0;i'+wordRev) return{wordFwd:wordFwd,wordRev:wordRev}} function Tile(wd,ht,xn,yn,val){this.wd=wd this.ht=ht this.xn=xn this.yn=yn this.val=val this.bgClr='#fef' this.fgClr='black' this.origQ=false this.cands=[] var div=document.createElement("div");div.style.width=wd+'px' div.style.height=ht+'px' div.style.position='absolute' div.style.left=boxLeft(xn)+'px' div.style.top=boxTop(yn)+'px' this.div=div var can=document.createElement('canvas');can.style.position="absolute";can.style.top='0px' can.style.left='0px' can.style.width='100%' can.style.height='100%' can.width=wd can.height=ht this.g=can.getContext("2d");div.appendChild(can) document.getElementById('board').appendChild(div);this.draw()} Tile.prototype.clrSet=function(clr){this.bgClr=clr this.draw()} Tile.prototype.valSet=function(v,histQ){histQ=typeof histQ!=='undefined'?histQ:true var was=this.val if(v>=1&&v<=9){this.val=parseInt(v) soundPlay('sndPlace')}else{this.val='' soundPlay('sndClear')} this.origQ=false if(histQ)my.hist.push({xn:this.xn,yn:this.yn,was:was}) this.draw()} Tile.prototype.draw=function(){var fgClr='black' this.drawNum(this.val,fgClr)} Tile.prototype.drawNum=function(v,clr){var g=this.g g.clearRect(0,0,this.wd,this.ht) g.strokeStyle='black' g.lineWidth=1 g.fillStyle=this.bgClr if(my.clrNumQ&&!this.origQ)g.fillStyle='#ffe' g.beginPath() var gap=1 g.rect(gap,gap,this.wd-2*gap,this.ht-2*gap) g.fill() if(my.clrNumQ)clr=my.clrs[v][1];g.fillStyle=clr g.font=Math.round(this.wd*0.75)+'px Arial';g.textAlign='center' g.beginPath() g.fillText(v,Math.round(this.wd*0.5),Math.round(this.wd*0.8)) g.fill()} Tile.prototype.hilite=function(onQ){if(onQ){this.bgClr='#bcf'}else{this.bgClr='#fef'} this.draw()} Tile.prototype.win=function(){this.bgClr='#ffe' this.draw()} Tile.prototype.setxy=function(lt,tp){this.div.style.left=lt+'px';this.div.style.top=tp+'px';} var Puzzle=function(){} Puzzle.prototype.fill=function(words){this.bd=[] for(var i=0;i=my.opt.wordN)break}else{if(false){return null;}}} my.words=my.words.sort(function(a,b){var nameA=a.toUpperCase();var nameB=b.toUpperCase();if(nameAnameB)return 1 return 0}) switch(my.opt.fill.type){case 'alpha':var ltrs='abcdefghijklmnoprstuvwy' if(my.opt.case.type=='up')ltrs=ltrs.toUpperCase() this.fillBlanks(ltrs);break case 'match':var ltrs='' for(var i=0;i=0)locs.push({x:i,y:j,move:dir.move,overlap:lap})}}} return locs} Puzzle.prototype.locCheck=function(word,xn,yn,move){var overlapN=0 var len=word.length-1 if(xn+len*move.x<0)return-1 if(xn+len*move.x>=my.opt.wd)return-1 if(yn+len*move.y<0)return-1 if(yn+len*move.y>=my.opt.wd)return-1 for(var i=0;i0){var n=Math.floor(Math.random()*ltrs.length);var ltr=ltrs[n];} this.bd[i][j]=ltr}}}} function winAnim(){console.log('winAnim',my.bd) var ms=50 for(var i=0;i0){var div=document.getElementById(name) if(div.currentTime>0&&div.currentTime0)soundPlayQueue();};} function soundToggle(){var btn='sound' if(my.soundQ){my.soundQ=false document.getElementById(btn).classList.add("mute")}else{my.soundQ=true document.getElementById(btn).classList.remove("mute")}} function radioHTML(prompt,id,lbls,checkId){var s='';s+='
';s+='
';s+=prompt;s+='
';s+='
';for(var i=0;i' s+='';s+=lbl.name s+=' ';} s+='
';s+='
';return s;} function radioHTMLa(prompt,id,lbls,checkId){var s='';s+='
';s+='
';s+=prompt;s+='
';s+='
';for(var prop in lbls){var lbl=lbls[prop] var idi=prop var chkStr=(lbl.id==checkId)?' checked ':'';s+=' ';} s+='
';s+='
';return s;} function optPopHTML(){var s='';s+='
';s+='
';s+='';s+=' ' s+='';s+='
' s+='
';var sliders=[{id:'wd',name:'Width',val:my.opt.wd,min:1,max:16,step:1,fnName:'onJoe'},{id:'ht',name:'Height',val:my.opt.ht,min:1,max:16,step:1,fnName:'onJoe'},{id:'wordN',name:'Words',val:my.opt.wordN,min:1,max:20,step:1,fnName:'onJoe'},{id:'overlapTgt',name:'Overlap',val:my.opt.overlapTgt,min:0,max:5,step:1,fnName:'onJoe'},];for(var i=0;iTry to fit:
' s+='
'+slider.name+':
' s+='';s+='
'+slider.val+'
';s+='
'} s+='' s+='
';s+=radioHTMLa('Fill spaces:','fill',my.fills,'',0);s+='
' s+='
';s+=radioHTMLa('Letter case:','case',my.cases,'',0);s+='
' s+='
';s+=radioHTMLa('Directions:','dirType',my.dirTypes,'',0);s+='
' s+='
';s+=radioHTMLa('Words:','dict',my.dicts,'',0);s+='
' s+='';return s;} function optPop(){var pop=document.getElementById('optpop');pop.style.transitionDuration="0.3s";pop.style.opacity=1;pop.style.left='3vmin'} function optYes(){var pop=document.getElementById('optpop');pop.style.opacity=0;pop.style.left='-120vmin';var div=document.querySelector('input[name="'+'dict'+'"]:checked') my.opt.dict=my.dicts[div.id];var div=document.querySelector('input[name="'+'fill'+'"]:checked') my.opt.fill=my.fills[div.id];var div=document.querySelector('input[name="'+'case'+'"]:checked') my.opt.case=my.cases[div.id];var div=document.querySelector('input[name="'+'dirType'+'"]:checked') my.opt.dirType=my.dirTypes[div.id];gameNew()} function optNo(){var pop=document.getElementById('optpop');pop.style.opacity=0;pop.style.left='-999px';} function onJoe(a,val,id){var div=document.getElementById(id) div.innerHTML=val my.opt[id]=parseInt(val) console.log('onJoe',a,val,id,my.opt)} function radioSet(name,setValue){var divs=document.querySelectorAll('input[name="'+name+'"]') for(var i=0;i