Ver Mensaje Individual
  #11 (permalink)  
Antiguo 23/12/2014, 16:27
amchacon
 
Fecha de Ingreso: julio-2012
Mensajes: 375
Antigüedad: 11 años, 9 meses
Puntos: 28
Respuesta: Sudoku en borland c++

Aquí va mi código ^^

Código C++:
Ver original
  1. #include <iostream>
  2. #include <ctime>
  3. #include <cstdlib>
  4. using namespace std;
  5.  
  6. const int TAM = 9; // Maximo numero que puede haber en el sudoku, numeros más grandes o mas pequeños generan sudokus con cuadrados de 2x2,4x4,5x5... Por defecto lo dejamos en el clásico 3x3
  7.  
  8. bool resuelto(short Tablero[TAM][TAM]);
  9. void generarSudoku(short Tablero[TAM][TAM]);
  10.  
  11. //funcion raiz natural, mas eficiente que sqrt y que uso para sacar el tamaño de cada cuadrado (raiz(TAM))
  12. inline int raiz(int n)
  13. {
  14.     for (int i = 2;i*i<=n;i++)
  15.     {
  16.         if (i*i == n) return i;
  17.     }
  18.     throw "Error no valido";
  19. }
  20. void mostrarTablero(short Tablero[TAM][TAM])
  21. {
  22.     for (int i = 0; i<TAM; i++)
  23.     {
  24.         for (int j = 0; j<TAM; j++)
  25.         {
  26.             cout<<(int)Tablero[i][j]<<" | ";
  27.         }
  28.         cout<<endl;
  29.     }
  30.  
  31.     cout<<endl<<endl;
  32. }
  33.  
  34. int main()
  35. {
  36.     srand(time(0));
  37.     short Tablero[TAM][TAM];
  38.     generarSudoku(Tablero);
  39.  
  40.     mostrarTablero(Tablero);
  41.  
  42.     cout<<resuelto(Tablero)<<endl;
  43.     return 0;
  44. }
  45.  
  46. // Generamos un sodoku, no es necesario que tablero este inicializado
  47. void generarSudoku(short Tablero[TAM][TAM])
  48. {
  49.     #define SUBCUADRADO(i,j) (i/TAM_N+(j/TAM_N)*TAM_N)
  50.     const int TAM_N = raiz(TAM); // tamaño de cada cuadrado, corresponde a su raiz
  51.     bool Tabla[TAM][TAM][TAM]; // Tabla(x,y,valor) con los valores probados en una casilla, true si fue probado
  52.     bool Tabla_Fila[TAM][TAM]; // Tabla(y,valor) con los valores existen en la fila, true si existe
  53.     bool Tabla_Columna[TAM][TAM]; // Tabla(x,valor) con los valores probados en una columna, true si fue probado
  54.     bool Tabla_Cuadrado[TAM][TAM]; // Tabla(SUBCUADRADO,valor) con los valores probado en un cuadrado, true si fue probado
  55.     int cont;
  56.  
  57.     // Inicializar las tablas
  58.  
  59.     for (int i = 0; i<TAM; i++)
  60.     {
  61.         for (int j = 0; j<TAM; j++)
  62.         {
  63.             Tablero[i][j] = -1; // inicializo el sudoku
  64.             for (int k = 0; k<TAM; k++)
  65.             {
  66.                 Tabla[i][j][k] = false;
  67.                 Tabla_Fila[j][k] = false;
  68.                 Tabla_Columna[i][k] = false;
  69.             }
  70.         }
  71.     }
  72.  
  73.     for (int i = 0; i<TAM; i++)
  74.     {
  75.         for (int k = 0; k<TAM; k++)
  76.         {
  77.             Tabla_Cuadrado[i][k] = false;
  78.         }
  79.     }
  80.  
  81.  
  82.     // Bucle principal
  83.  
  84.     for (int i = 0; i<TAM; i++)
  85.     {
  86.         for (int j = 0; j<TAM; j++)
  87.         {
  88.             int aux = (rand()%TAM); // Numero aleatorio
  89.             bool fallo;
  90.  
  91.             if (Tablero[i][j] >= 0) // Si ya contenía algo, quitamos sus valores de las tablas
  92.             {
  93.                 const int valor = Tablero[i][j] - 1;
  94.  
  95.                 Tabla_Fila[j][valor] = false;
  96.                 Tabla_Columna[i][valor] = false;
  97.                 Tabla_Cuadrado[SUBCUADRADO(i,j)][valor] = false;
  98.             }
  99.             cont = 0; //variable control para el bucle, solo vamos a comprobar los 9 valores posibles
  100.  
  101.             do
  102.             {
  103.                 aux = ((aux+1)%TAM);//aumento en una unidad
  104.                 fallo = (Tabla[i][j][aux] |        // tabla de valores probados en esa casilla
  105.                          Tabla_Fila[j][aux] |      // tabla de valores probados en esa fila
  106.                          Tabla_Columna[i][aux] |   // tabla de valores probados en esa columna
  107.                          Tabla_Cuadrado[SUBCUADRADO(i,j)][aux]); // tabla de valores probados en ese cuadrado
  108.                 cont++; // una iteracion mas
  109.             }
  110.             while( fallo && cont < TAM); // mientras no encontremos un valor que no este en las tablas y no hayamos recorrido todos los valores...
  111.  
  112.             if (!fallo) //añadimos
  113.             {
  114.                 Tablero[i][j] = aux+1; // Tablero a devolver, los numeros son del 1-9
  115.                 Tabla[i][j][aux] = true; // Marcamos en la tabla de casillas un nuevo valor
  116.                 Tabla_Fila[j][aux] = true; // Marcamos un nuevo valor en la fila
  117.                 Tabla_Columna[i][aux] = true; // Marcamos un nuevo valor en la columna
  118.                 Tabla_Cuadrado[SUBCUADRADO(i,j)][aux] = true; // Marcamos un nuevo valor en el cuadrado
  119.             }
  120.             else //Si no encontramos ningun valor válido para añadir
  121.             {
  122.                 for (int k = 0; k<TAM; k++)
  123.                 {
  124.                     Tabla[i][j][k] = false; // reseteamos la tabla de valores probados
  125.                 }
  126.  
  127.                 Tablero[i][j] = -1; // borramos la casilla
  128.                 j -= 2; // retrocedemos, son dos unidades porque luego el for me avanza una
  129.  
  130.                 if (j < -1) // si nos hemos pasado de la fila, retrocedemos una columna
  131.                 {
  132.                     j =TAM-2;
  133.                     i--;
  134.                     if(i < 0) // if de depuración, en principio no debería activarse nunca pues indica que nos hemos salido del sudoku
  135.                     {
  136.                         cerr<<"Error inesperado"<<endl;
  137.                         throw "Error inesperado";
  138.                     }
  139.                 }
  140.  
  141.             }
  142.         }
  143.     }
  144. }
  145.  
  146. /* Funcion auxiliar para depuración, reciclado de otro proyecto por lo que ha sido necesario añadir algunas constantes
  147.  
  148. Se usa para comprobar que el sudoku está correctamente generado (no hay repeticiones en cada fila/columna/cuadrado)
  149. */
  150.  
  151. const int MAX = TAM;
  152. const int MAX_N = 3;
  153. const int Suma = 45;
  154.  
  155. bool resuelto(short Tablero[TAM][TAM])
  156. {
  157.     // Macro para comprobar repeticiones
  158.  
  159. #define COMPROBAR_REPETICIONES if (i != 0) \
  160.     for (short k = i-1; k > -1;k--) \
  161.             if (Repeticiones[i] == Repeticiones[k]) \
  162.                     return false;
  163.  
  164.     // Lineas horizontales
  165.  
  166.     short Repeticiones[MAX];
  167.  
  168.     for (short i = 0; i < MAX; i++)
  169.         Repeticiones[i] = 0;
  170.  
  171.     short Contador = 0;
  172.  
  173.     for (short j = 0; j < MAX; j++)
  174.     {
  175.  
  176.         for (short i = 0; i < MAX; i++)
  177.         {
  178.             Repeticiones[i] = Tablero[i][j];
  179.  
  180.             COMPROBAR_REPETICIONES
  181.  
  182.         }
  183.  
  184.     }
  185.  
  186.     // Lineas verticales
  187.  
  188.     for (short j = 0; j < MAX; j++)
  189.     {
  190.         Contador = 0;
  191.         for (short i = 0; i < MAX; i++)
  192.         {
  193.             Repeticiones[i] = Tablero[j][i];
  194.  
  195.             COMPROBAR_REPETICIONES
  196.         }
  197.     }
  198.  
  199.  
  200.     // Cuadrados
  201.  
  202.     for (short l = 0; l < MAX_N; l++)
  203.         for (short k = 0; k < MAX_N; k++)
  204.         {
  205.             Contador = 0;
  206.             for (short j = k*MAX_N; j < (MAX_N*k)+MAX_N; j++)
  207.                 for (short i = l*MAX_N; i < (l*MAX_N)+MAX_N; i++)
  208.                 {
  209.                     Contador += Tablero[i][j];
  210.                 }
  211.  
  212.             // Aquí no podemos usar la macro, asi que usamos otro método
  213.  
  214.             if (Contador != Suma) // Suma es lo que da si se suma 1+2+3+4+5+6+7+8+9
  215.             {
  216.                 cout<<l<<','<<k<<endl;
  217.                 return false;
  218.             }
  219.  
  220.         }
  221.  
  222.     return true;
  223. }