Você está na página 1de 20

/*

*
*
*
*/
using
using
using
using
using

Laboratorio III
SUDOKU
Lenguaje Programacion :
C#
Enfoque greedy + backtrack. Soporta tableros vacos

System;
System.Collections.Generic;
System.Text;
System.Collections;
System.Windows.Forms;

namespace Sudoku
{
public class CSudoku
{
//================================================//
//--- Estructuras
public struct Datos
{
public ArrayList ListaPosibles;
public int Valor;
}
//--- Atributos
public Datos[,] Tabla;
datos

//--- La tabla sobre la cual se van a sacar y mostrar los

public ArrayList Resultados = new ArrayList();


resultados hallados
private static int NroRespuesta = 0;
hallados

//--- Contiene el valor todos los


//--- Indica el numero de resultados

//--- Constructores
public CSudoku()
{
Tabla = new Datos[9, 9];
IniciarDatos();
}
//--- Metodos
private void IniciarDatos()
{
for (int temp_fila = 0; temp_fila < 9; temp_fila++)
{
for (int temp_columna = 0; temp_columna < 9; temp_columna++)
{
Tabla[temp_fila, temp_columna].Valor = 0;
Tabla[temp_fila, temp_columna].ListaPosibles = new ArrayList();
}
}
}
/// <summary>
/// Mediante este modulo el usuario puede ingresar datos en modo consola
/// </summary>

public void LeerDatos()


{
bool Continuar = true;
while (Continuar)
{
Console.Write("Posicion fila
: ");
int fila = int.Parse(Console.ReadLine());
Console.Write("Posicion columna : ");
int columna = int.Parse(Console.ReadLine());
Console.Write("Valor
: ");
int Valor = int.Parse(Console.ReadLine());
Tabla[fila, columna].Valor = Valor;
Tabla[fila, columna].ListaPosibles = new ArrayList();
Console.Write("Continuar (S/N) : ");
Continuar = (Console.ReadLine().ToUpper() == "S") ? true : false;
}
}
private int DeterminarGrupo(int fila, int columna)
{
if (fila < 3)
{
if (columna < 3)
return 1;
else
{
if (columna < 6)
return 2;
else

return 3;
}
}
else
{
if (fila < 6)
{
if (columna < 3)
return 4;
else
{
if (columna < 6)
return 5;
else
return 6;
}
}
else
{
if (columna < 3)
return 7;
else
{
if (columna < 6)
return 8;
else
return 9;
}

}
}
}
private
{
int
int
int
int

bool EstaEnGrupo(int fila, int columna, int Valor, int Grupo)


temp_fila_inicial = 0;
temp_columna_inicial = 0;
temp_fila_final = 0;
temp_columna_final = 0;

DeterminarDatos(ref temp_fila_inicial, ref temp_columna_inicial, ref temp_fila_final,


ref temp_columna_final, Grupo);
for (int temp_fila = temp_fila_inicial; temp_fila < temp_fila_final; temp_fila++)
{
for (int temp_columna = temp_columna_inicial; temp_columna < temp_columna_final;
temp_columna++)
{
if (Tabla[temp_fila, temp_columna].Valor == Valor)
return false;
}
}
return true;
}
private void DeterminarDatos(ref int temp_fila_inicial, ref int temp_columna_inicial, ref
int temp_fila_final, ref
int temp_columna_final, int Grupo)
{
switch (Grupo)

{
case 1: temp_fila_inicial = 0;
temp_columna_inicial = 0;
break;
case 2: temp_fila_inicial = 0;
temp_columna_inicial = 3;
break;
case 3: temp_fila_inicial = 0;
temp_columna_inicial = 6;
break;
case 4: temp_fila_inicial = 3;
temp_columna_inicial = 0;
break;
case 5: temp_fila_inicial = 3;
temp_columna_inicial = 3;
break;
case 6: temp_fila_inicial = 3;
temp_columna_inicial = 6;
break;
case 7: temp_fila_inicial = 6;
temp_columna_inicial = 0;
break;
case 8: temp_fila_inicial = 6;
temp_columna_inicial = 3;
break;
case 9: temp_fila_inicial = 6;
temp_columna_inicial = 6;
break;

}
temp_fila_final = temp_fila_inicial + 3;
temp_columna_final = temp_columna_inicial + 3;
}
public void Inicio()
{
Datos[,] TablaCopia = CopiarTabla();
CSudoku S = new CSudoku();
S.Tabla = TablaCopia;
}
/// <summary>
/// Hace una copia del atributo tabla
/// </summary>
/// <returns>Retorna una copia de la tabla</returns>
public Datos[,] CopiarTabla()
{
Datos[,] TablaCopia = new Datos[9, 9];
for (int fila = 0; fila < 9; fila++)
{
for (int columna = 0; columna < 9; columna++)
{
TablaCopia[fila, columna].Valor = Tabla[fila, columna].Valor;
if (Tabla[fila, columna].Valor == 0 && Tabla[fila, columna].ListaPosibles !=
null)
{
TablaCopia[fila, columna].ListaPosibles = new ArrayList();
foreach (object o in Tabla[fila, columna].ListaPosibles)

TablaCopia[fila, columna].ListaPosibles.Add(o);
}
}
}
return TablaCopia;
}
private bool EstaEnFila(int fila, int Valor)
{
for (int temp_columna = 0; temp_columna < 9; temp_columna++)
{
if (Tabla[fila, temp_columna].Valor == Valor)
return true;
}
return false;
}
private bool EstaEnColumna(int columna, int Valor)
{
for (int temp_fila = 0; temp_fila < 9; temp_fila++)
{
if (Tabla[temp_fila, columna].Valor == Valor)
return true;
}
return false;
}
private bool EstaEnGrupo(int fila, int columna, int Valor)
{
int temp_fila_inicial = 0;

int temp_columna_inicial = 0;
int temp_fila_final = 0;
int temp_columna_final = 0;
int Grupo = DeterminarGrupo(fila, columna);
DeterminarDatos(ref temp_fila_inicial, ref temp_columna_inicial, ref temp_fila_final,
ref temp_columna_final, Grupo);
for (int temp_fila = temp_fila_inicial; temp_fila < temp_fila_final; temp_fila++)
{
for (int temp_columna = temp_columna_inicial; temp_columna < temp_columna_final;
temp_columna++)
{
if (Tabla[temp_fila, temp_columna].Valor == Valor)
return true;
}
}
return false;
}
private int CuantosPosiblesEnFila(int fila, int Valor)
{
int k = 0;
for (int temp_columna = 0; temp_columna < 9; temp_columna++)
{
if (Tabla[fila, temp_columna].Valor > 0)
{
if (Tabla[fila, temp_columna].Valor == Valor)
k++;
}
else

{
foreach (object o in Tabla[fila, temp_columna].ListaPosibles)
{
if (int.Parse(o.ToString()) == Valor)
{
k++;
break;
}
}
}
}
return k;
}
private int CuantosPosiblesEnColumna(int columna, int Valor)
{
int k = 0;
for (int temp_fila = 0; temp_fila < 9; temp_fila++)
{
if (Tabla[temp_fila, columna].Valor > 0)
{
if (Tabla[temp_fila, columna].Valor == Valor)
k++;
}
else
{
foreach (object o in Tabla[temp_fila, columna].ListaPosibles)
{
if (int.Parse(o.ToString()) == Valor)

{
k++;
break;
}
}
}
}
return k;
}
/// <summary>
/// Inicia todos los valores que se pueden almacenar en cada espacio de la tabla, por
defecto debe de iniciarse
/// antes de realizar el Backtraking
/// </summary>
public void IniciarLista()
{
for (int temp_fila = 0; temp_fila < 9; temp_fila++)
{
for (int temp_columna = 0; temp_columna < 9; temp_columna++)
{
Tabla[temp_fila, temp_columna].ListaPosibles = new ArrayList();
}
}
for (int temp_fila = 0; temp_fila < 9; temp_fila++)
{
for (int temp_columna = 0; temp_columna < 9; temp_columna++)

{
if (Tabla[temp_fila, temp_columna].Valor == 0)
{
for (int k = 1; k < 10; k++)
{
if (!EstaEnColumna(temp_columna, k))
if (!EstaEnFila(temp_fila, k))
if (!EstaEnGrupo(temp_fila, temp_columna, k))
Tabla[temp_fila, temp_columna].ListaPosibles.Add(k);
}
}
}
}
}
/// <summary>
/// Intenta completar la tabla con un algoritmo voraz
/// </summary>
/// <returns>Retorna el valor que indica si es posible continuar con el algoritmo voraz,
recomendable realizar
/// un bucle while(Sudoku.PrimerPaso()){} para realizar todo lo posible con el algoritmo
/// </returns>
public bool PrimerPaso()
{
bool CambioAlguno = false;
IniciarLista();
for (int temp_fila = 0; temp_fila < 9; temp_fila++)
{
for (int temp_columna = 0; temp_columna < 9; temp_columna++)

{
if (Tabla[temp_fila, temp_columna].ListaPosibles.Count == 1)
{
Tabla[temp_fila, temp_columna].Valor = (int)Tabla[temp_fila,
temp_columna].ListaPosibles[0];
Tabla[temp_fila, temp_columna].ListaPosibles = new ArrayList();
CambioAlguno = true;
}
else
{
if (Tabla[temp_fila, temp_columna].Valor == 0)
{
for (int k = 0; k < Tabla[temp_fila, temp_columna].ListaPosibles.Count;
k++)
{
int r = int.Parse(Tabla[temp_fila,
temp_columna].ListaPosibles[k].ToString());
if (CuantosPosiblesEnFila(temp_fila, r) == 1)
{
Tabla[temp_fila, temp_columna].Valor = r;
Tabla[temp_fila, temp_columna].ListaPosibles = new ArrayList();
CambioAlguno = true;
break;
}
else
{
if (CuantosPosiblesEnColumna(temp_columna, r) == 1)

{
Tabla[temp_fila, temp_columna].Valor = r;
Tabla[temp_fila, temp_columna].ListaPosibles = new
ArrayList();
CambioAlguno = true;
break;
}
}
}
}
}
}
}
return CambioAlguno;
}
//--- Modo consola
public void Mostrar()
{
for (int temp_fila = 0; temp_fila < 9; temp_fila++)
{
for (int temp_columna = 0; temp_columna < 9; temp_columna++)
{
Console.Write(Tabla[temp_fila, temp_columna].Valor.ToString().PadRight(2));
if ((temp_columna + 1) % 3 == 0)
Console.Write(" !");
}
Console.WriteLine();
if ((temp_fila + 1) % 3 == 0)

Console.WriteLine("______________________");
}
Console.WriteLine("--------------------------------------------");
}
/// <summary>
/// Sirve para modo consola, muestra todas las soluciones que se pueden hallar a partir de
la matriz inicial
/// </summary>
/// <param name="S">El objeto de la clase CSudoku del cual se hallar la respuesta</param>
/// <param name="fila">Indica la posicion inicial de la fila, por defecto iniciar en
0</param>
/// <param name="columna">Indica la posicion inicial de la columna, por defecto iniciar en
0</param>
/// <param name="Valor">Indica el valor desde el cual se va a tratar de hallar una
respuesta,
/// por defecto 0
/// </param>
public void BackTrackingConsola(CSudoku S, int fila, int columna, int Valor)
{
if (fila == 9 || columna == 9)
{
S.Mostrar();
Console.WriteLine("===============================");
Console.WriteLine("Presione una tecla para continuar...");
Console.ReadKey();
}
else
{

if (S.Tabla[fila, columna].Valor == 0)
{
S.Tabla[fila, columna].Valor = Valor;
S.IniciarLista();
}
int temp_fila = 0;
int temp_columna = 0;
bool Continuar = true;
for (temp_fila = fila; temp_fila < 9; temp_fila++)
{
for (temp_columna = columna; temp_columna < 9; temp_columna++)
{
if (S.Tabla[temp_fila, temp_columna].Valor == 0)
{
Continuar = false;
break;
}
}
columna = 0;
if (!Continuar)
break;
}
if (temp_fila == 9 && temp_columna == 9)
BackTrackingConsola(S, 9, 9, 0);
else
{
if (S.Tabla[temp_fila, temp_columna].ListaPosibles.Count > 0)

{
foreach (object o in Tabla[temp_fila, temp_columna].ListaPosibles)
{
int r = int.Parse(o.ToString());
int Valor_Antiguo = S.Tabla[temp_fila, temp_columna].Valor;
BackTrackingConsola(S, temp_fila, temp_columna, r);
S.Tabla[temp_fila, temp_columna].Valor = Valor_Antiguo;
S.IniciarLista();
}
}
}
}
}
//--- Formas
/// <summary>
/// Sirve para modo windows formas, muestra todas las soluciones que se pueden hallar a
partir de
/// la matriz inicial
/// </summary>
/// <param name="S">El objeto de la clase CSudoku del cual se hallar la respuesta</param>
/// <param name="fila">Indica la posicion inicial de la fila, por defecto iniciar en
0</param>
/// <param name="columna">Indica la posicion inicial de la columna, por defecto iniciar en
0</param>
/// <param name="Valor">Indica el valor desde el cual se va a tratar de hallar una
respuesta,
/// por defecto 0</param>

/// <param name="data">Indica el valor de DataGridView sobre el cual se van a mostrar los
resultados
/// que se hallen</param>
public void BackTrackingFormas(CSudoku S, int fila, int columna, int
Valor,System.Windows.Forms.DataGridView
data)
{
if (fila == 9 || columna == 9)
{
int[,] Matriz = new int[9, 9];
for (int fila2 = 0; fila2 < 9; fila2++)
{
for (int columna2 = 0; columna2 < 9; columna2++)
{
data[columna2, fila2].Value = S.Tabla[columna2, fila2].Valor;
Matriz[columna2,fila2] = S.Tabla[columna2, fila2].Valor;
}
}
Resultados.Add(Matriz);
NroRespuesta++;
MessageBox.Show("Respuesta N "+NroRespuesta.ToString());
}
else
{
if (S.Tabla[fila, columna].Valor == 0)
{
S.Tabla[fila, columna].Valor = Valor;
S.IniciarLista();
}

int temp_fila = 0;
int temp_columna = 0;
bool Continuar = true;
for (temp_fila = fila; temp_fila < 9; temp_fila++)
{
for (temp_columna = columna; temp_columna < 9; temp_columna++)
{
if (S.Tabla[temp_fila, temp_columna].Valor == 0)
{
Continuar = false;
break;
}
}
columna = 0;
if (!Continuar)
break;
}
if (temp_fila == 9 && temp_columna == 9)
BackTrackingFormas(S, 9, 9, 0,data);
else
{
if (S.Tabla[temp_fila, temp_columna].ListaPosibles.Count > 0)
{
foreach (object o in Tabla[temp_fila, temp_columna].ListaPosibles)
{
int r = int.Parse(o.ToString());
int Valor_Antiguo = S.Tabla[temp_fila, temp_columna].Valor;
BackTrackingFormas(S, temp_fila, temp_columna, r,data);

S.Tabla[temp_fila, temp_columna].Valor = Valor_Antiguo;


S.IniciarLista();
}
}
}
}
}
}
}

Você também pode gostar