Tema: Sudoku
Ver Mensaje Individual
  #2 (permalink)  
Antiguo 22/08/2005, 17:40
Avatar de derkenuke
derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 20 años, 6 meses
Puntos: 45
Mientras el script anterior me genera una pagina asi:

He conseguido crear esto:

A simple vista no tiene mucha diferencia. Pero en cuanto a programación sí. Éste ya diferencia los cuadros de 3x3, y además no deja utilizar el mismo numero en el mismo cuadrante. La piedra angular consiste en la creación del array. En vez de dos dimensiones, el array sodoku tiene cuatro dimensiones. Es decir, dos pares de coordenadas.

sodoku[caja_fila][caja_columna][celda_fila][celda_columna]

Asi es mas facil controlar en qué cuadrante nos encontramos.

Como sé que a nadie le apetece leerse un script de 500 paginas, lo he partido en cachitos mas entendibles:

Código PHP:
<style>
.
fila_celdas {
    
height:20px;
    
clear:both;
}
.
fila_cuadrantes {
    
height:62px;
    
clear:both;
    
text-align:center;
}
.
celda {
    
bordersolid 1px black;
    
text-align:center;
    
width20pxheight:20px;
    
font-size:10px;
    
font-family:tahoma;
    
float:left;
    
margin:0px;
}
.
caja {
    
width75pxheight:75px;
    
float:left;
    
text-align:center;
    
margin:0px;
}
</
style
La declaración de estilo CSS:
Es más engorrosa, pero define todo lo necesario para que queden formateados los divs sin necesidad de HTML de más. 'fila_cuadrantes' contiene un fila de 'caja', y 'caja' contiene 3 capas de 'fila_celdas', y 'fila_celdas' contiene a su vez 3 divs de 'celda'; creando asi la estructura deseada.

Código PHP:
var X=9;    // celdas de lado


//INICIALIZACION DEL ARRAY SODOKU (Array de 4 dimensiones)
var sodoku=new Array();        //contiene todas las cajas (X cajas)
for(var x=0;x<X/3;x++) {        //cajaX
    
sodoku[x]=new Array(X/3);
    for(var 
y=0;y<X/3;y++) {    //cajaY
        
sodoku[x][y]=new Array(X/3);
        for(var 
i=0n=0;i<3;i++) {        //celdaX
            
sodoku[x][y][i]=new Array(3);
            for(var 
j=0;j<3;j++) {    //celdaY
                
sodoku[x][y][i][j]=new Array(3);
                
sodoku[x][y][i][j]= -1//(n++)+x+y;
            
}
        }
    }
}
// asi el array queda sodoku[cajaX][cajaY][celdaX][celdaY]



//funcion document.write, no tan engorrosa y con opcion de salto <br />
function e(q,salto) { document.write(q); if(saltodocument.write("<br />"); }



// imprimimos la estructura HTML de divs para luego solo tener que poner los valores
for(var x=0x<X/3x++) {        //cajaX
    
e('<div class="fila_cuadrantes">');
    for(var 
y=0y<X/3y++) {    //cajaY
        
e('<div class="caja" id="caja_'+x+'_'+y+'">');
        for(var 
i=0;i<3;i++) {        //celdaX
            
e('<div class="fila_cajas">');
            for(var 
j=0;j<3;j++) {    //celdaY
                
e('<div class="celda" id="sodoku_'+x+'_'+y+'_'+i+'_'+j+'"></div>');
            }
            
e('</div>');
        }
        
e('</div>');
    }
    
e('</div>');
}
e("&nbsp;",1);


//actualiza los valores del array sodoku en la estructura de divs
function imprime_sodoku() {
    for(var 
x=0;x<X/3;x++)         //cajaX
        
for(var y=0;y<X/3;y++)     //cajaY
                
for(var i=0;i<3;i++)        //celdaX
                    
for(var j=0;j<3;j++)    //celdaY
                        
document.getElementById("sodoku_"+x+"_"+y+"_"+i+"_"+j).innerHTML=sodoku[x][y][i][j];

Inicialización, estructura HTML y funciones básicas:
Inicializa las variables y el array multidimensional 'sodoku'. Crea el HTML necesario (un par de divs) sin contenido. Define la funcion 'e' (para comodidad solamente (debug)), y la funcion 'imprime_sodoku' que se encarga de rellenar la estructura.

Código PHP:
/**************************************************************************/
// FUNCIONES GET_____

//nos devuelve un array con todos los elementos de una fila respecto a una celda
function getFila(x,y,i,j) {
    var 
dev=new Array();
    for(
_y=0_y<X/3_y++)        //fila de cajas
        
for(_j=0_j<X/3_j++)
            
dev.splice(dev.length0sodoku[x][_y][i][_j]);    //cogemos la fila entera de celdas
    
return dev;
}

//nos devuelve un array con todos los elementos de una columna respecto a una celda
function getColumna(x,y,i,j) {
    var 
dev=new Array();
    for(
_x=0_x<X/3_x++)        //columna de cajas
        
for(_i=0_i<3_i++)        // cada celda en la columna _j
            
dev.splice(dev.length0sodoku[_x][y][_i][j]);
    return 
dev;
}

//nos devuelve un solo array con la caja de la celda dada (solo tiene una dimension)
function getCaja(x,y) {
    var 
dev=new Array();
    for(
_i=0_i<3_i++)
        for(
_j=0_j<X/3_j++)
            
dev.splice(dev.length0sodoku[x][y][_i][_j]);
    return 
dev;

Funciones get___:
Las funciones get___ devuelven un array unidimensional de lo que se le pida. Asi es mas facil trabajar con los numeros que debemos excluir a la hora de colocarlos aleatoriamente en la estructura.

Código PHP:
/**************************************************************************/
// RELLENAR EL SODOKU


var nums_posibles=new Array(X);
for(var 
a=0;a<X;a++) nums_posibles[a]=a;

//busca un numero dentro de un array de numero
// y devuelve su indice. Si no lo encuentra devuelve -1
function numAt(arr,num) {
    for(var 
a=0a<arr.lengtha++)
        if( 
arr[a]==num )
            return 
a;
    return -
1;
}

//elimina del array 'total' todos los numeros del array 'posibilidades', y devuelve el nuevo 'total'
function eliminaPosibilidades(totalposibilidades) {
    for(var 
a=0a<posibilidades.lengtha++) {
        var 
esta=numAt(total,posibilidades[a])
        if( 
esta!=-1)
            
total.splice(esta,1);
    }
    return 
total;
}

//copia un array y lo devuelve
function copia(arr) {
    var 
dev=new Array();
    for(var 
a=0;a<arr.lengtha++)
        
dev[dev.length]=arr[a];
    return 
dev;
}




//rellenamos celda a celda
for(var x=0;x<X/3;x++)         //cajaX
    
for(var y=0;y<X/3;y++)  //cajaY
            
for(var i=0;i<3;i++)        //celdaX
                
for(var j=0;j<3;j++) {    //celdaY
                    
                    
e('sodoku['+x+']['+y+']['+i+']['+j+']: ');
                    var 
nums=copia(nums_posibles);
                    
nums=eliminaPosibilidades(numsgetFila(x,y,i,j) );
                    
nums=eliminaPosibilidades(numsgetColumna(x,y,i,j) );
                    
nums=eliminaPosibilidades(numsgetCaja(x,y) );
                    if(
nums.length!=0)    //nos hemos quedado sin numeros para poder poner
                        
sodoku[x][y][i][j]=numsparseInt(Math.random()*nums.length) ];
                    else
                        
sodoku[x][y][i][j]=-1;
                    
e("Posibilidades: "+nums+" --> <b>"+sodoku[x][y][i][j]+"</b>",1);
                    
                } 
Relleno aleatorio:
Como antes, nums_posibles es una matriz con todos los numeros del 0 al 9. La funcion 'numAt' es la que busca un numero en un array y devuelve su indice si lo encuentra. 'eliminaPosibilidades' borra del array total todos los elementos de 'posibilidades' si los encuentra (para excluir numeros posibles). La funcion 'copia' devuelve una copia del array pasado por argumento.
Después, [b]rellenamos[b]: Esto se hace mas legible que antes: Por cada celda se dan todas las posibilidades. A estas posibilidades iremos quitando los numeros que encontremos en su fila, su columna, y su cuadrante. Si nos quedamos sin numero por poner, colocamos el dichoso "-1".

Con un
Código PHP:
imprime_sodoku(); 
podremos ver el sodoku en pantalla, y ademas si hacemos al final
Código PHP:
//en rojo los "-1"
for(var x=0;x<X/3;x++)         //cajaX
    
for(var y=0;y<X/3;y++)  //cajaY
            
for(var i=0;i<3;i++)        //celdaX
                
for(var j=0;j<3;j++)    //celdaY
                    
if(sodoku[x][y][i][j]==-1)
                        
document.getElementById("sodoku_"+x+"_"+y+"_"+i+"_"+j).style.backgroundColor="red"
colorearemos de rojo los divs que contengan -1 para "cazarlos" mejor.


Bueno, el resultado lo he puesto antes:

Ahora me queda arreglar el "-1", que creo que lo voy a intentar por atributos HTML. A ver si me sale y lo puedo postear completo.

__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.