let w,h,my={};function matheraseMain(){let version='0.521';w=360;h=480;my.opts={name:'user',bdSzN:3} my.boxWd=40 my.unitsQ=true my.canHoverQ=false my.qLen=4 my.score=0 my.scoreMults=[0,1,2,4,10,20,40,100,200] my.bdSzs=[] for(let i=4;i<=9;i++){my.bdSzs.push({id:'sz'+i,name:i+'x'+i,n:i})} my.bdSz=7 my.modes=[{id:'add',name:'Add',min:1,max:9,op:'add'},{id:'multp3',name:'Multiply 0 to 3',min:0,max:3,op:'mult'},{id:'multn1',name:'Multiply -1 to 1',min:-1,max:1,op:'mult'},{id:'multn2',name:'Multiply -2 to 2',min:-2,max:2,op:'mult'},] my.mode=my.modes[0] let s='';s+='' my.sndHome=(document.domain=='localhost')?'/mathsisfun/images/sounds/':'/images/sounds/' s+='';s+='';s+='';s+='' my.snds=[];s+='
';s+='
' s+='
' s+='' s+='' my.soundQ=true s+=' ' s+=soundBtnHTML() s+='
' s+='
0
' s+='
score
' s+='
0
' s+='
moves
' s+=`
` s+='
' s+='
';s+=optPopHTML();s+='';s+='
© 2020 MathsIsFun.com v'+version+'
';s+='
';s+='
';document.write(s);my.clrs=[["Blue",'#0000FF'],["Orange",'#FFA500'],["Slate Blue",'#6A5ACD'],["Green",'#00cc00'],["Lime",'#00FF00'],["Teal",'#008080'],["Gold",'#ffd700'],["Med Purple",'#aa00aa'],["Navy",'#000080'],["Purple",'#800080'],["Dark SeaGreen",'#8FBC8F']];my.clrNum=0;document.getElementById("bdSzs").selectedIndex=optGet('bdSzN') document.getElementById("modes").selectedIndex=optGet('modeN') gameNew()} function gameNew(){let myNode=document.getElementById("board");while(myNode.firstChild){myNode.removeChild(myNode.firstChild);} my.qTiles=[] for(let i=0;i{if(tile.xn>0&&tile.yn>0&&tile.xn{if(tile.emptyQ){let nbors=nborsGet(tile) if(nbors.length>0){let val=nborsCalc(nbors) queue.push(val)}}}) console.log('queue',queue) return queue} function nborsCalc(nbors){switch(my.mode.op){case 'add':let sum=nbors.reduce((tot,nbor)=>{return nbor.emptyQ?tot:tot+nbor.val},0) return unitsGet(sum) break case 'mult':let prod=nbors.reduce((tot,nbor)=>{return nbor.emptyQ?tot:tot*nbor.val},1) return unitsGet(prod) break default:return 0}} function queueFill(){console.log('queueMake') let queue=queueVals() shuffleArray(queue) for(let i=0;i{if(i{if(!nbor.emptyQ)emptyN++;nbor.empty();}) let score=my.scoreMults[emptyN] me.wow(score) my.score+=score document.getElementById('score').innerHTML=my.score let count=my.tiles.reduce((tot,tile)=>{return tot+(tile.emptyQ?0:1)},0) console.log('left to do: ',count) if(count<=0){success() return}}else{soundPlay('sndDrop')} if(my.moveN<=0){movesDone() return} queueShift()} function bdFull(){my.activeQ=false console.log('board full') soundPlay('sndDraw') document.getElementById('optMsg').innerHTML='End of Game: Board is Full!' optPop()} function movesDone(){my.activeQ=false console.log('moves over') soundPlay('sndDraw') let s='' s+="Game Over" s+='
' s+='

' s+="Your score is "+my.score+'' s+='

' s+='
' s+="New Game?" document.getElementById('optMsg').innerHTML=s optPop()} function success(){my.activeQ=false console.log('success') my.tiles.map(tile=>{tile.empty()}) soundPlay('sndWin') let s='' s+="Well done, you cleared the board!" s+='
' s+="Bonus 20" my.score+=20 document.getElementById('score').innerHTML=my.score s+='
' s+='

' s+="Your score is "+my.score+'' s+='

' s+='
' s+="New Game?" document.getElementById('optMsg').innerHTML=s optPop()} function unitsGet(num){return num%10} function nborsGet(tile){let nbors=[] let xn=tile.xn let yn=tile.yn let rels=[[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1],] rels.map(rel=>{let xrel=xn+rel[0] if(xrel>=0&&xrel=0&&yrel';s+='';} s+='';return s;} let seed=+new Date();function random(){let x=Math.sin(seed++)*10000;return x-Math.floor(x);} function getRandomArbitrary(min,max){return Math.random()*(max-min)+min;} function getRandomInt(min,max){return Math.floor(Math.random()*(max-min+1))+min;} function optPopHTML(){let s='';s+='
';s+='
';s+='
';s+='Size: ';s+=getDropdownHTML(my.bdSzs,'','bdSzs',0);s+='
';s+='Type: ';s+=getDropdownHTML(my.modes,'','modes',0);s+='
';s+='
';s+='';s+='';s+='
';s+='
';return s;} function optPop(){let pop=document.getElementById('optpop');pop.style.transitionDuration="0.3s";pop.style.opacity=1;pop.style.zIndex=12;pop.style.left=(w-400)/2+'px';} function optYes(){let pop=document.getElementById('optpop');pop.style.opacity=0;pop.style.zIndex=1;pop.style.left='-999px';gameNew()} function optNo(){let pop=document.getElementById('optpop');pop.style.opacity=0;pop.style.zIndex=1;pop.style.left='-999px';} function optGet(name){var val=localStorage.getItem(`MathErase.${name}`) if(val==null)val=my.opts[name] return val} function optSet(name,val){localStorage.setItem(`MathErase.${name}`,val) my.opts[name]=val} function getDropdownHTML(opts,funcName,id,chkNo){let s='';s+='';return s;} function soundBtnHTML(){let onClr='blue' let offClr='#bbb' let s='' s+='' s+='
' return s} function soundPlay(id,simulQ){if(!my.soundQ)return simulQ=typeof simulQ!=='undefined'?simulQ:false if(simulQ){if(id.length>0)document.getElementById(id).play()}else{my.snds.push(id) soundPlayQueue(id)}} function soundPlayQueue(id){let div=document.getElementById(my.snds[0]) div.play() div.onended=function(){my.snds.shift();if(my.snds.length>0)soundPlayQueue(my.snds[0]);};} function soundToggle(){let btn='sound' if(my.soundQ){my.soundQ=false document.getElementById(btn).classList.add("mute")}else{my.soundQ=true document.getElementById(btn).classList.remove("mute")}} class Tile{constructor(wd,ht,lt,tp){this.wd=wd;this.ht=ht;this.bgClr='#def';this.fgClr='black';this.val=0;this.emptyQ=true;this.overQ=false;let div=document.createElement("div");document.getElementById('board').appendChild(div);div.style.width=wd+'px';div.style.height=ht+'px';div.style.position='absolute';div.style.top=tp+'px';div.style.left=lt+'px';div.style.transition='all 1s ease-in-out' this.div=div;let me=this;div.addEventListener('mouseover',function(){if(!my.activeQ)return;console.log('mouseover') me.overQ=true;me.draw() my.canHoverQ=true;});div.addEventListener('mouseleave',function(){if(!my.activeQ)return;me.overQ=false;me.draw();});div.addEventListener('click',function(){if(!my.activeQ)return;me.overQ=false;update(me);});let 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);let txtBox=document.createElement("div");txtBox.style="font: 22px Arial; position: absolute; text-align: center;";txtBox.style.top=Math.floor(-(23-my.boxWd)/2)+'px';txtBox.style.left='0px';txtBox.style.width='100%';txtBox.style.height='100%';div.appendChild(txtBox);this.txtBox=txtBox;let wowBox=document.createElement("div");wowBox.style="font: 20px Arial; position: absolute; right: 2px; top: 2px; text-align: right; color: goldenrod; opacity:0;";div.appendChild(wowBox);this.wowBox=wowBox;this.draw();} wow(n){let box=this.wowBox box.style.transition='none' box.style.opacity=1 box.innerHTML='+'+n setTimeout(function(){box.style.transition='all 1s ease-in-out' box.style.opacity=0},500)} valSet(n){this.val=n;this.emptyQ=false;this.txtBox.innerHTML=n;this.draw()} empty(){this.val=0;this.emptyQ=true this.overQ=false this.txtBox.innerHTML='';this.draw()} draw(){if(this.overQ){console.trace('draw ',this.overQ);} let fgClr='#def';let bgClr=my.clrs[Math.abs(this.val)][1] if(this.val>=0){}else{fgClr='#fed';} if(this.emptyQ){bgClr=fgClr if(this.overQ){fgClr='#acf';this.txtBox.innerHTML=my.qTiles[0].val}else{this.txtBox.innerHTML=''}} let g=this.g;g.clearRect(0,0,this.wd,this.ht);let gradient=g.createRadialGradient(this.wd/2,this.wd/2,this.wd*1.09,this.wd/2,this.wd/2,this.wd*0.01);gradient.addColorStop(0,bgClr);gradient.addColorStop(0.7,fgClr);gradient.addColorStop(1,fgClr);g.fillStyle=gradient;g.strokeStyle='white';g.lineWidth=1;g.beginPath();let gap=0.2 g.rect(gap,gap,this.wd-2*gap,this.ht-2*gap);g.fill();} win(){this.bgClr='#ffe';this.draw();} setxy(lt,tp){this.div.style.left=lt+'px';this.div.style.top=tp+'px';} setLt(lt){this.div.style.transition=fastQ?'none':'all 1s ease-in-out' this.div.style.left=lt+'px';}} function shuffleArray(array){for(let i=array.length-1;i>0;i--){let j=Math.floor(Math.random()*(i+1));let temp=array[i];array[i]=array[j];array[j]=temp;}}