practica2_vallesquino

code format="javascript"
 * 1) !/usr/bin/smjs

/*Practica 2: Resolver un sudoku incompleto con javascript*/

/** * Definición de la clase Sudoku */ function Sudoku { /*Datos miembro de la clase*/ this.tablero = new Array (9); //Creamos una matriz (Array de Array) for(i=0;i<9;i++) this.tablero[i]=new Array(9); this.completo = false;

this.solucionValida = true; /*Funciones de la clase*/ this.asignarValor=asignarValor; this.comprobarCompleto=comprobarCompleto; this.comprobarFila=comprobarFila; this.comprobarColumna=comprobarColumna; this.comprobarSubtablero=comprobarSubtablero; this.completamenteRelleno=completamenteRelleno; this.repetirValorFila=repetirValorFila; this.repetirValorColumna=repetirValorColumna; this.repetirValorSubtablero=repetirValorSubtablero; this.repetirValor=repetirValor; this.sumaFila=sumaFila; this.sumaColumna=sumaColumna; this.comprobarSuma=comprobarSuma; this.primer0=primer0; this.posiblesSol=posiblesSol; this.toString=toString; this.resolver=resolver; }

/** * Función que asigna un valor a una casilla del sudoku */ function asignarValor(fila, columna, valor){

//asignaremos un valor siempre y cuando estemos dentro del tablero y éste este comprendido del 1 al 9.

if(valor >=1 && valor <=9 && fila >= 0 && fila <=8 && columna >=0 && columna <=8){

this.tablero[fila][columna] = valor;

}

else if(valor<1 || valor>9){

print(" **Solo puedes introducir valores comprendidos entre el #1 y el #9 ** ");

}

else if(fila<0 || fila>8 || columna<0 || columna>8){

print(" ** Se ha salido fuera del rango del casillero ** ");

} }

/** * Funcion que comprueba que estan todas las casillas rellenas */ function comprobarCompleto{

var completo = true;

for(i=0; i <9 && (completo == true); i ++){

for(j=0; j <9 && (completo == true); j ++){

if (this.tablero[i][j]==0){

completo = false;

}

}

}

return completo;

}

/** * Funcion que comprueba si una fila es correcta (estan los valores del 1 al 9) */ function comprobarFila(fila){

var solucionValida=true;

//si solucionValida dejase de ser true no seguimos buscando.

for(valor=1;valor<=9 && (solucionValida==true);valor++){

solucionValida=false;

for(j=0;j<=8;j++){

if (this.tablero[fila][j]==valor){

solucionValida=true;

break;

}

}

}

return solucionValida;

}

/** * Funcion que nos comprueba si en una columna pasada como argumento estan los valores del 1 al 9. */

function comprobarColumna(columna){

var solucionValida=true;

for(valor=1;valor<=9 && (solucionValida==true);valor++){

solucionValida=false;

for(i=0;i<=8;i++){

if (this.tablero[i][columna]==valor){

solucionValida=true;

break;

}

}

}

return solucionValida;

}

/**

* Funcion que nos comprueba si en un subtablero, pasado su indice como argumento, se encuentran

* los valores del 1 al 9,cada vez que encuentre un valor, en un subtablero auxiliar copia un -1 en

* esa posicion,luego se comprueba que ese subtablero esta completo de -1s.

*/

function comprobarSubtablero(indice){

var subtableroCopia = new Array (3); for(i=0;i<3;i++){ subtableroCopia[i]=new Array(3); }   //fila,columna,me permite conocer donde empiezo a recorrer el tablero en forma de 3x3.

var fila=parseInt((indice-1)/3)*3;

var columna=((indice-1)%3)*3;

for(valor=1;valor<=9 && (encontrado==true);valor++){

encontrado = false;

for(i=fila; i<=(fila+2) && (encontrado ==false);i++){

for(j=columna; j<=(columna+2)&& (encontrado ==false);j++){

if((this.tablero[i][j]==valor) && (encontrado==false)){

a=(i-fila);//Esta a y b es para que le indique que los indices del subtableroCopia deben comenzar en cero.

b=(j-columna);

subtableroCopia[a][b]=-1; //Si me encuentra el valor que inserte un -1 en su casilla correspondiente.

encontrado=true;

}

}

}

}

var solucionValida = true;

for(i=0;i<=2;i++){//Hago un bucle que me recorra la submatriz para comprobar que este llena de -1 y si es asi que me devuelva true

for(j=0;j<=2;j++){

if(subtableroCopia[i][j] != -1){

solucionValida = false;

break;

}

}

}

return solucionValida;

}

/** * Funcion que comprueba que el sudoku está correcto */ function completamenteRelleno{

var completo = this.comprobarCompleto;

var solucionValida=false;

var solucionValida1 = false;

var solucionValida2 = false;

var solucionValida3 = false;

for(fila=0;fila<=8;fila++){

solucionValida1 = solucionValida1 & this.comprobarFila(fila);

}

if(solucionValida1)

for(columna=0;(columna<=8)&&(solucionValida1);columna++){

solucionValida2 = solucionValida2 & this.comprobarColumna(columna);

}

if(solucionValida2)

for(indice=1;(indice<=9)&&(solucionValida2);indice++){

solucionValida3 = solucionValida3 & this.comprobarSubtablero(indice);

}

if(solucionValida3)

solucionValida = completo;

return solucionValida;

}

/**

* Funcion que nos comprueba si un valor que introduzcamos como argumento se encuentra ya en esa

* fila, tambien pasada como argumento.

*/

function repetirValorFila(fila,valor){

var solucionValida=true; var j=0;

do{

if(this.tablero[fila][j] == valor){

solucionValida=false;

}

j++;

}while(j<=8 && (solucionValida==true));

return solucionValida;

}

/**

* Funcion que nos comprueba si un valor que introduzcamos como argumento se encuentra ya en esa

* columna, tambien pasada como argumento.

*/

function repetirValorColumna(columna,valor){

var solucionValida=true; var i=0;

do{

if(this.tablero[i][columna] == valor){

solucionValida=false;

}

i++;

}while(i<=8 && (solucionValida==true));

return solucionValida;

}

/**

* Funcion que nos comprueba si un valor que introduzcamos como argumento se encuentra ya en ese

* subtablero, pasado su indice como argumento.

*/

function repetirValorSubtablero(indice,valor){

var fila=parseInt((indice-1)/3)*3;

var columna=((indice-1)%3)*3;

var solucionValida=true;

for(i=fila;(solucionValida) && (i<=(fila+2)) ;i++){

for(j=columna;(solucionValida) && (j<=(columna+2)); j++){

if (this.tablero[i][j]==valor){

solucionValida = false;

}

}

}

return solucionValida;

}

/**

* Método que comprueba que los metodos implementados anteriormente: repetirValorFila,

* repetirValorColumna y repetirValorSubtablero al aplicarlos a la vez a un tablero,

* la solucion sera valida cuando el valor a introducir no se encuentra ni en la fila, ni

* columna ni en el subtablero.

*/

function repetirValor(fila,columna,valor){

var solucionValida=false;

var solucionValida1 = false;

var solucionValida2 = false;

var solucionValida3 = false; //formula para calcular el indice de una submatriz mediante una posicion

var indice =((parseInt(fila/3)*3)+(parseInt(columna/3)) + 1);

if(valor >=1 && valor <=9 && fila >= 0 && fila <=8 && columna >=0 && columna <=8 && this.tablero[fila][columna]== 0){

solucionValida1 = this.repetirValorFila(fila,valor);

if (solucionValida1)

solucionValida2 = this.repetirValorColumna(columna,valor);

if (solucionValida2)

solucionValida3 = this.repetirValorSubtablero(indice,valor);

if (solucionValida3)

solucionValida = true;

}

return solucionValida;

}

/**

* Metodo que suma todos los elementos de la fila introducida como argumento.

*/

function sumaFila(fila){

var suma=0;

for(j=0;j<=8;j++){

suma = suma + this.tablero[fila][j];

}

return suma;

}

/**

* Metodo que suma todos los elementos de la columna introducida como argumento.

*/

function sumaColumna(columna){

var suma=0;

for(i=0;i<=8;i++){

suma = suma + this.tablero[i][columna];

}

return suma;

}

/**

* Metodo que comprueba que cada fila sume lo mismo que cada columna.

*/

function comprobarSuma{

var solucionValida = true;

for(i=0;i<=8 && (solucionValida);i++){

for (j=0;j<=8 &&(solucionValida);j++){

if(this.sumaFila(i) != this.sumaColumna(j)){

solucionValida = false;

}

}

}

return solucionValida;

}

/**

* Método que nos indica cual es la primera posicion vacia en el tablero del Sudoku

*/

function primer0 {

var encontrado=false;

var pos =new Array(2);

for(i=0;(i<9)&&(!encontrado);i++)

for(j=0;(j<9)&&(!encontrado);j++)

if(this.tablero[i][j]==0){

pos[0]=i;

pos[1]=j;

encontrado=true;

}

return pos;

}

/**

* Método que sirve para conseguir los posibles valores que podamos asignar a una

* posicion dada por la fila y columna pasada como argumento

*/

function posiblesSol(fila,columna){

var i=0;

var v=new Array (9);

var soluciones;

for(valor=1;valor<=9;valor++){

if(this.repetirValor(fila,columna,valor)==true){

v[i]=valor;

i++;

}

}

soluciones=new Array(i);

for(j=0;j<i;j++)

soluciones[j]=v[j];

return soluciones;

}

/** * Función que convierte en un string la matriz del tablero del sudoku */ function toString { var tabla=new Array(9); for ( k=0; k < 9 ; k++ ){ tabla[k]=""; for ( i=0; i < 9 ; i++ ){ tabla[k]=tabla[k]+String(this.tablero[k][i])+" ";//Formato que tendrá la fila que se imprimira en pantalla. } }  return tabla; }

/** * Función recursiva que resuelve un sudoku incompleto. No se porque no funciona correctamente :( */ function resolver{

//asignamos a nuestras variables sus correspondientes valores

//para la comprobacion

var valorAsig=false;

var posicion = this.primer0;

var fila=posicion[0];

var columna=posicion[1];

//Caso base 1

if(this.completamenteRelleno==true)

return true;

//Guardamos en valores los posibles valores que se puedan

//introducir en esa posicion

var valores=this.posiblesSol(fila,columna);

//Caso base 2

if(valores.length < 1){

return false;

}

//Recorremos el vector con los posibles valores y asignamos el valor

for(i=0;(valorAsig==false)&&(i<valores.length);i++){

this.asignarValor(fila,columna,valores[i]);

//llamada recursiva

valorAsig=this.resolver;

if(valorAsig==true)

return true;

if(valorAsig==false){

//si el valor asignado a desencadenado una solucion erronea

//borramos esa posicion.

this.tablero[fila][columna]=0;

}

}

return false;

} /********************************PARTE USUARIO*******************************************/

//Creamos un sudoku var sdk=new Sudoku;

//Inicializamos su tablero a 0 for(i=0;i<9;i++) for(j=0;j<9;j++) sdk.tablero[i][j]=0;

var salir=true; while(salir){

//Menu de usuario

print(

"\n*************************************************************************\n"+

"**                                                                    **\n"+

"**   ## Bienvenido a SuDoKu....¡¡elija una opcion para comenzar!!##   **\n"+

"**                                                                    **\n"+ "**       1. ¡¡Jugar!!                                                 **\n"+ "**       2. Crear un Sudoku                                          **\n"+

"**       3. Borrar el Sudoku actual                                   **\n"+

"**       4. **********************Salir*************************      **\n"+

"**                                                                    **\n"+

"*************************************************************************\n");

//Tomamos la opcion del menu a realizar

var fila,columna,valor,opcion;

do{

print("\n****************** Introduzca la opcion deseada  ********************** \n"); var entrada = readline; opcion = parseInt(entrada); }while (opcion<1 || opcion >4);

//Seleccion de opciones de la clase PruebaSudoku.

switch (opcion){

case 1: //En la opcion 1 podremos jugar al sudoku

print(

"\n*************************************************************************\n"+

"**                    Opcion 1 : ## ¡¡¡A jugar!!! ##                  **\n"+

"*************************************************************************\n");

print("\n *****PARA DEJAR DE INSERTAR VALORES INTRODUCIR UNA LETRA CUANDO PIDA LA FILA********");

//Pedimos la fila

print("\n ******** [ Introduzca el índice de la fila ] ******** \n");

entrada = readline;

fila = parseInt(entrada);

while(fila>=0 || fila<9){//Saldremos cuando insertemos un numero de fila no valido.

//Pedimos la columna

print("\n ******** [ Introduzca el índice de la columna ] ******** \n");

entrada = readline;

columna = parseInt(entrada);

//Pedimos la columna

print("\n ******* Introduzca el valor de la casilla : ["+fila+"] ["+columna+"] ********"); entrada = readline;

valor = parseInt(entrada);

//Comprobamos si el dato introducido es correcto

if(sdk.repetirValor(fila,columna,valor))

sdk.asignarValor(fila,columna,valor);

else

print("\n ******DATO INCORRECTO****** \n ***** Recuerde : No puede introducir un valor que ya se encuentre en esa fila, columna y submatriz *****");

//Imprimimos el estado del sudoku

for ( j=0; j < 9 ; j++ ) print(sdk.toString[j]);

//Volvemos a leer la fila print("\n *****PARA DEJAR DE INSERTAR VALORES INTRODUCIR UNA LETRA CUANDO PIDA LA FILA********");

print("\n ******** [ Introduzca el índice de la fila ] ******** \n");

entrada = readline;

fila = parseInt(entrada);

}

//Ahora mostramos el tablero. for ( j=0; j < 9 ; j++ ) print(sdk.toString[j]);

//Por ultimo comprobamos la validez del sudoku.

if ((sdk.completamenteRelleno== true) && (sdk.comprobarSuma == true)){

print("\n Este Sudoku esta ****CORRECTO**** ");

}

else{

print("\n Este Sudoku esta ****INCORRECTO**** ");

}

break;

case 2://Crear un sudoku print( "\n*************************************************************************\n"+

"**               Opcion 2 : ## Crear un Sudoku ##                     **\n"+

"*************************************************************************\n");     do{

print(

"\n*************************************************************************\n"+

"**                   ## Eliga el nivel de dificultad ##               **\n"+ "**                                                                    **\n"+ "**                              1. Facil                              **\n"+ "**                              2. Normal                             **\n"+

"**                              3. Chungo                             **\n"+ "**                                                                    **\n"+

"*************************************************************************\n");

entrada = readline;

var nivel = parseInt(entrada); }while(nivel<1 || nivel >3);

//Creamos un sudoku aleatorio como maximo con N valores var N = nivel*10; for(i=0;i<N;i++){ var fil=Math.round(8*Math.random); var col=Math.round(8*Math.random); var posible_valor=1+Math.round(8*Math.random);//Nos dara un entero entre 1 y 9. if(sdk.repetirValor(fil,col,posible_valor)) sdk.tablero[fil][col]=posible_valor; }     for ( j=0; j < 9 ; j++ ) print(sdk.toString[j]); break;

print( "\n*************************************************************************\n"+

"**                  Opcion 3 : ## Borrar Sudoku ##                    **\n"+

"*************************************************************************\n");

case 3: //En la opcion 3 podemos borrar el sudoku.

for(i=0;i<=8;i++)

for(j=0;j<=8;j++)

sdk.tablero[i][j]=0;

print("\n *******El Sudoku ha sido borrado********* \n");

// Ahora mostramos el tablero. for ( j=0; j < 9 ; j++ ) print(sdk.toString[j]);

break;

case 4://Salir print( "\n*************************************************************************\n"+

"**                      Opcion 4 : ## Salir ##                        **\n"+

"*************************************************************************\n");     salir=false;

break;

} } code