appelsinbrus Skrevet 25. oktober 2008 Del Skrevet 25. oktober 2008 Håper jeg poster i rett forum... Har sittet her i timesvis for å finne et sudoku-script jeg kan bruke på bloggen min. Finner utrolig nok ingen som passer, så er det noen som aner hvor jeg kan få tak i et? Og ja, jeg har søkt, jeg fant 1 tråd om noe lignende fra før. Forslaget som da kom frem passer ikke på sida mi. Skulle vært klassisk svart/hvit med mulighet for valg av 3 eller helst 4-5 vanskelighetsgrader. Endte i grunn med at jeg fant et script jeg håpet kunne funke, for utseendet så i allefall bra ut på sida jeg henta det fra. Noen som kan se over (om det er noe mening i scriptet i det heletatt)? Pfh mange takk. <script type="text/javascript"> var debug=0; var currentG=4; var currentP=4; function BoardData(){ this.changed = false; this.arr = new Array(9); for(i=0;i<9;i++){ this.arr=new Array(9); } } function GetCell(g,p){ var cell; var collect; collect = document.getElementsByName(g+'_'+p); cell = collect.item(0); return cell; } function IsInvalidCellContents(cell){ var invalid = false; var num=cell.value; //check length bigger than 1 if(cell.length>1){ invalid=true; } //check for invalid charachters num = cell.value; if (isNaN(num)||num<1||num>9){ invalid=true; } return invalid; } /*************************************************************************** Hint: address lookup of (g,p) (0,0) (0,1) (0,2) (1,0) (1,1) (1,2) (2,0) (2,1) (2,2) (0,3) (0,4) (0,5) (1,3) (1,4) (1,5) (2,3) (2,4) (2,5) (0,6) (0,7) (0,8) ... ... ... ... ... ... (3,0) (3,1) (3,2) ... ... ... ... ... ... (3,3) (3,4) (3,5) ... ... ... ... ... ... (3,6) (3,7) (3,8) ... ... ... ... ... ... (6,0) (6,1) (6,2) (7,0) (7,1) (7,2) (8,0) (8,1) (8,2) (6,3) (6,4) (6,5) ... ... ... ... ... ... (6,6) (6,7) (6,8) ... ... ... ... ... ... Hint: address lookup of (r,c) (0,0) (0,1) (0,2) (0,3) (0,4) (0,5) (0,6) (0,7) (0,8) (1,0) ... ... ... ... ... ... ... ... (2,0) ... ... ... ... ... ... ... ... (3,0) ... ... ... ... ... ... ... ... (4,0) ... ... ... ... ... ... ... ... (5,0) ... ... ... ... ... ... ... ... (6,0) ... ... ... ... ... ... ... ... (7,0) ... ... ... ... ... ... ... ... (8,0) ... ... ... ... ... ... ... ... **************************************************************************/ function GetCellFromRowCol(r,c){ var g; var p; //Calculate g g = ((c - (c % 3)) / 3) + (((r - (r % 3)) / 3)*3); //Calculate p p = (c % 3) + ((r % 3) * 3); return GetCell(g,p); } function DoWithVerticles(g,p,fPointer){ var origCell; var compCell; var gLoop; var gLoopStart; var gLoopEnd; var pLoop; var pLoopStart; var pLoopEnd; //Get Cell contents origCell = GetCell(g,p); if(origCell.value=='')return; //don't check blank cells ////////////////////////////////////////////////////// //Verticles //G loop vars gLoopStart = g % 3; gLoopEnd = gLoopStart+6; //p loop vars pLoopStart = p % 3; pLoopEnd = pLoopStart+6; for(gLoop=gLoopStart;gLoop<=gLoopEnd;gLoop+=3){ for(pLoop=pLoopStart;pLoop<=pLoopEnd;pLoop+=3){ //if vert violation //then color conflicting cell if((g==gLoop)&&(p==pLoop)){ //do nothing, don't compare to self. }else{ compCell = GetCell(gLoop,pLoop); fPointer(origCell,compCell); } } } } function DoWithGridicles(g,p,fPointer){ var origCell; var compCell; var gLoop; var pLoop; var pLoopStart; var pLoopEnd; //Get Cell contents origCell = GetCell(g,p); if(origCell.value=='')return; //don't check blank cells ////////////////////////////////////////////////////// //Verticles //G loop vars gLoop=g; //p loop vars pLoopStart = 0; pLoopEnd = 8; for(pLoop=pLoopStart;pLoop<=pLoopEnd;pLoop++){ //if vert violation //then color conflicting cell if((g==gLoop)&&(p==pLoop)){ //do nothing, don't compare to self. }else{ compCell = GetCell(gLoop,pLoop); fPointer(origCell,compCell); } } } function DoWithHorizontals(g,p,fPointer){ var origCell; var compCell; var gLoop; var gLoopStart; var gLoopEnd; var pLoop; var pLoopStart; var pLoopEnd; //Get Cell contents origCell = GetCell(g,p); if(origCell.value=='')return; //don't check blank cells ////////////////////////////////////////////////////// //Horizontals //G loop vars gLoopStart = ((g - (g % 3)) / 3) * 3; gLoopEnd = gLoopStart+2; //p loop vars pLoopStart = ((p - (p % 3)) / 3) * 3; pLoopEnd = pLoopStart+2; for(gLoop=gLoopStart;gLoop<=gLoopEnd;gLoop++){ for(pLoop=pLoopStart;pLoop<=pLoopEnd;pLoop++){ //if vert violation //then color conflicting cell if((g==gLoop)&&(p==pLoop)){ //do nothing, don't compare to self. }else{ compCell = GetCell(gLoop,pLoop); fPointer(origCell,compCell); } } } } function PaintErrorCell(orig,comp){ if(comp.value==orig.value){ comp.setAttribute('id','error'); orig.setAttribute('id','error'); } } function PaintOrClearErrorCell(orig,comp){ if(comp.value==orig.value){ comp.setAttribute('id','error'); }else{ comp.setAttribute('id','ok'); } } function FastCheck(){ //true if done //any error Cells? cell = document.getElementById('error'); if(cell==null){ //Any cells empty? for(g=0;g<=8;g++){ for(p=0;p<=8;p++){ switch(GetCell(g,p).value){ case '': return false; } } } return true; } return false; } function CheckBoard(){ var g; var p; var count; var cell; count = 0; //check all cells for(g=0;g<=8;g++){ for(p=0;p<=8;p++){ //Set Cell Ok cell = GetCell(g,p); cell.setAttribute('id','ok'); //check to see if there is a value here if(cell.value != '')count++; ////////////////////////////////////////////////////// //Horizontals DoWithHorizontals(g,p,PaintErrorCell); ////////////////////////////////////////////////////// //Verticles DoWithVerticles(g,p,PaintErrorCell); ////////////////////////////////////////////////////// //Grid-icles DoWithGridicles(g,p,PaintErrorCell); } } if(count==81){ //every cell has a value are any error cells? cell = document.getElementById('error'); if(cell==null){ cell = document.getElementById('board'); if(cell!=null){ cell.setAttribute('id','board_solved'); window.alert('Congratulations! You solved this puzzle.'); return true; } } } return false; } function CheckRules(g,p){ //called when keyboard events var origCell; var compCell; var gLoop; var gLoopStart; var gLoopEnd; var pLoop; var pLoopStart; var pLoopEnd; //Get Cell contents origCell = GetCell(g,p); origCell.setAttribute('id','ok'); //if invalid characters if(IsInvalidCellContents(origCell)){ //then clear cell origCell.value = ""; }else{ //else check the rules ////////////////////////////////////////////////////// //Horizontals DoWithHorizontals(g,p,PaintOrClearErrorCell); ////////////////////////////////////////////////////// //Verticles DoWithVerticles(g,p,PaintOrClearErrorCell); ////////////////////////////////////////////////////// //Grid-icles DoWithGridicles(g,p,PaintOrClearErrorCell); } //if(debug)console.log('<< CheckRules(grid='+g+', pos='+p+')'); } function SaveBoard(){ //Read dot notation var dots = document.getElementById('dots'); var cell; var r; var c; dots.value = ''; for(c=0;c<=8;c++){ for(r=0;r<=8;r++){ cell = GetCellFromRowCol(r,c); switch(cell.value){ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': dots.value += cell.value; break; default: dots.value += '.'; break; } } } ReloadBoard(); } function ReloadBoard(){ //Read dot notation var dots = new String(document.getElementById('dots').value); var pos; var ch; var cell; var r; var c; pos = 0; for(c=0;c<=8;c++){ for(r=0;r<=8;r++){ cell = GetCellFromRowCol(r,c); ch = dots.substr(pos,1); switch(ch){ case '.': cell.value = ''; break; default: cell.value = ch; break; } pos++; } } cell = document.getElementById('board_solved'); if(cell!=null){ cell.setAttribute('id','board'); } CheckBoard(); } function RowContainsDigit(liveBoard,r,digit){ var c; for(c=0;c<9;c++){ if(liveBoard.arr[r][c].value == digit)return true; } return false; } function ColContainsDigit(liveBoard,c,digit){ var r; for(r=0;r<9;r++){ if(liveBoard.arr[r][c].value == digit)return true; } return false; } function MarkPossible(digit,possible,liveBoard){ var r; var c; //clear all data for(r=0;r<=8;r++){ for(c=0;c<=8;c++){ possible.arr[r][c] = 0; } } //scan row for digit for(r=0;r<9;r++){ if(!RowContainsDigit(liveBoard,r,digit)){ //increment the empty spaces for(c=0;c<9;c++){ if(!(liveBoard.arr[r][c].value > 0)){ possible.arr[r][c] += 1; } } } } //scan col for digit for(c=0;c<9;c++){ if(!ColContainsDigit(liveBoard,c,digit)){ //increment the empty spaces for(r=0;r<9;r++){ if(!(liveBoard.arr[r][c].value > 0)){ possible.arr[r][c] += 1; } } } } //By now each possible location should have a 2 in it. //This indicates that the row and col are clear at this location //and thus is a possible location for this digit... } function ClearGrid(possible, g){ var r; var c; var x = (g%3)*3; var y = (g-(g%3))/3*3; for(r=0;r<3;r++){ for(c=0;c<3;c++){ possible.arr[r+y][c+x] = 0; } } } function CheckGrid(possible, digit, g){ var p; //Check if there is a digit already in the zone. for(p=0;p<=8;p++){ if(((GetCell(g,p).value)-digit)==0){ ClearGrid(possible,g); break; } } } function CheckGridTriples(possible,digit,g){ var x = (g%3)*3; var y = (g-(g%3))/3*3; var s = new Array(10); var t = new Array(10);; var pCount=0; var r; var c; for(r=y,i=0;i<3;r++,i++){ for(c=x,j=0;j<3;c++,j++){ if((possible.arr[r][c]-2) == 0){ pCount++; s[pCount] = r; t[pCount] = c; } } } if((pCount-3)==0){ //Only two spots for this digit in this zone, so check it! if(s[1]==s[2]&&s[2]==s[3]){ //In same Row - remove possibles from other zones in same Row for(c=0;c<9;c++){ possible.arr[s[1]][c]=0; } } if(t[1]==t[2]&&t[2]==t[3]){ //In same Col - remove possibles from other zones in same Col for(r=0;r<9;r++){ possible.arr[r][t[1]]=0; } } //Put Back the possibles cuz they were removed possible.arr[t[1]][s[1]]=2; possible.arr[t[2]][s[2]]=2; possible.arr[t[3]][s[3]]=2; //if(debug)console.log('----> HINT(): Tripple'); } } function CheckGridDoubles(possible,digit,g){ var x = (g%3)*3; var y = (g-(g%3))/3*3; var s = new Array(10); var t = new Array(10);; var pCount=0; var r; var c; for(r=y,i=0;i<3;r++,i++){ for(c=x,j=0;j<3;c++,j++){ if((possible.arr[r][c]-2) == 0){ pCount++; s[pCount] = r; t[pCount] = c; } } } if((pCount-2)==0){ //Only two spots for this digit in this zone, so check it! if(s[1]==s[2]){ //In same Row - remove possibles from other zones in same Row for(c=0;c<9;c++){ possible.arr[s[1]][c]=0; } } if(t[1]==t[2]){ //In same Col - remove possibles from other zones in same Col for(r=0;r<9;r++){ possible.arr[r][t[1]]=0; } } //Put Back the possibles cuz they were removed possible.arr[t[1]][s[1]]=2; possible.arr[t[2]][s[2]]=2; //if(debug)console.log('----> HINT(): Double'); } } function CheckGridSingles(possible,digit,g){ var x = (g%3)*3; var y = (g-(g%3))/3*3; var s; var t; var pCount; var r; var c; var rtn; rtn = false; pCount = 0; for(r=y,i=0;i<3;r++,i++){ for(c=x,j=0;j<3;c++,j++){ if((possible.arr[r][c]-2) == 0){ s = r; t = c; pCount++; } } } if((pCount-1)==0){ //found a single (only posible location, so take it) var cell = GetCellFromRowCol(s,t); cell.value = digit; cell.setAttribute('id','hint'); rtn = true; //changed } return rtn; } function CheckRowSingles(possible, digit){ //Check the rows for a single possible value var s; var t; var pCount; var r; var c; var rtn; rtn = false; for(r=0;r<9;r++){ pCount = 0; for(c=0;c<9;c++){ if((possible.arr[r][c]-2) == 0){ s = r; t = c; pCount++; } } if((pCount-1)==0){ //found a single (only posible location, so take it) var cell = GetCellFromRowCol(s,t); cell.value = digit; cell.setAttribute('id','hint'); rtn = true; //changed break; //stop after the first found. } } return rtn; } function CheckColSingles(possible, digit){ //Check the rows for a single possible value var s; var t; var pCount; var r; var c; var rtn; rtn = false; for(c=0;c<9;c++){ pCount = 0; for(r=0;r<9;r++){ if((possible.arr[r][c]-2) == 0){ s = r; t = c; pCount++; } } if((pCount-1)==0){ //found a single (only posible location, so take it) var cell = GetCellFromRowCol(s,t); cell.value = digit; cell.setAttribute('id','hint'); rtn = true; //changed break; //stop after the first found. } } return rtn; } function CheckForSingletons(possible){ //A singletone is only one possible digit for this cell. var digit; var r; var c; var s; var t; var count=0; var tempDigit; for(r=0;r<9;r++){ for(c=0;c<9;c++){ //Look in each position and count the number of 2's count = 0; for(digit=1;digit<10;digit++){ if((possible[digit].arr[r][c]-2) == 0){ s = r; t = c; tempDigit = digit; count++; } } if((count-1)==0){ //found a single (only posible location, so take it) var cell = GetCellFromRowCol(s,t); cell.value = tempDigit; cell.setAttribute('id','hint'); return true; } } } return false; } function Hint(hintLevel,verbose){ //Only deterministic attempts, no Guessing. var liveBoard; var possible; var digit; var g; var count=0; //if(debug)console.log('>> Hint(): STARTED'); liveBoard = new BoardData(); possible = new Array(10); //Load the BoardData structure for(r=0;r<=8;r++){ for(c=0;c<=8;c++){ liveBoard.arr[r][c] = GetCellFromRowCol(r,c); } } //if(debug)console.log('Hint(): liveBoard Populated'); liveBoard.changed = false; for(digit=1;digit<10;digit++){ possible[digit] = new BoardData(); MarkPossible(digit,possible[digit],liveBoard); for(g=0;g<9;g++){ CheckGrid(possible[digit], digit, g); switch(hintLevel){ case 5: liveBoard.changed |= CheckColSingles(possible[digit], digit); break; case 4: liveBoard.changed |= CheckRowSingles(possible[digit], digit); break; case 3: CheckGridTriples(possible[digit], digit, g); case 2: CheckGridDoubles(possible[digit], digit, g); case 1: liveBoard.changed |= CheckGridSingles(possible[digit], digit, g); } if(liveBoard.changed)break; //only make one change at a time } if(liveBoard.changed)break; //only make one change at a time } if(!liveBoard.changed){ //Try a better hint level switch(hintLevel){ case 5: //Last check at top level "Singletons" Don't recurse, since the current "possible" matrix is populated already liveBoard.changed = CheckForSingletons(possible); break; case 4: liveBoard.changed = Hint(5,0); break; case 3: liveBoard.changed = Hint(4,0); break; case 2: liveBoard.changed = Hint(3,0); break; case 1: liveBoard.changed = Hint(2,0); break; default: break; } if(verbose && !liveBoard.changed && window.confirm('This is a tough one, there are no obivous moves left. Which often means a brute force approach of guess and test is required. We will save this board position for you, so that you can make a guess and continue. To reload this position, just click in the puzzle field and it will reload this position.')){ //Let's save the current board position SaveBoard(); } } //check to see if we're done for(g=0;g<=8;g++){ for(p=0;p<=8;p++){ //Set Cell Ok //check to see if there is a value here if(liveBoard.arr[g][p].value != '')count++; } } if(count==81){ //every cell has a value are any error cells? CheckBoard(); } return liveBoard.changed; } function Solve(){ var currentBoard; var guessBoard; var done = false; var guess; var cell; var error; var nextSolver; var r; var c; var digit; while(!this.done){ if(!Hint(1,0)){ //hint did not find a move better save this position SaveBoard(); //Keep this good position this.currentBoard = document.getElementById('dots').value; //Time to start Guessing for(this.r=0;this.r<9;this.r++){ for(this.c=0;this.c<9;this.c++){ for(this.digit=1;this.digit<=9;this.digit++){ this.cell = GetCell(this.r,this.c); if(this.cell==null)break;//shouldn't get here, but we do from time to time. switch(this.cell.value){ case '': //Empty Cell, let us make a guess this.cell.value = this.digit; this.done = CheckBoard(); if(!this.done){ //are any error cells? this.error = document.getElementById('error'); if(this.error==null){ //No Errors = possibly a good guess... so start a new Solver this.nextSolver = new Solve(); this.done = this.nextSolver.done; if(!this.done){ //restore the old board, this guess is bad. document.getElementById('dots').value = this.currentBoard; ReloadBoard(); } }else{ //bad guess, better back this out. this.cell.value = ''; } }else{ //we're done! return; } if(!this.done&&this.digit>=9)return false; } if(this.done)return; //get out of this loop } if(this.done)return; //get out of this loop } if(this.done)return; //get out of this loop } //Done guessing... return; }else{ //the hint found something, so keep spinning this.done = FastCheck(); } } } function PreSolve(){ var boardPosition if(window.confirm('The brute force solver may appear to be stuck, and you may receive warnings about unresponsive scripts... \n\nThe script isn\'t locked up, but it will take a long time, and it will use 100% of your CPU time. \n\nGo ahead, it shouldn\'t crash your browser. \n\nYou can see it thinking in Firefox, I recommend you check it out.')){ boardPosition = document.getElementById('dots').value; solver = new Solve(); //Put back the original board position... document.getElementById('dots').value = boardPosition; } } //Stole this from someonline tutorial... function KeyPressed(e) { if( !e ) { if( window.event ) { e = window.event; } else { return; } } if( typeof( e.which ) == 'number' ) { e = e.which; } else { if( typeof( e.keyCode ) == 'number' ) { e = e.keyCode; } else { if( typeof( e.charCode ) == 'number' ) { e = e.charCode; } else { return; } } } //Now check to see if we need to check the board or move the focus if(currentG!=null && currentP!=null){ //Calculate current Row row = Math.floor(currentG/3)*3+Math.floor(currentP/3); //Calculate current Col col = ((currentG%3)*3)+(currentP%3); //We only care about cursor movement... everything else should get a sanity check by CheckRules() switch (e) { case 37: //left col = Math.max(col-1,0); break; case 38: //up row = Math.max(row-1,0); break; case 39: //right col = Math.min(col+1,8); break; case 40: //down row = Math.min(row+1,8); break; default: return CheckRules(currentG,currentP); } //Still here? guess we got movement, so let's set a new focus GetCellFromRowCol(row,col).focus(); } } function Init(){ //Hook the keyboard event if( document.captureEvents && Event.KEYUP ) { document.captureEvents( Event.KEYUP ); } document.onkeyup = KeyPressed; //Set the focus in the centre of the board GetCell(4,4).focus(); //Load the board ReloadBoard(); } </script> Lenke til kommentar
pgdx Skrevet 26. oktober 2008 Del Skrevet 26. oktober 2008 (endret) Hva skjedde med kode-blokken eller pastebin? Jeg ville nok ha endret invalid-saken din til dette: function IsValidCellContents(cell) { var num=cell.value; //check length bigger than 1 if(cell.length>1){ return false; } //check for invalid charachters num = cell.value; if (isNaN(num)||num<1||num>9){ return false; } return true; } Endret 26. oktober 2008 av pgdx Lenke til kommentar
appelsinbrus Skrevet 26. oktober 2008 Forfatter Del Skrevet 26. oktober 2008 Aner ikke hva kode-blokken eller pastebin er, jeg har ganske begrenset kunnskap rundt dette. Takk for svar. Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå