ÿþ<html> <head> <title>Su Doku</title> <meta name="description" content="Sudoku"> <meta name="keywords" content="Sudoku"> </head> <body> <style> .digit { margin : 0px 0px 0px 0px; padding : 3px 3px 3px 3px; background-color: cornflowerblue; font-family: verdana, tahoma, helvetica, arial, sans-serif; font-weight: bold; color: #000000; font-size: 18pt; text-align: center; border: 0px none; width: 28pt; } .digitlock { margin : 0px 0px 0px 0px; padding : 3px 3px 3px 3px; background-color: cornflowerblue; font-family: verdana, tahoma, helvetica, arial, sans-serif; font-weight: bold; color: cornflowerblue; font-size: 18pt; text-align: center; border: 0px none; width: 28pt; } .score { margin : 0px 0px 0px 0px; padding : 0px 0px 0px 0px; background-color: cornflowerblue; font-family: verdana, tahoma, helvetica, arial, sans-serif; font-weight: bold; color: cornflowerblue; font-size: 16pt; text-align: center; border: 0px none; } .instr { margin : 0px 0px 0px 0px; padding : 0px 0px 0px 0px; background-color: cornflowerblue; font-family: verdana, tahoma, helvetica, arial, sans-serif; font-weight: bold; color: cornflowerblue; font-size: 12pt; text-align: center; border: 0px none; } .target { margin : 0px 0px 0px 0px; padding : 0px 0px 0px 0px; background-color: cornflowerblue; font-family: verdana, tahoma, helvetica, arial, sans-serif; font-weight: bold; color: cornflowerblue; font-size: 12pt; text-align: center; border: 0px none; } .bdigit { width: 50px; height: 30px; font-family: verdana, tahoma, helvetica, arial, sans-serif; font-weight: bold; font-size: 12pt; } .bcontrol { width: 80px; height: 30px; font-family: verdana, tahoma, helvetica, arial, sans-serif; font-weight: bold; font-size: 12pt; } </style> </script> <body onload="initialise()" onunload="saveboard()"> <p><center> <h1 align=center>Su Doku Puzzle Creator</h1> <form> <p><center><table border=3 cellpadding=0 cellspacing=0 bgcolor="cornflowerblue"> <tr> <td rowspan=3 align=center width=100 valign=middle bgcolor="cornflowerblue"> <h3>controls</h3> <input type="button" class="bcontrol" name="bcreate" value="Create" onclick="docreate()"><br> <input type="button" class="bcontrol" name="bclear" value="Clear" onclick="doclear()"><br> <input type="button" class="bcontrol" name="block" value="Lock" onclick="dolock()"><br> <input type="button" class="bcontrol" name="breset" value="Reset" onclick="doreset()"><br> <input type="button" class="bcontrol" name="breset" value="Hint" onclick="dohint()"><br> <input type="button" class="bcontrol" name="bsolve" value="Solve" onmousedown="dosolution(1)" onmouseup="dosolution(0)"><br> </td> <td valign=top> <table border=1 cellpadding=0 cellspacing=0> <tr> <td><input class="digit" type="text" id="c0" value=" " size="1" readonly onclick="cell(0)" ></td> <td><input class="digit" type="text" id="c1" value=" " size="1" readonly onclick="cell(1)" ></td> <td><input class="digit" type="text" id="c2" value=" " size="1" readonly onclick="cell(2)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c9" value=" " size="1" readonly onclick="cell(9)" ></td> <td><input class="digit" type="text" id="c10" value=" " size="1" readonly onclick="cell(10)" ></td> <td><input class="digit" type="text" id="c11" value=" " size="1" readonly onclick="cell(11)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c18" value=" " size="1" readonly onclick="cell(18)" ></td> <td><input class="digit" type="text" id="c19" value=" " size="1" readonly onclick="cell(19)" ></td> <td><input class="digit" type="text" id="c20" value=" " size="1" readonly onclick="cell(20)" ></td> </tr> </table> </td> <td valign=top> <table border=1 cellpadding=0 cellspacing=0> <tr> <td><input class="digit" type="text" id="c3" value=" " size="1" readonly onclick="cell(3)" ></td> <td><input class="digit" type="text" id="c4" value=" " size="1" readonly onclick="cell(4)" ></td> <td><input class="digit" type="text" id="c5" value=" " size="1" readonly onclick="cell(5)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c12" value=" " size="1" readonly onclick="cell(12)" ></td> <td><input class="digit" type="text" id="c13" value=" " size="1" readonly onclick="cell(13)" ></td> <td><input class="digit" type="text" id="c14" value=" " size="1" readonly onclick="cell(14)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c21" value=" " size="1" readonly onclick="cell(21)" ></td> <td><input class="digit" type="text" id="c22" value=" " size="1" readonly onclick="cell(22)" ></td> <td><input class="digit" type="text" id="c23" value=" " size="1" readonly onclick="cell(23)" ></td> </tr> </table> </td> <td valign=top> <table border=1 cellpadding=0 cellspacing=0> <tr> <td><input class="digit" type="text" id="c6" value=" " size="1" readonly onclick="cell(6)" ></td> <td><input class="digit" type="text" id="c7" value=" " size="1" readonly onclick="cell(7)" ></td> <td><input class="digit" type="text" id="c8" value=" " size="1" readonly onclick="cell(8)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c15" value=" " size="1" readonly onclick="cell(15)" ></td> <td><input class="digit" type="text" id="c16" value=" " size="1" readonly onclick="cell(16)" ></td> <td><input class="digit" type="text" id="c17" value=" " size="1" readonly onclick="cell(17)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c24" value=" " size="1" readonly onclick="cell(24)" ></td> <td><input class="digit" type="text" id="c25" value=" " size="1" readonly onclick="cell(25)" ></td> <td><input class="digit" type="text" id="c26" value=" " size="1" readonly onclick="cell(26)" ></td> </tr> </table> </td> <td rowspan=3 align=center width=100 valign=middle bgcolor="cornflowerblue"> <input type="button" class="bdigit" name="but1" value="1" onclick="dodigit(0)"><br> <input type="button" class="bdigit" name="but2" value="2" onclick="dodigit(1)"><br> <input type="button" class="bdigit" name="but3" value="3" onclick="dodigit(2)"><br> <input type="button" class="bdigit" name="but4" value="4" onclick="dodigit(3)"><br> <input type="button" class="bdigit" name="but5" value="5" onclick="dodigit(4)"><br> <input type="button" class="bdigit" name="but6" value="6" onclick="dodigit(5)"><br> <input type="button" class="bdigit" name="but7" value="7" onclick="dodigit(6)"><br> <input type="button" class="bdigit" name="but8" value="8" onclick="dodigit(7)"><br> <input type="button" class="bdigit" name="but9" value="9" onclick="dodigit(8)"><br> <input type="button" class="bdigit" name="but0" value="_" onclick="dodigit(15)"><br> </td> </tr> <tr> <td valign=top> <table border=1 cellpadding=0 cellspacing=0> <tr> <td><input class="digit" type="text" id="c27" value=" " size="1" readonly onclick="cell(27)" ></td> <td><input class="digit" type="text" id="c28" value=" " size="1" readonly onclick="cell(28)" ></td> <td><input class="digit" type="text" id="c29" value=" " size="1" readonly onclick="cell(29)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c36" value=" " size="1" readonly onclick="cell(36)" ></td> <td><input class="digit" type="text" id="c37" value=" " size="1" readonly onclick="cell(37)" ></td> <td><input class="digit" type="text" id="c38" value=" " size="1" readonly onclick="cell(38)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c45" value=" " size="1" readonly onclick="cell(45)" ></td> <td><input class="digit" type="text" id="c46" value=" " size="1" readonly onclick="cell(46)" ></td> <td><input class="digit" type="text" id="c47" value=" " size="1" readonly onclick="cell(47)" ></td> </tr> </table> </td> <td valign=top> <table border=1 cellpadding=0 cellspacing=0> <tr> <td><input class="digit" type="text" id="c30" value=" " size="1" readonly onclick="cell(30)" ></td> <td><input class="digit" type="text" id="c31" value=" " size="1" readonly onclick="cell(31)" ></td> <td><input class="digit" type="text" id="c32" value=" " size="1" readonly onclick="cell(32)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c39" value=" " size="1" readonly onclick="cell(39)" ></td> <td><input class="digit" type="text" id="c40" value=" " size="1" readonly onclick="cell(40)" ></td> <td><input class="digit" type="text" id="c41" value=" " size="1" readonly onclick="cell(41)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c48" value=" " size="1" readonly onclick="cell(48)" ></td> <td><input class="digit" type="text" id="c49" value=" " size="1" readonly onclick="cell(49)" ></td> <td><input class="digit" type="text" id="c50" value=" " size="1" readonly onclick="cell(50)" ></td> </tr> </table> </td> <td valign=top> <table border=1 cellpadding=0 cellspacing=0> <tr> <td><input class="digit" type="text" id="c33" value=" " size="1" readonly onclick="cell(33)" ></td> <td><input class="digit" type="text" id="c34" value=" " size="1" readonly onclick="cell(34)" ></td> <td><input class="digit" type="text" id="c35" value=" " size="1" readonly onclick="cell(35)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c42" value=" " size="1" readonly onclick="cell(42)" ></td> <td><input class="digit" type="text" id="c43" value=" " size="1" readonly onclick="cell(43)" ></td> <td><input class="digit" type="text" id="c44" value=" " size="1" readonly onclick="cell(44)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c51" value=" " size="1" readonly onclick="cell(51)" ></td> <td><input class="digit" type="text" id="c52" value=" " size="1" readonly onclick="cell(52)" ></td> <td><input class="digit" type="text" id="c53" value=" " size="1" readonly onclick="cell(53)" ></td> </tr> </table> </td> </tr> <tr> <td valign=top> <table border=1 cellpadding=0 cellspacing=0> <tr> <td><input class="digit" type="text" id="c54" value=" " size="1" readonly onclick="cell(54)" ></td> <td><input class="digit" type="text" id="c55" value=" " size="1" readonly onclick="cell(55)" ></td> <td><input class="digit" type="text" id="c56" value=" " size="1" readonly onclick="cell(56)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c63" value=" " size="1" readonly onclick="cell(63)" ></td> <td><input class="digit" type="text" id="c64" value=" " size="1" readonly onclick="cell(64)" ></td> <td><input class="digit" type="text" id="c65" value=" " size="1" readonly onclick="cell(65)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c72" value=" " size="1" readonly onclick="cell(72)" ></td> <td><input class="digit" type="text" id="c73" value=" " size="1" readonly onclick="cell(73)" ></td> <td><input class="digit" type="text" id="c74" value=" " size="1" readonly onclick="cell(74)" ></td> </tr> </table> </td> <td valign=top> <table border=1 cellpadding=0 cellspacing=0> <tr> <td><input class="digit" type="text" id="c57" value=" " size="1" readonly onclick="cell(57)" ></td> <td><input class="digit" type="text" id="c58" value=" " size="1" readonly onclick="cell(58)" ></td> <td><input class="digit" type="text" id="c59" value=" " size="1" readonly onclick="cell(59)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c66" value=" " size="1" readonly onclick="cell(66)" ></td> <td><input class="digit" type="text" id="c67" value=" " size="1" readonly onclick="cell(67)" ></td> <td><input class="digit" type="text" id="c68" value=" " size="1" readonly onclick="cell(68)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c75" value=" " size="1" readonly onclick="cell(75)" ></td> <td><input class="digit" type="text" id="c76" value=" " size="1" readonly onclick="cell(76)" ></td> <td><input class="digit" type="text" id="c77" value=" " size="1" readonly onclick="cell(77)" ></td> </tr> </table> </td> <td valign=top> <table border=1 cellpadding=0 cellspacing=0> <tr> <td><input class="digit" type="text" id="c60" value=" " size="1" readonly onclick="cell(60)" ></td> <td><input class="digit" type="text" id="c61" value=" " size="1" readonly onclick="cell(61)" ></td> <td><input class="digit" type="text" id="c62" value=" " size="1" readonly onclick="cell(62)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c69" value=" " size="1" readonly onclick="cell(69)" ></td> <td><input class="digit" type="text" id="c70" value=" " size="1" readonly onclick="cell(70)" ></td> <td><input class="digit" type="text" id="c71" value=" " size="1" readonly onclick="cell(71)" ></td> </tr> <tr> <td><input class="digit" type="text" id="c78" value=" " size="1" readonly onclick="cell(78)" ></td> <td><input class="digit" type="text" id="c79" value=" " size="1" readonly onclick="cell(79)" ></td> <td><input class="digit" type="text" id="c80" value=" " size="1" readonly onclick="cell(80)" ></td> </tr> </table> </td> </tr> </table></center> <embed src="beep.wav" autostart=false hidden=true id="beep" enablejavascript="true"> </body> <script> // Sudoku Puzzle Creator & WorkPad // (c) 2005 Mark Huckvale - University College London // // Revision history // 1.0 - Initial Release // 1.1 - Final animation // 1.2 - Improved hint function, clear cell button // // global variables var ccell; // current cell for cursor var board=new Array(81); // board on display var digit=new Array('1','2','3','4','5','6','7','8','9','*','*','*','*','*','*',' '); var digit_mask=0x0000000F; // displayed digit mask var solve_mask=0x000000F0; // solution digit mask var allow_mask=0x0001FF00; // digits allowed in this cell mask var locks_mask=0x00020000; // cell locked mask var allow_bits=new Array(0x00100,0x00200,0x00400,0x00800,0x01000,0x02000,0x04000,0x08000,0x10000); var lock_flag=0x00020000; // cell locked var box_index=new Array(9); // look-up table for boxes var col_index=new Array(9); // look-up table for columns var row_index=new Array(9); // look-up table for rows var solved; // flag if solution found var animthread=null; var animtrigger=0; var spiral=new Array(0,1,2,3,4,5,6,7,8,17,26,35,44,53,62,71,80,79,78,77,76,75,74,73,72,63,54,45,36,27,18,9,10,11,12,13,14,15,16,25,34,43,52,61,70,69,68,67,66,65,64,55,46,37,28,19,20,21,22,23,24,33,42,51,60,59,58,57,56,47,38,29,30,31,32,41,50,49,48,39,40); var target0=new Array(40,40); var target1=new Array(30,31,32,41,50,49,48,39); var target2=new Array(20,21,22,23,24,33,42,51,60,59,58,57,56,47,38,29); var target3=new Array(10,11,12,13,14,15,16,25,34,43,52,61,70,69,68,67,66,65,64,55,46,37,28,19); var target4=new Array(0,1,2,3,4,5,6,7,8,17,26,35,44,53,62,71,80,79,78,77,76,75,74,73,72,63,54,45,36,27,18,9); // random number generator var today=new Date(); var seed=today.getTime(); function rnd() { seed = (seed*9301+49297) % 233280; return seed/(233280.0); }; function rand(number) { return Math.floor(rnd()*number); }; // clear back to empty function doclear() { var i; for (i=0;i<81;i++) { var pfield=document.getElementById("c"+i); pfield.className="digit"; pfield.style.backgroundColor="#CEE7FF"; pfield.value=' '; board[i]=allow_mask | solve_mask | digit_mask; } solved=0; } // once only initialisation function initialise() { // initialise quick indexes box_index[0]=new Array(0,1,2,9,10,11,18,19,20); box_index[1]=new Array(3,4,5,12,13,14,21,22,23); box_index[2]=new Array(6,7,8,15,16,17,24,25,26); box_index[3]=new Array(27,28,29,36,37,38,45,46,47); box_index[4]=new Array(30,31,32,39,40,41,48,49,50); box_index[5]=new Array(33,34,35,42,43,44,51,52,53); box_index[6]=new Array(54,55,56,63,64,65,72,73,74); box_index[7]=new Array(57,58,59,66,67,68,75,76,77); box_index[8]=new Array(60,61,62,69,70,71,78,79,80); row_index[0]=new Array(0,1,2,3,4,5,6,7,8); row_index[1]=new Array(9,10,11,12,13,14,15,16,17); row_index[2]=new Array(18,19,20,21,22,23,24,25,26); row_index[3]=new Array(27,28,29,30,31,32,33,34,35); row_index[4]=new Array(36,37,38,39,40,41,42,43,44); row_index[5]=new Array(45,46,47,48,49,50,51,52,53); row_index[6]=new Array(54,55,56,57,58,59,60,61,62); row_index[7]=new Array(63,64,65,66,67,68,69,70,71); row_index[8]=new Array(72,73,74,75,76,77,78,79,80); col_index[0]=new Array(0,9,18,27,36,45,54,63,72); col_index[1]=new Array(1,10,19,28,37,46,55,64,73); col_index[2]=new Array(2,11,20,29,38,47,56,65,74); col_index[3]=new Array(3,12,21,30,39,48,57,66,75); col_index[4]=new Array(4,13,22,31,40,49,58,67,76); col_index[5]=new Array(5,14,23,32,41,50,59,68,77); col_index[6]=new Array(6,15,24,33,42,51,60,69,78); col_index[7]=new Array(7,16,25,34,43,52,61,70,79); col_index[8]=new Array(8,17,26,35,44,53,62,71,80); // clear board doclear(); // restore from cookie restoreboard(); // display cursor ccell=0; var pfield=document.getElementById("c"+ccell); if (board[ccell]&lock_flag) pfield.className="digitlock"; else pfield.className="digit"; pfield.style.backgroundColor="#CEE7FF"; pfield.focus(); // trap key presses document.onkeydown=kbdhandler; } // get row index from cell number function getrow(cell) { return(Math.floor(cell/9)); } // get column from cell number function getcol(cell) { return(Math.floor(cell%9)); } // get box from cell number function getbox(cell) { var row=getrow(cell); var col=getcol(cell); return(Math.floor(3*Math.floor(row/3)+Math.floor(col/3))); } // move cursor to cell function cell(cc) { var pfield=document.getElementById("c"+ccell); if (board[ccell]&lock_flag) pfield.className="digitlock"; else pfield.className="digit"; pfield.style.backgroundColor="#CEE7FF"; ccell=cc; pfield=document.getElementById("c"+ccell); if (board[ccell]&lock_flag) pfield.className="digitlock"; else pfield.className="digit"; pfield.style.backgroundColor="#ccddee"; pfield.focus(); } // move hint highlight to cell function cellblink(cc) { var pfield=document.getElementById("c"+ccell); if (board[ccell]&lock_flag) pfield.className="digitlock"; else pfield.className="digit"; pfield.style.backgroundColor="#eeeeee"; ccell=cc; var pfield=document.getElementById("c"+ccell); if (board[ccell]&lock_flag) pfield.className="digitlock"; else pfield.className="digit"; pfield.style.backgroundColor="#ccddee"; pfield.focus(); } // enter a digit from digit buttons function dodigit(num) { var pfield=document.getElementById("c"+ccell); if (checklegal(board,ccell,num)&&!(board[ccell]&lock_flag)) { pfield.value=digit[num]; board[ccell] = (board[ccell] & ~digit_mask) | num; solved=0; if (animtrigger && checksolution()) { animthread=setInterval("animate()",60); setTimeout("noanimate()",20000); animtrigger=0; } } else if (!(board[ccell]&lock_flag)) { pfield.value=' '; board[ccell] |= digit_mask; solved=0; dobeep(); } cell(ccell); } // enter a digit from keyboard function kbdhandler(e) { var pfield=document.getElementById("c"+ccell); if (!e) e=window.event; var chr = String.fromCharCode(e.keyCode); if (('1'<=chr)&&(chr <='9')) { var d=chr.charCodeAt(0)-49; dodigit(d); } else if (('a'<=chr)&&(chr <='i')) { var d=chr.charCodeAt(0)-97; dodigit(d); } else if ((chr==' ')||(e.keyCode==46)||(e.keyCode==8)) { if ((board[ccell]&lock_flag)==0) { pfield.value=' '; board[ccell] |= digit_mask; cell(ccell); solved=0; } } else if (chr=='\x25') { // left arrow var cc=ccell-1; if (cc<0) { cc += 81; } cell(cc); } else if (chr=='\x26') { // up arrow var cc=ccell-9; if (cc<0) { if (cc==-9) cc = 80; else cc += 80; } cell(cc); } else if (chr=='\x27') { // right arrow var cc=ccell+1; if (cc>80) { cc -= 81; } cell(cc); } else if (chr=='\x28') { // down arrow var cc=ccell+9; if (cc > 80) { if (cc==89) cc=0; else cc -= 80; } cell(cc); } // else if (chr==0) // alert("Got key code="+e.keyCode); // else // alert("Got key code="+e.keyCode+" char="+chr); pfield.focus(); } // check user input is allowed // note that we allow users to enter incorrect digits // that happen to still be legal according to the rules function checklegal(board,cc,d) { var hold=board[cc]; var i,j; board[cc] |= digit_mask; // check row var row=getrow(cc); for (j=0;j<9;j++) if ((board[row_index[row][j]]&digit_mask)==d) { board[cc]=hold; return(0); } // check column var col=getcol(cc); for (j=0;j<9;j++) if ((board[col_index[col][j]]&digit_mask)==d) { board[cc]=hold; return(0); } // check box var box=getbox(cc); for (j=0;j<9;j++) if ((board[box_index[box][j]]&digit_mask)==d) { board[cc]=hold; return(0); } // OK board[cc]=hold; return(1); } // lock the currently displayed digits function dolock() { var i; for (i=0;i<81;i++) { if ((board[i]&digit_mask)<9) { var pfield=document.getElementById("c"+i); pfield.className="digitlock"; board[i] |= lock_flag; } } } // reset the board to the locked digits only function doreset() { var i; for (i=0;i<81;i++) { if (!(board[i]&lock_flag)) { var pfield=document.getElementById("c"+i); pfield.value=' '; board[i] |= digit_mask; } } } // play a warning beep function dobeep() { var thissound=document.getElementById("beep"); thissound.Play(); } // check solution function checksolution() { var i,sum; // check rows for (i=0;i<9;i++) { sum=0; for (j=0;j<9;j++) sum += board[row_index[i][j]] & digit_mask; if (sum!=36) return(0); } // check cols for (i=0;i<9;i++) { sum=0; for (j=0;j<9;j++) sum += board[col_index[i][j]] & digit_mask; if (sum!=36) return(0); } // check boxes for (i=0;i<9;i++) { sum=0; for (j=0;j<9;j++) sum += board[box_index[i][j]] & digit_mask; if (sum!=36) return(0); } return(1); } // set a digit into a board cell function setdigit(cc,num) { var pfield=document.getElementById("c"+cc); if (board[cc] & lock_flag) pfield.className="digitlock"; else pfield.className="digit"; pfield.value=digit[num]; board[cc] = (board[cc] & ~digit_mask) | num; } // check the contents of all boxes function boxcheck(board) { var i,j,d,sum,last,last2,last3; for (i=0;i<9;i++) { for (d=0;d<9;d++) { sum=0; last=-1; last2=-1; last3=-1; for (j=0;j<9;j++) { if (board[box_index[i][j]]&allow_bits[d]) { sum++; last3=last2; last2=last; last=box_index[i][j]; } else sum += ((board[box_index[i][j]] & solve_mask)==(d << 4)) ? 1: 0; } // if #possible is 0 then fail if (sum==0) return(0); // if #possible is 1 then fix it in solution if ((sum==1)&&(last>=0)) { if (!setallowed(board,last,d)) return(0); } // if #possible is 2 then if both on same row, can't be elsewhere on row if ((sum==2)&&(last>=0)&&(last2>=0)&&(getrow(last)==getrow(last2))) { for (j=0;j<9;j++) { var c=row_index[getrow(last)][j]; if ((c!=last)&&(c!=last2)) { if (board[c]&allow_bits[d]) { board[c] &= ~allow_bits[d]; if ((board[c]&allow_mask)==0) return(0); } } } } // if #possible is 2 then if both on same col, can't be elsewhere on col if ((sum==2)&&(last>=0)&&(last2>=0)&&(getcol(last)==getcol(last2))) { for (j=0;j<9;j++) { var c=col_index[getcol(last)][j]; if ((c!=last)&&(c!=last2)) { if (board[c]&allow_bits[d]) { board[c] &= ~allow_bits[d]; if ((board[c]&allow_mask)==0) return(0); } } } } // if #possible is 3 then if all on same row, can't be elsewhere on row if ((sum==3)&&(last>=0)&&(last2>=0)&&(last3>=0)&&(getrow(last)==getrow(last2))&&(getrow(last)==getrow(last3))) { for (j=0;j<9;j++) { c=row_index[getrow(last)][j]; if ((c!=last)&&(c!=last2)&&(c!=last3)) { if (board[c]&allow_bits[d]) { board[c] &= ~allow_bits[d]; if ((board[c]&allow_mask)==0) return(0); } } } } // if #possible is 3 then if all on same col, can't be elsewhere on col if ((sum==3)&&(last>=0)&&(last2>=0)&&(last3>=0)&&(getcol(last)==getcol(last2))&&(getcol(last)==getcol(last3))) { for (j=0;j<9;j++) { c=col_index[getcol(last)][j]; if ((c!=last)&&(c!=last2)&&(c!=last3)) { if (board[c]&allow_bits[d]) { board[c] &= ~allow_bits[d]; if ((board[c]&allow_mask)==0) return(0); } } } } } } return(1); } // check the contents of all rows function rowcheck(board) { var i,j,d,sum,last; for (i=0;i<9;i++) { for (d=0;d<9;d++) { sum=0; last=-1; for (j=0;j<9;j++) { if (board[row_index[i][j]]&allow_bits[d]) { sum++; last=j; } else sum += ((board[row_index[i][j]] & solve_mask)==(d << 4)) ? 1: 0; } if (sum==0) return(0); if ((sum==1)&&(last>=0)) { if (!setallowed(board,row_index[i][last],d)) return(0); } } } return(1); } // check the contents of all columns function colcheck(board) { var i,j,d,sum,last; for (i=0;i<9;i++) { for (d=0;d<9;d++) { sum=0; last=-1; for (j=0;j<9;j++) { if (board[col_index[i][j]]&allow_bits[d]) { sum++; last=j; } else sum += ((board[col_index[i][j]] & solve_mask)==(d << 4)) ? 1: 0; } if (sum==0) return(0); if ((sum==1)&&(last>=0)) { if (!setallowed(board,col_index[i][last],d)) return(0); } } } return(1); } // set a digit into a board, clearing allowed flags elsewhere function setallowed(board,cc,num) { var i,j,k,l,d; var s; // clear alternatives in this cell board[cc] &= ~allow_mask; // and set value as solution board[cc] = (board[cc] & ~solve_mask) | (num << 4); // clear this digit on same row var row=getrow(cc); for (j=0;j<9;j++) { if (board[row_index[row][j]]&allow_bits[num]) { board[row_index[row][j]] &= ~allow_bits[num]; if ((board[row_index[row][j]]&allow_mask)==0) return(0); } } // clear this digit on same column var col=getcol(cc); for (j=0;j<9;j++) { if (board[col_index[col][j]]&allow_bits[num]) { board[col_index[col][j]] &= ~allow_bits[num]; if ((board[col_index[col][j]]&allow_mask)==0) return(0); } } // clear this digit in same box var box=getbox(cc); for (j=0;j<9;j++) { if (board[box_index[box][j]]&allow_bits[num]) { board[box_index[box][j]] &= ~allow_bits[num]; if ((board[box_index[box][j]]&allow_mask)==0) return(0); } } // process all singletons created by setting for (i=0;i<81;i++) for (d=0;d<9;d++) if ((board[i]&allow_mask)==allow_bits[d]) if (!setallowed(board,i,d)) return(0); // check each digit still available in each box, row and column if (!boxcheck(board)||!rowcheck(board)||!colcheck(board)) return(0); // process all singletons created by setting (double check) for (i=0;i<81;i++) for (d=0;d<9;d++) if ((board[i]&allow_mask)==allow_bits[d]) if (!setallowed(board,i,d)) return(0); return(1); } // check if board is a solution function chksolved(board) { var i; var nchoices=0; // count # choices left for (i=0;i<81;i++) if ((board[i]&allow_mask)!=0) nchoices++; // solved? if (nchoices==0) solved=1; // OK return(solved); } // debug variable to test depth of search var maxlevel; // attempt to solve from this situation function attempt(pboard,level) { var board=new Array(81); var i,j,k; var s,e; // check for runaway if (level > maxlevel) { maxlevel=level; // alert("Level="+level); } if (level > 25) return; // probably gone wrong // pick starting square at random i=s=rand(81); do { if ((pboard[i]&allow_mask)!=0) { // pick starting digit at random j=e=rand(9); do { if (pboard[i]&allow_bits[j]) { // push current solution for (k=0;k<81;k++) board[k]=pboard[k]; // try out digit if (setallowed(board,i,j)) { board[i] = (board[i] & ~digit_mask) | j; if (chksolved(board)) { for (k=0;k<81;k++) pboard[k]=board[k]; return; } // recurse attempt(board,level+1); if (chksolved(board)) { for (k=0;k<81;k++) pboard[k]=board[k]; return; } // no good board[i] |= digit_mask; if (level > 2) return; // don't both searching anymore } } j=(j+1)%9; } while (j!=e); } i=(i+1)%81; } while (i!=s); } // create a new initial configuration function docreate() { var i,d; do { // clear the board doclear(); solved=0; maxlevel=0; // assign one of each digit at random for (d=0;d<9;d++) { i=rand(81); if (board[i]&allow_bits[d]) { setallowed(board,i,d); board[i] = (board[i] & ~digit_mask) | d; } } // attempt to solve from here attempt(board,0); // display result for (i=0;i<81;i++) { if ((0<=(board[i]&digit_mask))&&((board[i]&digit_mask) < 9)) board[i] |= lock_flag; setdigit(i,board[i]&digit_mask); } if (!solved) alert("Failed to make puzzle\nTrying again."); } while (!solved); // display cursor ccell=0; var pfield=document.getElementById("c"+ccell); if (board[ccell]&lock_flag) pfield.className="digitlock"; else pfield.className="digit"; pfield.style.backgroundColor="cornflowerbluec"; pfield.focus(); // set animation trigger animtrigger=1; } // find a possible move in a board function findmove(board) { var i,d; var s; // pick starting square at random i=s=rand(81); do { if (!(board[i]&allow_mask)) { d=(board[i]&solve_mask)>>4; if ((board[i]&digit_mask)!=d) return(i); } i=(i+1)%81; } while (i!=s); // failed return(-1); } // give a hint function dohint() { var tboard=new Array(81); var i,j,k,l,d; var s,t; // reset work arrays for (i=0;i<81;i++) tboard[i]=allow_mask | solve_mask | digit_mask; // add in current cells s=-1; i=t=rand(81); do { c=board[i] & digit_mask; if ((0<=c)&&(c<9)) { tboard[i] = (tboard[i] & ~digit_mask) | c; if (!setallowed(tboard,i,c)) { alert("Starting position impossible, lastchar="+digit[c]); return; } if ((s=findmove(tboard))>=0) { if ((board[s]&digit_mask)==digit_mask) break; } } i=(i+1)%81; } while (i!=t); // find a possible go // s=findmove(tboard); if (s>=0) { cellblink(s); } else { // for (i=0;i<81;i++) { // s=""; // for (j=0;j<9;j++) if (tboard[i]&allow_bits[j]) s=digit[j]+s; // if (s!="") { // var pfield=document.getElementById("c"+i); // pfield.value="("+s+")"; // } // } alert("No hint available."); cell(ccell); } } // find and display complete solution function dosolution(show) { var pboard=new Array(81); var i,c; if (show) { if (!solved) { // reset solution for (i=0;i<81;i++) pboard[i] = allow_mask | solve_mask | digit_mask; // add in current cells for (i=0;i<81;i++) { c=board[i] & digit_mask; if ((0<=c)&&(c<9)) { if (!setallowed(pboard,i,c)) { alert("Starting position impossible.\nFailed at cell="+i+" char="+digit[c]); return; } } } // attempt solution attempt(pboard,0); // copy solution into main board for (i=0;i<81;i++) board[i] = (board[i] & ~solve_mask) | (pboard[i] & solve_mask); } // display solution for (i=0;i<81;i++) { var pfield=document.getElementById("c"+i); pfield.value=digit[(board[i]&solve_mask)>>4]; } } else { // restore board contents for (i=0;i<81;i++) { var pfield=document.getElementById("c"+i); pfield.value=digit[board[i]&digit_mask]; } } } // save board to cookie on user's machine function saveboard() { var s=board.join("|"); var exp = new Date(); var oneYearFromNow = exp.getTime() + (365 * 24 * 60 * 60 * 1000); exp.setTime(oneYearFromNow); document.cookie = "sudoku="+s+"; expires=" + exp.toGMTString(); } // get a variable from a cookie string function getCookieData(labelName) { var labelLen = labelName.length; var cookieData = document.cookie; var cLen = cookieData.length; var i = 0; var cEnd; while (i < cLen) { var j = i + labelLen; if (cookieData.substring(i,j) == labelName) { cEnd = cookieData.indexOf(";",j); if (cEnd == -1) { cEnd = cookieData.length; } return unescape(cookieData.substring(j+1, cEnd)); } i++; } return ""; } // restore board from cookie on user's machine function restoreboard() { var s=getCookieData("sudoku"); var a=s.split("|"); if (a.length==81) { var i; for (i=0;i<81;i++) { board[i]=a[i]; setdigit(i,board[i]&digit_mask); } } } // animation state var state=0; // animate a pattern of colours function animate() { var i,j; var colours=new Array("#ffffcc", "#ffccff","#ccffff","#eeeeee"); if (state < 81) { i=spiral[(state+80)%81]; j=spiral[state]; var pfield=document.getElementById("c"+i); pfield.style.backgroundColor="#eeeeee"; var pfield=document.getElementById("c"+j); pfield.style.backgroundColor="#eecccc"; var pfield=document.getElementById("c"+(80-i)); pfield.style.backgroundColor="#eeeeee"; var pfield=document.getElementById("c"+(80-j)); pfield.style.backgroundColor="#cceecc"; } else { clearInterval(animthread); animthread=setInterval("animate()",100); for (i=0;i<target0.length;i++) { j=target0[i]; var pfield=document.getElementById("c"+j); pfield.style.backgroundColor=colours[state%4]; } for (i=0;i<target1.length;i++) { j=target1[i]; var pfield=document.getElementById("c"+j); pfield.style.backgroundColor=colours[(state+1)%4]; } for (i=0;i<target2.length;i++) { j=target2[i]; var pfield=document.getElementById("c"+j); pfield.style.backgroundColor=colours[(state+2)%4]; } for (i=0;i<target3.length;i++) { j=target3[i]; var pfield=document.getElementById("c"+j); pfield.style.backgroundColor=colours[(state+3)%4]; } for (i=0;i<target4.length;i++) { j=target4[i]; var pfield=document.getElementById("c"+j); pfield.style.backgroundColor=colours[(state+4)%4]; } } state = state+1; } // cancel animation function noanimate() { if (animthread) { clearInterval(animthread); animthread=null; } for (i=0;i<81;i++) { var pfield=document.getElementById("c"+i); pfield.style.backgroundColor="#eeeeee"; pfield.className="digit"; } state=0; } </script> <center> <b>Uitleg</b><BR><BR> Vul het Diagram op een zodanig manier in dat alle cijfers van 1 tot en met 9 slechts één keer voorkomen in alle horizontale rijen en verticale kolommen, en dat alle cijfers van 1 tot en met 9 voorkomen in elk van de negen vierkantjes van 3 x 3 vakjes. <BR><BR> Klik op "Create" om een nieuwe speelveld te maken. Als je een cijfer wilt toevoegen op het speelveld, klik dan op het desbetreffende vakje en klik op het cijfer. Wil je het cijfer weer weghalen, klik dan op het streepje (onder de 9). <BR><BR> Klik op Clear om alles van het veld weg te halen, ook de begincijfers.<BR><BR> ALs je een cijfer wilt vastleggen, zodat je deze niet per ongeluk weer weg kan halen, dan klik je het vakje aan waar het cijfer in staat en dan klik je op Lock. Je ziet het cijfer van kleur veranderen.<BR><BR> Wil je het speelveld overnieuw spelen, dan kan je op reset drukken.<BR><BR> Als je op "hint" klikt, dan wordt een vakje geselecteerd waar je al makkelijk een cijfer in kan vullen.<BR><BR> En als laatste "solve", als je hier op klikt en je houdt je muisknop ingedrukt, dan zie je het gehele speelveld ingevuld! <BR><BR> Ik wens iedereen veel succes! </html>