Gå til innhold

Script for sudoku?


Anbefalte innlegg

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
Videoannonse
Annonse

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 av pgdx
Lenke til kommentar

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 konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...