Cookie Notice

As far as I know, and as far as I remember, nothing in this page does anything with Cookies.

2009/06/09

Fun with jQuery

I have created jSudoku, an implementation of Sudoku in Javascript with jQuery.

Using jQuery allowed me to use very simple HTML. Just a table with nine rows of nine blocks, each with just a nonbreaking space inside. It kinda breaks the display code, so trust me, OK?

And also very simple

table {
margin: 0 auto ;
border-collapse: collapse ;
}
td {
height: 40px ;
width: 40px ;
font-size: 30px ;
line-height:40px ;
text-align: center ;
padding: 0 ;
}
#junk {
display: none ;
}

.header {
position: absolute ;
top: 0 ;
left: 0 ;
width: 100% ;
height: 70px ;
background-color: #666 ;
padding-left: 5% ;
border-bottom: 2px solid #333 ;
}

.header .title {
color: white ;
font-size: 48px ;
}

.header .subtitle {
color: #bbb ;
font-size: 14px ;
border-bottom: 1px solid #bbb ;
}

.main{
position: absolute ;
top: 100px ;
left: 0 ;
width: 100% ;
}

.footer{
background-color: #aaa ;
border-top: 2px solid #ccc ;
color: #333 ;
position: absolute ;
bottom: 0 ;
left: 0 ;
width: 100% ;
}

Nothing even remotely clever there.

Where the cleverness comes in is in the javascript.


//------------------------------------------------------------------------------
// Kinda the "Main()" for this. Runs when the page is fully loaded.
//------------------------------------------------------------------------------
$(function() {

//--------------------------------------------------------------------------
// sudoku
//--------------------------------------------------------------------------

//--------------------------------------------------------------------------
// look and feel
//--------------------------------------------------------------------------
$( '#sudoku' ).children( 'table' ).each( function() {
} ) ;
$( 'td' ).each( function() {
$( this ).css( 'border-color' , 'black' ) ;
$( this ).css( 'border-width' , '1px' ) ;
$( this ).css( 'border-style' , 'solid' ) ;
} ) ;
$( 'td:even' ).each( function() {
$( this ).css( 'background-color' , '#eee' ) ;
} ) ;
//--------------------------------------------------------------------------

//--------------------------------------------------------------------------
// borders
//--------------------------------------------------------------------------
var i = 1 ;
var j = 1 ;
$( 'tr' ).each( function() {
i = 1 ;
$( this ).children( 'td' ).each( function() {
//$( this ).html( i ) ;
if ( aSudoku[j][i] != '' ) {
$( this ).html( aSudoku[j][i] ) ;
$( this ).attr( 'class' , 'static' ) ;
$( this ).css( 'font-weight' , '700' ) ;
// $( this ).css( 'color' , '#000' ) ;
}
else {
$( this ).attr( 'class' , 'change' ) ;
$( this ).css( 'font-weight' , '100' ) ;
$( this ).css( 'font-size' , '28px' ) ;
// $( this ).css( 'color' , '#066' ) ;
}
if ( i == 1 || i == 4 || i == 7 ) {
$( this ).css( 'border-left-width' , '3px' )
} ;
if ( i == 3 || i == 6 || i == 9 ) {
$( this ).css( 'border-right-width' , '3px' )
} ;
if ( j == 1 || j == 4 || j == 7 ) {
$( this ).css( 'border-top-width' , '3px' )
} ;
if ( j == 3 || j == 6 || j == 9 ) {
$( this ).css( 'border-bottom-width' , '3px' )
} ;
i++ ;
} ) ;
j++ ;
} ) ;

//--------------------------------------------------------------------------
// position tracking
//--------------------------------------------------------------------------
$( 'td:even' ).hover( function() {
$( this ).css( 'background-color' , '#eea' ) ;
} , function() {
$( this ).css( 'background-color' , '#eee' ) ;
} ) ;
$( 'td:odd' ).hover( function() {
$( this ).css( 'background-color' , '#eea' ) ;
} , function() {
$( this ).css( 'background-color' , '#fff' ) ;
} ) ;

//--------------------------------------------------------------------------
// setting numbers
//--------------------------------------------------------------------------

var box ;
$( 'td.change' ).hover(
function() {
box = $( this ) ;
$( document ).keypress( function(e) {
if ( ( e.which > 48 && e.which < 58 ) ||
( e.which == 32 ) && ( 1 ) ) {
var c = String.fromCharCode( e.which ) ;
if ( c == ' ' ) { c = ' ' ; }
box.html( c ) ;
}
} ) ;
score_table( ) ;
} ,
function() {
box = $( '#junk' ) ;
score_table( ) ;
}
) ;

//--------------------------------------------------------------------------

score_table() ;

} ) ;
//------------------------------------------------------------------------------



//------------------------------------------------------------------------------
function score_table ( ) {
$( 'input#space' ).attr('value','') ;
var results = new Array(9) ;
for (var i = 0 ; i < 9 ; i++ ){
results[i] = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
}
var isDup = new Array(9) ;
for (var i = 0 ; i < 9 ; i++ ){
isDup[i] = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
}
var output = '' ;
var t = ' ' ;
var nl = '\n' ;

// Neeed To Check....

var x = 0 ;
var trs = $( '#stable tr' ) ;
trs.each( function() {
var y = 0 ;
$( this ).find( 'td' ).each( function() {
results[x][y] = $( this ) ;
y++ ;
}) ;
x++ ;
}) ;

// each row ---------------------------------------------------------------

for ( var x = 0 ; x < 9; x++ ) {
var aColumn = new Array(10) ;
for (var i = 0 ; i < 10 ; i++ ){ aColumn[i] = 0 ; }
// first pass -- count
for ( var y = 0 ; y < 9 ; y++ ) {
var val = results[x][y].html() ;
if ( val.length == 8 ) { val = 0 ; }
val = parseInt( val ) ;
if ( val > 0 ) { aColumn[val]++ ; }
}
// second pass -- mark isDup
for ( var y = 0 ; y < 9 ; y++ ) {
var val = results[x][y].html() ;
if ( val.length != 1 ) { val = 0 ; }
val = parseInt( val ) ;
if ( aColumn[val] > 1 ) {
isDup[x][y] = 1 ;
}
}
}

// each column -------------------------------------------------------------

for ( var y = 0 ; y < 9; y++ ) {
var aColumn = new Array(10) ;
for (var i = 0 ; i < 10 ; i++ ){ aColumn[i] = 0 ; }
// first pass -- count
for ( var x = 0 ; x < 9 ; x++ ) {
var val = results[x][y].html() ;
if ( val.length != 1 ) { val = 0 ; }
val = parseInt( val ) ;
if ( val > 0 ) { aColumn[val]++ ; }
}
// second pass -- mark isDup
for ( var x = 0 ; x < 9 ; x++ ) {
var val = results[x][y].html() ;
if ( val.length != 1 ) { val = 0 ; }
val = parseInt( val ) ;
if ( aColumn[val] > 1 ) {
isDup[x][y] = 1 ;
}
}
}

// each block --------------------------------------------------------------

var range = new Array(3) ;
range[0] = [ 0 , 1 , 2 ] ;
range[1] = [ 3 , 4 , 5 ] ;
range[2] = [ 6 , 7 , 8 ] ;

for ( var a = 0 ; a < 3 ; a++ ) {
for ( var b = 0 ; b < 3 ; b++ ) {
var rangeX = range[a] ;
var rangeY = range[b] ;
output = output + a + b + nl ;

var aColumn = new Array(10) ;
for (var i = 0 ; i < 10 ; i++ ){ aColumn[i] = 0 ; }
// first pass -- count
for ( var c = 0 ; c < rangeX.length ; c++ ) {
for ( var d = 0 ; d < rangeY.length ; d++ ) {
var x = rangeX[c] ;
var y = rangeY[d] ;

var val = results[x][y].html() ;
if ( val.length != 1 ) { val = 0 ; }
val = parseInt( val ) ;
if ( val > 0 ) { aColumn[val]++ ; }
}
}
// second pass -- mark isDup
for ( var c = 0 ; c < rangeX.length ; c++ ) {
for ( var d = 0 ; d < rangeY.length ; d++ ) {
var x = rangeX[c] ;
var y = rangeY[d] ;

var val = results[x][y].html() ;
if ( val.length != 1 ) { val = 0 ; }
val = parseInt( val ) ;
if ( aColumn[val] > 1 ) { isDup[x][y] = 1 ; }
}
}
}
}

// and mark ----------------------------------------------------------------
output = '' ;
for ( var x = 0 ; x < 9; x++ ) {
for ( var y = 0 ; y < 9 ; y++ ) {
var val = results[x][y].html() ;
var dup = isDup[x][y] ;
if ( val.length != 1 ) { val = 0 ; }
val = parseInt( val ) ;
if ( dup == 1 ) { make_red( results[x][y] ) ; }
else { unmake_red( results[x][y] ) ; }
}
output = output + nl ;
}
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// make_red
//------------------------------------------------------------------------------
function make_red ( td ) {
td.css( 'color' , 'red' ) ;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// make_red
//------------------------------------------------------------------------------
function unmake_red ( td ) {
td.css( 'color' , '#000' ) ;
}
//------------------------------------------------------------------------------
This code has only been tested in Firefox 3.0. If you have problems, please report them here. And nothing say "Hey, you won!" when the puzzle is solved yet. I figure that will come when I can generate new puzzles. Sorry.

The next bit, the tricky bit, would be to generate new puzzles. I don't have that yet. But if I can make 'em up, I can put 'em into the puzzle. Feel free to try it.

2 comments:

  1. First of all, great script!
    But, how can I generate random combinations each time the page is reloaded so that the puzzle changes?

    ReplyDelete
  2. My solution, which I have not implemented, would be to take a solver script, throw some random numbers into random position, see if it's solvable from that, and push them in.

    Problem with that is that the solver is slow. I have one in Perl that I cannot imagine could be much faster, and putting it in Javascript on the client machine would make it slower, and a slow UI is the kiss of death.

    The solution there is to keep a batch of unsolved puzzles and AJAX 'em into position as needed, perhaps having a crontab run every hour, saying "when the number of unsolved puzzles is less than 100, generate 400 more puzzles".

    But that's just my take. Good luck in whatever you try.

    ReplyDelete