new file: Files/flashplayer_32_sa.exe new file: favicon.ico new file: globe.gif new file: imgs/download.png new file: imgs/zuck.jpg new file: index.html new file: other.ico new file: script.js new file: site.webmanifest new file: sitemap.html new file: styles/backround.css new file: styles/border.css new file: styles/fonts/Titillium_Web/OFL.txt new file: styles/fonts/Titillium_Web/TitilliumWeb-Black.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Bold.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-BoldItalic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-ExtraLight.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-ExtraLightItalic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Italic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Light.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-LightItalic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Regular.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-SemiBold.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-SemiBoldItalic.ttf new file: styles/fonts/webfontkit-20221027-163353/generator_config.txt new file: styles/fonts/webfontkit-20221027-163353/specimen_files/grid_12-825-55-15.css new file: styles/fonts/webfontkit-20221027-163353/specimen_files/specimen_stylesheet.css new file: styles/fonts/webfontkit-20221027-163353/stylesheet.css new file: styles/fonts/webfontkit-20221027-163353/titilliumweb-extralight-demo.html new file: styles/fonts/webfontkit-20221027-163353/titilliumweb-extralight-webfont.woff new file: styles/fonts/webfontkit-20221027-163353/titilliumweb-extralight-webfont.woff2 new file: styles/fonts/webfontkit-20221027-165950/generator_config.txt new file: styles/fonts/webfontkit-20221027-165950/specimen_files/grid_12-825-55-15.css new file: styles/fonts/webfontkit-20221027-165950/specimen_files/specimen_stylesheet.css new file: styles/fonts/webfontkit-20221027-165950/stylesheet.css new file: styles/fonts/webfontkit-20221027-165950/titilliumweb-bold-demo.html new file: styles/fonts/webfontkit-20221027-165950/titilliumweb-bold-webfont.woff new file: styles/fonts/webfontkit-20221027-165950/titilliumweb-bold-webfont.woff2 new file: styles/style.css new file: tools/2048/.gitignore new file: tools/2048/.jshintrc new file: tools/2048/CONTRIBUTING.md new file: tools/2048/LICENSE.txt new file: tools/2048/README.md new file: tools/2048/Rakefile new file: tools/2048/favicon.ico new file: tools/2048/index.html new file: tools/2048/js/animframe_polyfill.js new file: tools/2048/js/application.js new file: tools/2048/js/bind_polyfill.js new file: tools/2048/js/classlist_polyfill.js new file: tools/2048/js/game_manager.js new file: tools/2048/js/grid.js new file: tools/2048/js/html_actuator.js new file: tools/2048/js/keyboard_input_manager.js new file: tools/2048/js/local_storage_manager.js new file: tools/2048/js/tile.js new file: tools/2048/meta/apple-touch-icon.png new file: tools/webretro/cores/neocd_libretro.js new file: tools/webretro/cores/neocd_libretro.wasm new file: tools/webretro/cores/nestopia_libretro.js new file: tools/webretro/cores/nestopia_libretro.wasm new file: tools/webretro/cores/o2em_libretro.js new file: tools/webretro/cores/o2em_libretro.wasm new file: tools/webretro/cores/opera_libretro.js new file: tools/webretro/cores/opera_libretro.wasm
392 lines
30 KiB
JavaScript
392 lines
30 KiB
JavaScript
var w,h,g,my={};function sudokuMain(){my.version='0.562';w=360;h=454
|
|
my.bdSzs=[9]
|
|
my.levels=[{name:'Beginner',type:"easy",blankN:19},{name:'Medium',type:"medium",blankN:28},{name:'Challenging',type:"hard",blankN:37},{name:'Hard',type:"very-hard",blankN:46},{name:'Tough',type:"insane",blankN:55},{name:'Brutal',type:"inhuman",blankN:64},]
|
|
my.bdStyles=[{name:'simple',checkQ:false},{name:'fancy',checkQ:false}]
|
|
my.bdStyle=my.bdStyles[1];my.activeQ=false
|
|
var s='';s+=arrowBoxHTML()
|
|
s+='<style>'
|
|
s+='.btn { display: inline-block; position: relative; text-align: center; margin: 2px; text-decoration: none; font: 15px/25px Arial, sans-serif; color: #268; border: 1px solid #88aaff; border-radius: 10px;cursor: pointer; background: linear-gradient(to top right, rgba(170,190,255,1) 0%, rgba(255,255,255,1) 100%); outline-style:none;}'
|
|
s+='.btn:hover { background: linear-gradient(to top, rgba(255,255,0,1) 0%, rgba(255,255,255,1) 100%); }'
|
|
s+='.yy { border: solid 2px #eeeeaa; background: linear-gradient(to top, rgba(255,220,130,1) 0%, rgba(255,255,255,1) 100%); }'
|
|
s+='.hi { border: solid 2px #eeeeaa; background: linear-gradient(to top, rgba(130,220,255,1) 0%, rgba(255,255,255,1) 100%); box-shadow: 2px 2px 6px #66a; }'
|
|
s+='.lo { border: solid 1px #888888; background: linear-gradient(to top, rgba(170,170,170,1) 0%, rgba(205,205,205,1) 100%); }'
|
|
s+='</style>'
|
|
my.sndHome=(document.domain=='localhost')?'/mathsisfun/images/sounds/':'/images/sounds/'
|
|
s+='<audio id="sndWin" src="'+my.sndHome+'kids-cheer.mp3" preload="auto"></audio>';s+='<audio id="sndPlace" src="'+my.sndHome+'click1.mp3" preload="auto"></audio>';s+='<audio id="sndClear" src="'+my.sndHome+'pheew.mp3" preload="auto"></audio>';my.snds=[];s+='<div id="main" style="position:relative; width:'+w+'px; min-height:'+h+'px; background-xnor: white; margin:auto; display:block; border: none; border-radius: 10px;">';s+='<div id="top" style="font: 24px Arial; text-align:left; margin:3px; height:34px;">'
|
|
s+='<div id="btns" style="position:absolute; left: 3px; font: 18px Arial; width:99%;">'
|
|
s+='<button type="button" style="z-index:2;" class="btn" onclick="optPop()">Options</button>'
|
|
s+='<button type="button" style="z-index:2;" class="btn" onclick="gameNew()">New Game</button>'
|
|
s+='<button type="button" style="z-index:2;" class="btn" onclick="gameSolve()">Solve</button>'
|
|
s+='<button type="button" style="z-index:2;" class="btn" onclick="gameReset()">Reset</button>'
|
|
my.soundQ=true
|
|
s+=' '
|
|
s+=soundBtnHTML()
|
|
s+='<br>'
|
|
s+='<button type="button" style="z-index:2; margin-top:7px;" class="btn" onclick="gameUndo()">Undo</button>'
|
|
s+='<button type="button" style="z-index:2; margin-top:7px; float:right;" class="btn" onclick="gameSolveCheck()">Check</button>'
|
|
s+='</div>'
|
|
s+='</div>'
|
|
s+='<div id="msg" style="font: 24px Arial; text-align:center; padding-top:5px; height:30px; background-color:#ffffe8; border-radius: 10px;">?</div>'
|
|
s+='<canvas id="canvas1" style="position: absolute; width:'+w+'px; height:'+w+'px; left: 0px; top: 0px; border: none; pointer-events: none; z-index:2;"></canvas>';s+='<div id="board" style=""></div>';s+='<div id="ansBox" class="arrowTop" style="position: absolute; left: 50px; top: 6px; visibility: hidden; z-index:3;"></div>';s+=optPopHTML();s+='<canvas id="timercanvas" width="100" height="100" style="z-index:2; width:100px;"></canvas>';s+='<div id="copyrt" style="font: 11px Arial; color: #6600cc; position:absolute; bottom:5px; left:5px; text-align:center;">© 2019 MathsIsFun.com v'+my.version+'</div>';s+='</div>';document.write(s);var el=document.getElementById('canvas1');var ratio=3;el.width=w*ratio;el.height=h*ratio;el.style.width=w+"px";el.style.height=h+"px";g=el.getContext("2d");g.setTransform(ratio,0,0,ratio,0,0);my.clrs=[["Blue",'#0000FF'],["Red",'#FF0000'],["Black",'#000000'],["Green",'#00cc00'],["Orange",'#FFA500'],["Slate Blue",'#6A5ACD'],["Lime",'#00FF00'],["Spring Green",'#00FF7F'],["Teal",'#008080'],["Gold",'#ffd700'],["Med Purple",'#aa00aa'],["Light Blue",'#ADD8E6'],["Navy",'#000080'],["Purple",'#800080'],["Dark SeaGreen",'#8FBC8F']];my.clrNum=0;my.game=new Sudoku()
|
|
my.hintQ=false
|
|
my.clrNumQ=false
|
|
my.bd=[]
|
|
optPop()}
|
|
function gameNew(){my.bdSz=9
|
|
bdMake()
|
|
document.getElementById('ansBox').style.visibility='hidden';my.hist=[]
|
|
var levelStr=document.querySelector('input[name="level"]:checked').value
|
|
my.level=my.levels[0]
|
|
for(var i=0;i<my.levels.length;i++){var level=my.levels[i]
|
|
if(level.name==levelStr){my.level=my.levels[i]
|
|
break}}
|
|
console.log('gameNew',levelStr,my.level)
|
|
var starttime=performance.now()
|
|
var blankN=my.level.blankN
|
|
var uniq=uniquePuzzleGen(blankN)
|
|
uniq=uniq.join('').split(',').join('')
|
|
console.log('unique: '+uniq);var bdStr=uniq
|
|
var elapsed=performance.now()-starttime;console.log('Solver elapsed time: '+elapsed+'ms');var n=0
|
|
for(var i=0;i<9;i++){for(var j=0;j<9;j++){var val=bdStr.charAt(n++)
|
|
var tile=my.bd[i][j]
|
|
if(val>=1&&val<=9){tile.val=val
|
|
tile.origQ=true}}}
|
|
bdCandUpdate()
|
|
bdDraw()
|
|
my.activeQ=true
|
|
msg('New game')}
|
|
function bdCandUpdate(){for(var i=0;i<9;i++){for(var j=0;j<9;j++){var tile=my.bd[i][j]
|
|
var cands=[1,2,3,4,5,6,7,8,9]
|
|
if(tile.val==''){for(var k=0;k<9;k++){var index=cands.indexOf(parseInt(my.bd[i][k].val))
|
|
if(index>-1)cands.splice(index,1)}
|
|
for(var k=0;k<9;k++){var index=cands.indexOf(parseInt(my.bd[k][j].val))
|
|
if(index>-1)cands.splice(index,1)}
|
|
var iStt=parseInt(i/3)*3
|
|
var jStt=parseInt(j/3)*3
|
|
for(var k=iStt;k<iStt+3;k++){for(var l=jStt;l<jStt+3;l++){var index=cands.indexOf(parseInt(my.bd[k][l].val))
|
|
if(index>-1)cands.splice(index,1)}}
|
|
var was=tile.cands.join()
|
|
tile.cands=cands
|
|
if(was!=cands.join()){tile.draw()}}}}}
|
|
function gameSolve(){var bdStr=''
|
|
for(var i=0;i<9;i++){for(var j=0;j<9;j++){var tile=my.bd[i][j]
|
|
if(tile.origQ){bdStr+=tile.val}else{bdStr+='.'}}}
|
|
var soln=my.game.solve(bdStr)
|
|
console.log('gameSolve',bdStr)
|
|
console.log('gameSolve',soln)
|
|
console.log('gameSolve',gameSolvable())
|
|
var bdStr=soln
|
|
var n=0
|
|
for(var i=0;i<9;i++){for(var j=0;j<9;j++){var val=bdStr.charAt(n++)
|
|
var tile=my.bd[i][j]
|
|
if(val>=1&&val<=9){tile.val=val
|
|
tile.draw()}}}
|
|
msg('Solution')
|
|
my.activeQ=false}
|
|
function gameSolvable(){var bdStr=bdString(my.bd,false)
|
|
var soln=my.game.solve(bdStr)
|
|
return(!!soln)}
|
|
function gameWinCheck(){var bdStr=bdString(my.bd,false)
|
|
var n=0
|
|
for(var i=0;i<bdStr.length;i++){var c=bdStr.charAt(i)
|
|
if(c>=1&&c<=9){}else{n++}}
|
|
if(n<5){msg(n+' left to go')}else{msg('')}
|
|
if(n==0){if(gameSolvable()){msg('You win!','gold')
|
|
soundPlay('sndWin')}else{msg('(not solved)','red')}}}
|
|
function gameSolveCheck(){msg(gameSolvable()?'Solvable':'Not Solvable')}
|
|
function gameReset(){for(var i=0;i<9;i++){for(var j=0;j<9;j++){var tile=my.bd[i][j]
|
|
if(!tile.origQ){tile.val=''
|
|
tile.draw()}}}
|
|
msg('Reset')
|
|
my.activeQ=true}
|
|
function gameUndo(){if(!my.activeQ)return
|
|
var step=my.hist.pop()
|
|
if(step){var tile=my.bd[step.xn][step.yn]
|
|
tile.valSet(step.was,false)}
|
|
gameWinCheck()
|
|
bdCandUpdate()}
|
|
function msg(s,clr){clr=typeof clr!=='undefined'?clr:'black'
|
|
var div=document.getElementById('msg')
|
|
div.innerHTML=s
|
|
div.style.color=clr}
|
|
function bdMake(){my.border=1
|
|
my.boxWd=Math.min(70,(Math.min(w-my.border*5,h-90))/my.bdSz)
|
|
my.borderTp=75
|
|
my.borderLt=(w-my.bdSz*my.boxWd)/2+my.border
|
|
var myNode=document.getElementById("board");while(myNode.firstChild){myNode.removeChild(myNode.firstChild);}
|
|
my.bd=[]
|
|
for(var xn=0;xn<my.bdSz;xn++){my.bd[xn]=[]
|
|
for(var yn=0;yn<my.bdSz;yn++){var tile=new Tile(my.boxWd,my.boxWd,xn,yn)
|
|
tile.xn=xn;tile.yn=yn;my.bd[xn][yn]=tile}}}
|
|
function bdDraw(){if(my.bd.length==0)return
|
|
for(var i=0;i<9;i++){for(var j=0;j<9;j++){var tile=my.bd[i][j]
|
|
tile.draw()}}
|
|
g.strokeStyle='#6aa'
|
|
g.lineWidth=2
|
|
g.fillStyle='#abc'
|
|
var wd=my.boxWd*3
|
|
for(var i=0;i<3;i++){var xp=boxLeft(i*3)
|
|
for(var j=0;j<3;j++){var yp=boxTop(j*3)
|
|
g.beginPath()
|
|
g.rect(xp,yp,wd,wd)
|
|
g.stroke()}}
|
|
g.strokeStyle='black'
|
|
g.fillStyle='black'
|
|
g.beginPath()
|
|
g.rect(boxLeft(0)-my.border,boxTop(0)-my.border,my.boxWd*9+my.border*2,my.boxWd*9+my.border*2)
|
|
g.stroke()}
|
|
function boxLeft(xn){return my.borderLt+my.boxWd*xn}
|
|
function boxTop(yn){return my.borderTp+my.boxWd*yn}
|
|
function arrowBoxHTML(){var s='';var bgClr='#cdf'
|
|
var borderClr='darkblue'
|
|
s+='<style type="text/css">';for(var i=0;i<2;i++){var classStr=(i==0)?'.arrowTop':'.arrowBot'
|
|
var topStr=(i==0)?'bottom':'top'
|
|
s+=classStr+' {position: relative; border: 2px solid '+borderClr+'; background: '+bgClr+'; width:98px; }';s+=classStr+':after, '+classStr+':before {'+topStr+': 100%; left: 50%; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none; }';s+=classStr+':after {border-color: rgba(0, 0, 0, 0); border-'+topStr+'-color: '+bgClr+'; border-width: 30px; margin-left: -29px; }';s+=classStr+':before {border-color: rgba(0, 0, 0, 0); border-'+topStr+'-color: '+borderClr+'; border-width: 32px; margin-left: -31px; }';}
|
|
s+='</style>';return s;}
|
|
function showOpts(me){var div=document.getElementById('ansBox')
|
|
if(me.origQ){div.style.visibility='hidden';return}
|
|
div.style.left=(boxLeft(me.xn-0.67))+'px'
|
|
if(me.yn<1){div.style.top=(boxTop(me.yn+1.5))+'px'
|
|
div.classList.remove("arrowBot")
|
|
div.classList.add("arrowTop")}else{div.style.top=(boxTop(me.yn-2.9))+'px'
|
|
div.classList.remove("arrowTop")
|
|
div.classList.add("arrowBot")}
|
|
div.style.visibility='visible';var s='';var anss=['-','-','X',1,2,3,4,5,6,7,8,9];var n=0;for(var i=0;i<4;i++){s+='<div style="font: 18px Verdana;">';for(var j=0;j<3;j++){var id=me.xn+'-'+me.yn+'-'+anss[n];s+='<div id="'+id+'" style="display: inline-block; width:30px; height:24px; line-height:24px; text-align: center; border: 1px solid white; cursor:pointer;" onmousedown="doAns(this)">';var ans=anss[n]
|
|
if(ans=='-')ans=' '
|
|
s+=ans
|
|
s+='</div>';n++;}
|
|
s+='</div>';}
|
|
div.innerHTML=s;}
|
|
function getChoices(xn,yn){var keys=[1,2,3,4,5,6,7,8,9];var choices=candFill(xn,yn)
|
|
for(var i=0;i<9;i++){if(choices.indexOf(keys[i])==-1){keys[i]='-'}}
|
|
return keys}
|
|
function bdString(bd,origQ){var s=''
|
|
for(var i=0;i<9;i++){for(var j=0;j<9;j++){var val=bd[i][j].val
|
|
if(origQ&&!bd[i][j].origQ){val='.'}else{if(val>=1&&val<=9){}else{val='.'}}
|
|
s+=val}}
|
|
return s}
|
|
function candFill(xn,yn){var starttime=performance.now()
|
|
var alpha='ABCDEFGHI'
|
|
var id=alpha.charAt(xn)+(yn+1)
|
|
var bdStr=bdString(my.bd)
|
|
my.cands=my.game._get_candidates_map(bdStr);console.log('my.cands',id,my.cands[id],my.cands)
|
|
var elapsed=performance.now()-starttime;console.log('Cand elapsed time: '+elapsed+'ms');return my.cands[id]}
|
|
function doAns(me){var ids=me.id.split('-');var xn=ids[0]
|
|
var yn=ids[1]
|
|
var tile=my.bd[xn][yn]
|
|
var div=document.getElementById('ansBox')
|
|
div.style.visibility='hidden';var val=ids[2]
|
|
if(val>=1&&val<=9)tile.valSet(val)
|
|
if(val=='')tile.valSet(val)
|
|
gameWinCheck()
|
|
bdCandUpdate()}
|
|
function radioHTML(prompt,id,lbls,func){var s='';s+='<div style="font: bold 16px Arial;">';s+=prompt;s+='</div>';s+='<div style="display:inline-block; border: 1px solid white; border-radius:5px; padding:3px; margin:3px; background-xnor:rgba(255,255,255,0.5);">';for(var i=0;i<lbls.length;i++){var lbl=lbls[i].name
|
|
var idi=id+i;var chkStr=(i==0)?' checked ':'';s+='<input id="'+idi+'" type="radio" name="'+id+'" value="'+lbl+'" onclick="'+func+'('+i+');" autocomplete="off" '+chkStr+' >';s+='<label for="'+idi+'">'+lbl+' </label>';}
|
|
s+='</div>';return s;}
|
|
function optPopHTML(){var s='';s+='<div id="optpop" style="position:absolute; left:-500px; top:20px; width:320px; padding: 5px; border-radius: 9px; font:14px Arial; background-color: #bcd; box-shadow: 10px 10px 5px 0px rgba(40,40,40,0.75); transition: all linear 0.3s; opacity:0; text-align: center; ">';s+='<div style="position:relative; margin:auto; background-color:lightblue; margin: 5px 0 1px 0; padding: 5px 0 5px 0;">';s+=radioHTML('Level:','level',my.levels,'');s+='</div>'
|
|
s+='<div style="position:relative; margin:auto; background-color:lightblue; margin: 5px 0 1px 0; padding: 5px 0 5px 0;">';s+='<button type="button" id="hintBtn" style="z-index:2;" class="btn lo" onclick="hintToggle()">Hints</button>'
|
|
s+='<button type="button" id="clrNumBtn" style="z-index:2;" class="btn lo" onclick="clrNumToggle()">Colored Numbers</button>'
|
|
s+='</div>'
|
|
s+='<div style="float:right; margin: 0 0 5px 10px; font:16px Arial;">';s+='New game? '
|
|
s+='<button id="optYes" onclick="optYes()" style="z-index:2; font: 22px Arial;" class="btn" >✔</button>';s+=' '
|
|
s+='<button onclick="optNo()" style="z-index:2; font: 22px Arial;" class="btn" >✘</button>';s+='</div>';s+='</div>';return s;}
|
|
function optPop(){var pop=document.getElementById('optpop');pop.style.transitionDuration="0.3s";pop.style.opacity=1;pop.style.zIndex=12;pop.style.left=(w-340)/2+'px';}
|
|
function optYes(){var pop=document.getElementById('optpop');pop.style.opacity=0;pop.style.zIndex=1;pop.style.left='-999px';gameNew()}
|
|
function optNo(){var pop=document.getElementById('optpop');pop.style.opacity=0;pop.style.zIndex=1;pop.style.left='-999px';}
|
|
function soundBtnHTML(){var onClr='blue'
|
|
var offClr='#bbb'
|
|
var s=''
|
|
s+='<style> '
|
|
s+=' .speaker { height: 30px; width: 30px; position: relative; overflow: hidden; display: inline-block; vertical-align:top; } '
|
|
s+=' .speaker span { display: block; width: 9px; height: 9px; background-color:'+onClr+'; margin: 10px 0 0 1px; }'
|
|
s+=' .speaker span:after { content: ""; position: absolute; width: 0; height: 0; border-style: solid; border-color: transparent '+onClr+' transparent transparent; border-width: 10px 16px 10px 15px; left: -13px; top: 5px; }'
|
|
s+=' .speaker span:before { transform: rotate(45deg); border-radius: 0 60px 0 0; content: ""; position: absolute; width: 5px; height: 5px; border-style: double; border-color:'+onClr+'; border-width: 7px 7px 0 0; left: 18px; top: 9px; transition: all 0.2s ease-out; }'
|
|
s+=' .speaker:hover span:before { transform: scale(.8) translate(-3px, 0) rotate(42deg); }'
|
|
s+=' .speaker.mute span:before { transform: scale(.5) translate(-15px, 0) rotate(36deg); opacity: 0; }'
|
|
s+=' .speaker.mute span { background-color:'+offClr+'; }'
|
|
s+=' .speaker.mute span:after {border-color: transparent '+offClr+' transparent '+offClr+';}'
|
|
s+=' </style>'
|
|
s+='<div id="sound" onClick="soundToggle()" class="speaker"><span></span></div>'
|
|
return s}
|
|
function hintToggle(){my.hintQ=!my.hintQ;toggleBtn("hintBtn",my.hintQ);bdDraw()}
|
|
function clrNumToggle(){my.clrNumQ=!my.clrNumQ;toggleBtn("clrNumBtn",my.clrNumQ);bdDraw()}
|
|
function toggleBtn(btn,onq){if(onq){document.getElementById(btn).classList.add("hi");document.getElementById(btn).classList.remove("lo");}else{document.getElementById(btn).classList.add("lo");document.getElementById(btn).classList.remove("hi");}}
|
|
function soundPlay(name,simulQ){if(!my.soundQ)return
|
|
simulQ=typeof simulQ!=='undefined'?simulQ:true
|
|
if(simulQ){if(name.length>0){var div=document.getElementById(name)
|
|
if(div.currentTime>0&&div.currentTime<div.duration){console.log('soundPlay cloned',div.currentTime,div.duration)
|
|
div.cloneNode(true).play()}else{div.play()}}}else{my.snds.push(name)
|
|
soundPlayQueue()}}
|
|
function soundPlayQueue(){var div=document.getElementById(my.snds[0])
|
|
div.play()
|
|
div.onended=function(){my.snds.shift();if(my.snds.length>0)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 Timer(g,rad,secs,clr,funcEnd){this.g=g;this.rad=rad;this.secs=secs;this.clr=clr;this.funcEnd=funcEnd;this.x=rad;this.y=rad;this.stt=performance.now();this.stopQ=false;}
|
|
Timer.prototype.update=function(){};Timer.prototype.restart=function(secs){this.secs=secs;this.stt=performance.now();this.stopQ=false;requestAnimationFrame(this.draw.bind(this));};Timer.prototype.more=function(secs){this.stt+=secs*1000;};Timer.prototype.stop=function(){this.stopQ=true;};Timer.prototype.draw=function(){if(this.stopQ)return;var now=performance.now();var elapsed=now-this.stt;var ratio=Math.min(1,elapsed/this.secs/1000);var g=this.g;g.beginPath();g.fillStyle="#def";g.arc(this.x,this.y,this.rad,0,2*Math.PI);g.fill();g.beginPath();g.moveTo(this.x,this.y);g.fillStyle=this.clr;g.arc(this.x,this.y,this.rad,-Math.PI/2,ratio*2*Math.PI-Math.PI/2);g.fill();if(ratio<1){requestAnimationFrame(this.draw.bind(this));}else{this.funcEnd();}};function Tile(wd,ht,xn,yn){this.wd=wd
|
|
this.ht=ht
|
|
this.xn=xn
|
|
this.yn=yn
|
|
this.bgClr='#fef'
|
|
this.fgClr='black'
|
|
this.val=''
|
|
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 me=this
|
|
div.addEventListener('mouseover',function(){if(!my.activeQ)return})
|
|
div.addEventListener('mouseleave',function(){if(!my.activeQ)return})
|
|
div.addEventListener('click',function(){if(!my.activeQ)return
|
|
showOpts(me)})
|
|
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.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=this.origQ?'black':'orange'
|
|
if(this.val>=1&&this.val<=9){this.drawNum(this.val,fgClr)}else{this.drawHints('#444')}}
|
|
Tile.prototype.drawHints=function(clr){var g=this.g
|
|
g.clearRect(0,0,this.wd,this.ht)
|
|
if(my.hintQ){for(var i=0;i<this.cands.length;i++){var cand=this.cands[i]
|
|
var n=cand-1
|
|
var nx=(n%3)
|
|
var ny=parseInt(n/3)
|
|
g.fillStyle=clr
|
|
g.font="12px Arial";g.beginPath()
|
|
g.fillText(cand,5+nx*11,14+ny*11)
|
|
g.fill()}}}
|
|
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="21px Arial";g.beginPath()
|
|
g.fillText(v,15,28)
|
|
g.fill()}
|
|
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';}
|
|
function Sudoku(){this.DIGITS="123456789";this.ROWS="ABCDEFGHI";this.COLS=this.DIGITS;this.SQUARES=null;this.UNITS=null;this.SQUARE_UNITS_MAP=null;this.SQUARE_PEERS_MAP=null;this.MIN_GIVENS=17;this.NR_SQUARES=81;this.DIFFICULTY={"easy":62,"medium":53,"hard":44,"very-hard":35,"insane":26,"inhuman":17,};this.BLANK_CHAR='.';this.BLANK_BOARD="...................................................."+
|
|
".............................";this.SQUARES=this._cross(this.ROWS,this.COLS);this.UNITS=this._get_all_units(this.ROWS,this.COLS);this.SQUARE_UNITS_MAP=this._get_square_units_map(this.SQUARES,this.UNITS);this.SQUARE_PEERS_MAP=this._get_square_peers_map(this.SQUARES,this.SQUARE_UNITS_MAP);}
|
|
Sudoku.prototype.generate=function(difficulty,unique){if(typeof difficulty==="string"||typeof difficulty==="undefined"){difficulty=this.DIFFICULTY[difficulty]||this.DIFFICULTY.easy;}
|
|
difficulty=this._force_range(difficulty,this.NR_SQUARES+1,this.MIN_GIVENS);unique=unique||true;var blank_board="";for(var i=0;i<this.NR_SQUARES;++i){blank_board+='.';}
|
|
var candidates=this._get_candidates_map(blank_board);var shuffled_squares=this._shuffle(this.SQUARES);for(var si in shuffled_squares){var square=shuffled_squares[si];var rand_candidate_idx=this._rand_range(candidates[square].length);var rand_candidate=candidates[square][rand_candidate_idx];if(!this._assign(candidates,square,rand_candidate)){break;}
|
|
var single_candidates=[];for(var si in this.SQUARES){var square=this.SQUARES[si];if(candidates[square].length==1){single_candidates.push(candidates[square]);}}
|
|
if(single_candidates.length>=difficulty&&this._strip_dups(single_candidates).length>=8){var board="";var givens_idxs=[];for(var i in this.SQUARES){var square=this.SQUARES[i];if(candidates[square].length==1){board+=candidates[square];givens_idxs.push(i);}else{board+=this.BLANK_CHAR;}}
|
|
var nr_givens=givens_idxs.length;if(nr_givens>difficulty){givens_idxs=this._shuffle(givens_idxs);for(var i=0;i<nr_givens-difficulty;++i){var target=parseInt(givens_idxs[i]);board=board.substr(0,target)+this.BLANK_CHAR+
|
|
board.substr(target+1);}}
|
|
if(this.solve(board)){console.log('board',board,candidates)
|
|
return board;}}}
|
|
return this.generate(difficulty);};Sudoku.prototype.solve=function(board,reverse){var report=this.validate_board(board);if(report!==true){throw report;}
|
|
var nr_givens=0;for(var i in board){if(board[i]!==this.BLANK_CHAR&&this._in(board[i],this.DIGITS)){++nr_givens;}}
|
|
if(nr_givens<this.MIN_GIVENS){throw "Too few givens. Minimum givens is "+this.MIN_GIVENS;}
|
|
reverse=reverse||false;var candidates=this._get_candidates_map(board);var result=this._search(candidates,reverse);if(result){var solution="";for(var square in result){solution+=result[square];}
|
|
return solution;}
|
|
return false;};Sudoku.prototype.get_candidates=function(board){var report=this.validate_board(board);if(report!==true){throw report;}
|
|
var candidates_map=this._get_candidates_map(board);if(!candidates_map){return false;}
|
|
var rows=[];var cur_row=[];var i=0;for(var square in candidates_map){var candidates=candidates_map[square];cur_row.push(candidates);if(i%9==8){rows.push(cur_row);cur_row=[];}
|
|
++i;}
|
|
return rows;}
|
|
Sudoku.prototype._get_candidates_map=function(board){var report=this.validate_board(board);if(report!==true){throw report;}
|
|
var candidate_map={};var squares_values_map=this._get_square_vals_map(board);for(var si in this.SQUARES){candidate_map[this.SQUARES[si]]=this.DIGITS;}
|
|
for(var square in squares_values_map){var val=squares_values_map[square];if(this._in(val,this.DIGITS)){var new_candidates=this._assign(candidate_map,square,val);if(!new_candidates){return false;}}}
|
|
return candidate_map;};Sudoku.prototype._search=function(candidates,reverse){if(!candidates){return false;}
|
|
reverse=reverse||false;var max_nr_candidates=0;var max_candidates_square=null;for(var si in this.SQUARES){var square=this.SQUARES[si];var nr_candidates=candidates[square].length;if(nr_candidates>max_nr_candidates){max_nr_candidates=nr_candidates;max_candidates_square=square;}}
|
|
if(max_nr_candidates===1){return candidates;}
|
|
var min_nr_candidates=10;var min_candidates_square=null;for(si in this.SQUARES){var square=this.SQUARES[si];var nr_candidates=candidates[square].length;if(nr_candidates<min_nr_candidates&&nr_candidates>1){min_nr_candidates=nr_candidates;min_candidates_square=square;}}
|
|
var min_candidates=candidates[min_candidates_square];if(!reverse){for(var vi in min_candidates){var val=min_candidates[vi];var candidates_copy=JSON.parse(JSON.stringify(candidates));var candidates_next=this._search(this._assign(candidates_copy,min_candidates_square,val));if(candidates_next){return candidates_next;}}}else{for(var vi=min_candidates.length-1;vi>=0;--vi){var val=min_candidates[vi];var candidates_copy=JSON.parse(JSON.stringify(candidates));var candidates_next=this._search(this._assign(candidates_copy,min_candidates_square,val),reverse);if(candidates_next){return candidates_next;}}}
|
|
return false;};Sudoku.prototype._assign=function(candidates,square,val){var other_vals=candidates[square].replace(val,"");for(var ovi in other_vals){var other_val=other_vals[ovi];var candidates_next=this._eliminate(candidates,square,other_val);if(!candidates_next){return false;}}
|
|
return candidates;};Sudoku.prototype._eliminate=function(candidates,square,val){if(!this._in(val,candidates[square])){return candidates;}
|
|
candidates[square]=candidates[square].replace(val,'');var nr_candidates=candidates[square].length;if(nr_candidates===1){var target_val=candidates[square];for(var pi in this.SQUARE_PEERS_MAP[square]){var peer=this.SQUARE_PEERS_MAP[square][pi];var candidates_new=this._eliminate(candidates,peer,target_val);if(!candidates_new){return false;}}}
|
|
if(nr_candidates===0){return false;}
|
|
for(var ui in this.SQUARE_UNITS_MAP[square]){var unit=this.SQUARE_UNITS_MAP[square][ui];var val_places=[];for(var si in unit){var unit_square=unit[si];if(this._in(val,candidates[unit_square])){val_places.push(unit_square);}}
|
|
if(val_places.length===0){return false;}else if(val_places.length===1){var candidates_new=this._assign(candidates,val_places[0],val);if(!candidates_new){return false;}}}
|
|
return candidates;};Sudoku.prototype._get_square_vals_map=function(board){var squares_vals_map={};if(board.length!=this.SQUARES.length){throw "Board/squares length mismatch.";}else{for(var i in this.SQUARES){squares_vals_map[this.SQUARES[i]]=board[i];}}
|
|
return squares_vals_map;};Sudoku.prototype._get_square_units_map=function(squares,units){var square_unit_map={};for(var si in squares){var cur_square=squares[si];var cur_square_units=[];for(var ui in units){var cur_unit=units[ui];if(cur_unit.indexOf(cur_square)!==-1){cur_square_units.push(cur_unit);}}
|
|
square_unit_map[cur_square]=cur_square_units;}
|
|
return square_unit_map;};Sudoku.prototype._get_square_peers_map=function(squares,units_map){var square_peers_map={};for(var si in squares){var cur_square=squares[si];var cur_square_units=units_map[cur_square];var cur_square_peers=[];for(var sui in cur_square_units){var cur_unit=cur_square_units[sui];for(var ui in cur_unit){var cur_unit_square=cur_unit[ui];if(cur_square_peers.indexOf(cur_unit_square)===-1&&cur_unit_square!==cur_square){cur_square_peers.push(cur_unit_square);}}}
|
|
square_peers_map[cur_square]=cur_square_peers;}
|
|
return square_peers_map;};Sudoku.prototype._get_all_units=function(rows,cols){var units=[];for(var ri in rows){units.push(this._cross(rows[ri],cols));}
|
|
for(var ci in cols){units.push(this._cross(rows,cols[ci]));}
|
|
var row_squares=["ABC","DEF","GHI"];var col_squares=["123","456","789"];for(var rsi in row_squares){for(var csi in col_squares){units.push(this._cross(row_squares[rsi],col_squares[csi]));}}
|
|
return units;};Sudoku.prototype.board_string_to_grid=function(board_string){var rows=[];var cur_row=[];for(var i in board_string){cur_row.push(board_string[i]);if(i%9==8){rows.push(cur_row);cur_row=[];}}
|
|
return rows;};Sudoku.prototype.board_grid_to_string=function(board_grid){var board_string="";for(var r=0;r<9;++r){for(var c=0;c<9;++c){board_string+=board_grid[r][c];}}
|
|
return board_string;};Sudoku.prototype.print_board=function(board){var report=this.validate_board(board);if(report!==true){throw report;}
|
|
var V_PADDING=" ";var H_PADDING='\n';var V_BOX_PADDING=" ";var H_BOX_PADDING='\n';var display_string="";for(var i in board){var square=board[i];display_string+=square+V_PADDING;if(i%3===2){display_string+=V_BOX_PADDING;}
|
|
if(i%9===8){display_string+=H_PADDING;}
|
|
if(i%27===26){display_string+=H_BOX_PADDING;}}
|
|
console.log(display_string);};Sudoku.prototype.validate_board=function(board){if(!board){return "Empty board";}
|
|
if(board.length!==this.NR_SQUARES){return "Invalid board size. Board must be exactly "+this.NR_SQUARES+" squares.";}
|
|
for(var i in board){if(!this._in(board[i],this.DIGITS)&&board[i]!==this.BLANK_CHAR){return "Invalid board character encountered at index "+i+
|
|
": "+board[i];}}
|
|
return true;};Sudoku.prototype._cross=function(a,b){var result=[];for(var ai in a){for(var bi in b){result.push(a[ai]+b[bi]);}}
|
|
return result;};Sudoku.prototype._in=function(v,seq){return seq.indexOf(v)!==-1;};Sudoku.prototype._first_true=function(seq){for(var i in seq){if(seq[i]){return seq[i];}}
|
|
return false;};Sudoku.prototype._shuffle=function(seq){var shuffled=[];for(var i=0;i<seq.length;++i){shuffled.push(false);}
|
|
for(var i in seq){var ti=this._rand_range(seq.length);while(shuffled[ti]){ti=(ti+1)>(seq.length-1)?0:(ti+1);}
|
|
shuffled[ti]=seq[i];}
|
|
return shuffled;};Sudoku.prototype._rand_range=function(max,min){min=min||0;if(max){return Math.floor(Math.random()*(max-min))+min;}else{throw "Range undefined";}};Sudoku.prototype._strip_dups=function(seq){var seq_set=[];var dup_map={};for(var i in seq){var e=seq[i];if(!dup_map[e]){seq_set.push(e);dup_map[e]=true;}}
|
|
return seq_set;};Sudoku.prototype._force_range=function(nr,max,min){min=min||0
|
|
nr=nr||0
|
|
if(nr<min){return min;}
|
|
if(nr>max){return max;}
|
|
return nr}
|
|
function emptyCellCoordinatesGen(puzz){var emptyCells=[];for(var i=0;i<9;i++){for(var j=0;j<9;j++){if(puzz[i][j]===0)
|
|
emptyCells.push([i,j]);}}
|
|
return emptyCells;}
|
|
function emptyPuzzleGenerator(){var emptyPuzz=[];for(var i=0;i<9;i++){emptyPuzz[i]=[];for(var j=0;j<9;j++){emptyPuzz[i][j]=0;}}
|
|
return emptyPuzz;}
|
|
var stdSolveArray=[1,2,3,4,5,6,7,8,9];function shuffleArray(arr){arr=arr.slice();var randomArray=[];var arrLength=arr.length;while(randomArray.length<arrLength){var randomIndex=Math.floor(Math.random()*arr.length);randomArray.push(arr.splice(randomIndex,1)[0]);}
|
|
return randomArray;}
|
|
function isUnique(puzz){var origSolution=solve(false,stdSolveArray,puzz);for(var i=0;i<=10;i++){var newSolution=solve(false,shuffleArray(stdSolveArray),puzz);if(origSolution.toString()!=newSolution.toString())
|
|
return false;}
|
|
return true;}
|
|
function uniquePuzzleGen(emptyN,startPuzzle){if(!startPuzzle){startPuzzle=emptyPuzzleGenerator();}
|
|
var randomPuzzle=solve(true,[],startPuzzle);var randomCoordinates=shuffleArray(emptyCellCoordinatesGen(emptyPuzzleGenerator()));var n=0
|
|
while(randomCoordinates.length>0&&n<emptyN){var temp=randomPuzzle[randomCoordinates[0][0]][randomCoordinates[0][1]];randomPuzzle[randomCoordinates[0][0]][randomCoordinates[0][1]]=0;if(!isUnique(randomPuzzle)){randomPuzzle[randomCoordinates[0][0]][randomCoordinates[0][1]]=temp;}
|
|
randomCoordinates.shift();n++}
|
|
return randomPuzzle;}
|
|
function clonePuzzle(puzz){var clonedPuzz=[];for(var i=0;i<puzz.length;i++){clonedPuzz.push(puzz[i].slice(0));}
|
|
return clonedPuzz;}
|
|
function solve(randomize,solveArray,puzz1){var puzz=clonePuzzle(puzz1);function inRow(num,rowIndex){return puzz[rowIndex].indexOf(num)>-1;}
|
|
function inCol(num,colIndex){var col=[];puzz.forEach(function(row){col.push(row[colIndex]);});return col.indexOf(num)>-1;}
|
|
function inBox(num,rowIndex,colIndex){var boxTopLeftCoordinates=[[0,0],[0,3],[0,6],[3,0],[3,3],[3,6],[6,0],[6,3],[6,6]];var correspondingBox=boxTopLeftCoordinates.filter(function(box){return(rowIndex>=box[0]&&rowIndex<box[0]+3)&&(colIndex>=box[1]&&colIndex<box[1]+3);});var boxArray=[];for(var i=correspondingBox[0][0];i<=correspondingBox[0][0]+2;i++){for(var j=correspondingBox[0][1];j<=correspondingBox[0][1]+2;j++){boxArray.push(puzz[i][j]);}}
|
|
return boxArray.indexOf(num)>-1;}
|
|
function isValid(num,rowIndex,colIndex){return!inRow(num,rowIndex,colIndex)&&!inCol(num,colIndex)&&!inBox(num,rowIndex,colIndex);}
|
|
var i=0
|
|
var steps=0
|
|
var emptyCell=emptyCellCoordinatesGen(puzz)
|
|
var n
|
|
while(i<emptyCell.length){steps++;if(steps>1000000)
|
|
return false;if(randomize)
|
|
solveArray=shuffleArray(stdSolveArray);if(puzz[emptyCell[i][0]][emptyCell[i][1]]===0)
|
|
n=0;else
|
|
n=solveArray.indexOf(puzz[emptyCell[i][0]][emptyCell[i][1]])+1;while(!isValid(solveArray[n],emptyCell[i][0],emptyCell[i][1])&&n<=solveArray.length-1){n++;}
|
|
if(n==solveArray.length){puzz[emptyCell[i][0]][emptyCell[i][1]]=0;i--;if(i==-1)
|
|
return false;continue;}
|
|
puzz[emptyCell[i][0]][emptyCell[i][1]]=solveArray[n];i++;}
|
|
return puzz;}
|
|
function sudoku(puzz){var solveArray=[1,2,3,4,5,6,7,8,9];return solve(false,solveArray,puzz);} |