Sudoku Game

This commit is contained in:
Fernando Méndez 2019-06-20 12:06:27 +02:00 committed by GitHub
parent 1baddf2a56
commit 36df5ecef5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1213 additions and 0 deletions

View File

@ -0,0 +1,51 @@
//Sudoku - Fernando Méndez Torrubiano
#include "CasillaSudoku.h"
using namespace std;
void iniciar(tCasillaSudoku& casilla, int numero, tEstadoCasilla estado) {
casilla.estado = estado;
casilla.numero = numero;
iniLLeno(casilla.posibles);
}
bool actualizar(tCasillaSudoku & casilla, int numero, tEstadoCasilla estado) {
bool actualizado = false;
if (estado != fija) {
if (pertenece(casilla.posibles, numero)) {
casilla.numero = numero;
casilla.estado = estado;
actualizado = true;
}
}
return actualizado;
}
bool actualizarSimple(tCasillaSudoku& casilla) {
bool actualizado = false;
if (casilla.estado == vacia) {
if (numElems(casilla.posibles) == 1) {
for (int i = 0; i <= MAX_INTERVALOS; i++){
if (pertenece(casilla.posibles, i)) {
casilla.numero = i;
}
}
casilla.estado = rellena;
iniVacio(casilla.posibles);
actualizado = true;
}
}
return actualizado;
}
void mostrar(const tCasillaSudoku& casilla) {
cout << " ";
colorFondo(casilla.estado);
if (casilla.estado == vacia) { cout << " "; }
else { cout << casilla.numero; }
colorFondo(0);
}

View File

@ -0,0 +1,27 @@
//Sudoku - Fernando Méndez Torrubiano
#ifndef H_CASILLASODOKU_H
#define H_CASILLASODOKU_H
#pragma once
#include <iostream>
#include <string>
#include "Conjunto_1_9.h"
#include "UtilidadesWin.h"
//Constantes:
//Tipos:
typedef enum tEstadoCasilla { vacia = 0, fija = 1, rellena = 4};
typedef struct tCasillaSudoku {
tEstadoCasilla estado; //Estado de la casilla.
int numero; //Número que contiene (en caso de NO estar vacía).
tConjunto_1_9 posibles; //Conjunto de posibles números válidos para esa casilla.
};
//Funciones:
void iniciar(tCasillaSudoku& casilla, int numero, tEstadoCasilla estado); //Inicializa el estado de la casilla dada a estado, su número a numero y su conjunto de candidatos al conjunto { 1,2,3,4,5,6,7,8,9 }.
bool actualizar(tCasillaSudoku& casilla, int numero, tEstadoCasilla estado); //Modifica el estado y el nº de casilla si el estado actual de la casilla no es fija y numero es un candidato, en otro caso devuelve false.
bool actualizarSimple(tCasillaSudoku& casilla); //Si la casilla está vacía y tiene un único candidato, rellena la casilla con dicho valor, en otro caso devuelve false.
void mostrar(const tCasillaSudoku& casilla); //Muestra en la consola la casilla dada, utilizando distintos colores de fondo.Se mostrarán sobre fondo azul las casillas fijas y sobre fondo rojo las casillas rellenas.El resto, sobre el fondo negro por defecto.
#endif

View File

@ -0,0 +1,64 @@
//Sudoku - Fernando Méndez Torrubiano
#include "Conjunto_1_9.h"
using namespace std;
void iniVacio(tConjunto_1_9& c) {
for (int i = 0; i <= MAX_INTERVALOS; i++) {
c.boleano[i] = false;
}
c.cardinal = 0;
}
void iniLLeno(tConjunto_1_9& c) {
for (int i = 0; i <= MAX_INTERVALOS; i++) {
c.boleano[i] = true;
}
c.cardinal = MAX_INTERVALOS;
}
bool pertenece(const tConjunto_1_9& c, int e) {
bool encontrado = false;
if (c.boleano[e - 1] == true) {
encontrado = true;
}
return encontrado;
}
void incluir(tConjunto_1_9& c, int e) {
if ((c.cardinal < MAX_INTERVALOS)) {
c.boleano[e - 1] = true;
c.cardinal++;
}
}
void quitar(tConjunto_1_9& c, int e) {
if (pertenece(c, e)) {
c.boleano[e - 1] = false;
c.cardinal--;
}
}
int numElems(const tConjunto_1_9& c) {
int num = c.cardinal;
return num;
}
void mostrar(const tConjunto_1_9& c) {
for (int i = 1; i <= MAX_INTERVALOS; i++){
if (pertenece(c, i)) {
cout << right << setw(5) << i;
}
}
}

View File

@ -0,0 +1,30 @@
//Sudoku - Fernando Méndez Torrubiano
#ifndef H_CONJUNTO_1_9_H
#define H_CONJUNTO_1_9_H
#pragma once
#include <iostream>
#include <string>
#include <iomanip>
#include "checkML.h"
//Constantes:
const int MAX_INTERVALOS = 9;
//Tipos:
typedef struct tConjunto_1_9 {
bool boleano[MAX_INTERVALOS];
int cardinal;
};
//Funciones:
void iniVacio(tConjunto_1_9& c); //Inicializa c al conjunto vacío.
void iniLLeno(tConjunto_1_9& c); //Inicializa c al conjunto formado por todos los enteros del intervalo [1, 9].
bool pertenece(const tConjunto_1_9& c, int e); //Devuelve un booleano que indica si el elemento e (nº entero € [1, 9]) se encuentra en el conjunto c.
void incluir(tConjunto_1_9& c, int e); //Mete el elemento e (€ [1, 9]) en  el conjunto c.
void quitar(tConjunto_1_9& c, int e); //Saca el elemento e (€ [1, 9]) del  conjunto c.
int numElems(const tConjunto_1_9& c); //Devuelve el  de elementos que  hay en el conjunto c.
void mostrar(const tConjunto_1_9& c); //Visualiza  en  la  consola  los  elementos del conjunto c.
#endif

View File

@ -0,0 +1,134 @@
//Sudoku - Fernando Méndez Torrubiano
#include "JuegoSudoku.h"
using namespace std;
void mostrar(const tJuegoSudoku& juego) {
mostrar(juego.registro);
mostrar(juego.tablero);
}
int jugar(const tRegSudoku& sudoku) {
tJuegoSudoku juego;
int puntos = 0;
juego.registro.nomTablero = sudoku.nomTablero;
juego.registro.puntos = sudoku.puntos;
if (cargar(juego.tablero, sudoku.nomTablero)) {
clear();
mostrar(juego);
ejecutarSubMenu(juego, puntos);
}
else {
cout << "No se ha podido cargar el tablero." << endl;
}
return puntos;
}
void ejecutarSubMenu(tJuegoSudoku& juego, int& puntos) {
tCoor coordenadas;
char opc = '1';
int num = 0;
bool resuelto = false;
do {
actulizarCandidatos(juego, coordenadas);
opc = subMenu();
switch (opc) {
case '1':
pedirCoordenadas(coordenadas);
mostrarCandidatos(juego.tablero, coordenadas);
pausa();
break;
case '2':
pedirCoordenadas(coordenadas);
do {
cout << endl << "Introduzca un numero [1-9]: ";
cin >> num;
} while ((num < 1) || (num > MAXDIM));
if (actualizar(juego.tablero, coordenadas, num)) {
cout << "Casilla actualizada correctamente." << endl;
}
else {
cout << "No se ha podido actualizar esa casilla." << endl;
}
pausa();
break;
case '3':
pedirCoordenadas(coordenadas);
if (borrar(juego.tablero, coordenadas)) {
cout << "Borrado correctamente." << endl;
}
else {
cout << "No se puede borrar esa casilla." << endl;
}
pausa();
break;
case '4':
if (cargar(juego.tablero, juego.registro.nomTablero)) {
cout << "Tablero reiniciado correctamente." << endl;
}
pausa();
break;
case '5':
completarSimples(juego.tablero);
break;
}
if (numVacias(juego.tablero) == 0) {
resuelto = true;
puntos = juego.registro.puntos;
}
clear();
mostrar(juego);
} while ((opc != '0') && (!resuelto));
}
char subMenu() {
char opc = '1';
cout << endl << "<" << setfill(char('-')) << setw(35) << "OPCIONES DE JUEGO" << setw(18) << ">" << "\n" << setfill(char(0));
cout << "1 - Ver posibles valores de una casilla vacía" << endl;
cout << "2 - Colocar valor en una casilla" << endl;
cout << "3 - Borrar valor de una casilla" << endl;
cout << "4 - Reiniciar el tablero" << endl;
cout << "5 - Autocompletar celdas simples" << endl;
cout << "0 - Abortar la resolución y volver al menú principal" << endl;
cout << "<" << setfill(char('-')) << setw(53) << ">" << "\n" << setfill(char(0));
cout << "Seleccione una opcion: ";
cin >> opc;
while (opc != '0' && opc != '1' && opc != '2' && opc != '3' && opc != '4' && opc != '5') {
cout << "Seleccione una opción del menu (entre 0 y 5): ";
cin >> opc;
}
return opc;
}
void pedirCoordenadas(tCoor& coordenadas) {
do {
cout << "Introduzca fila [1-9]: ";
cin >> coordenadas.fila;
} while ((coordenadas.fila < 1) || (coordenadas.fila > MAXDIM));
coordenadas.fila -= 1;
do {
cout << "Introduzca columna [1-9]: ";
cin >> coordenadas.col;
} while ((coordenadas.col < 1) || (coordenadas.col > MAXDIM));
coordenadas.col -= 1;
}
void actulizarCandidatos(tJuegoSudoku& juego, tCoor& coordenadas) {
for (int i = 0; i < MAXDIM; i++) {
for (int j = 0; j < MAXDIM; j++) {
coordenadas.fila = i;
coordenadas.col = j;
cargarCandidatos(juego.tablero, coordenadas);
}
}
}

View File

@ -0,0 +1,27 @@
//Sudoku - Fernando Méndez Torrubiano
#ifndef H_JUEGOSODOKU_H
#define H_JUEGOSODOKU_H
#pragma once
#include <iostream>
#include <string>
#include "ListaSudokus.h"
#include "TableroSudoku.h"
//Constantes:
//Tipos:
typedef struct tJuegoSudoku {
tRegSudoku registro;
tTableroSudoku tablero;
};
//Funciones:
void mostrar(const tJuegoSudoku& juego); //Muestra por pantalla la  información del sudoku que se va a jugar así como el tablero del mismo. bool cargar(tJuegoSuduko & juego, const tRegSudoku & sudoku) : actualiza el tablero del parámetro juego con el contenido del archivo cuyo  nombre figura en el parámetro sudoku.
int jugar(const tRegSudoku& sudoku); //Dada la información del sudoku elegido lleva a cabo todas las acciones correspondientes a haber elegido la opción 1 de esta versión y devuelve la puntuación obtenida por el jugador (0 si  aborta  la  resolución  antes  de  rellenar  el  tablero  o  los  puntos  asociados  al  sudoku elegido en caso de resolverlo).
char subMenu();
void ejecutarSubMenu(tJuegoSudoku& juego, int& puntos);
void pedirCoordenadas(tCoor& coordenadas);
void actulizarCandidatos(tJuegoSudoku& juego, tCoor& coordenadas);
#endif

View File

@ -0,0 +1,176 @@
//Sudoku - Fernando Méndez Torrubiano
#include "ListaJugadores.h"
using namespace std;
//Funciones auxiliares:
bool busquedaRecursiva(const tListaJugadores& lista, const tRegJugador& jugador, int& pos, int& ini, int& fin); //Función auxiliar para realizar la búsqueda recursiva binaria.
void iniciar(tListaJugadores& lista) {
lista.capacidad = 3;
lista.contador = 0;
lista.jugadores = new tRegJugador*[lista.capacidad];
}
bool cargar(tListaJugadores& lista) {
bool carga = false;
ifstream archivo;
string id = "";
int puntos = 0;
iniciar(lista);
archivo.open("registroJugadores.txt");
if (!archivo.is_open()) {
cout << "Error al cargar la lista de jugadores." << endl;
}
else {
carga = true;
archivo >> id;
archivo >> puntos;
while (!archivo.fail()) {
if (lista.contador == lista.capacidad) {
ampliar(lista, lista.capacidad);
}
lista.jugadores[lista.contador] = new tRegJugador;
iniciar(*lista.jugadores[lista.contador], id, puntos);
lista.contador++;
archivo >> id;
archivo >> puntos;
}
archivo.close();
}
return carga;
}
void mostrar(const tListaJugadores& lista) {
cout << right << setw(8) << "POSICIÓN" << setw(12) << "JUGADOR" << setw(12) << "PUNTOS" << endl;
cout << setfill(char('-')) << setw(35) << "\n" << setfill(char(0));
for (int i = 0; i < lista.contador; i++){
cout << setw(3) << i + 1 << "." << setw(7);
mostrar(*lista.jugadores[i]);
}
cout << setfill(char('-')) << setw(35) << "\n" << setfill(char(0));
}
bool guardar(const tListaJugadores& lista) {
bool guardado = false;
ofstream archivo;
archivo.open("registroJugadores.txt");
if (!archivo.is_open()) {
cout << "Error al guardar el registro de jugadores." << endl;
}
else {
for (int i = 0; i < lista.contador; i++){
archivo << lista.jugadores[i]->id << " ";
archivo << lista.jugadores[i]->puntos << endl;
}
guardado = true;
archivo.close();
}
return guardado;
}
bool buscar(const tListaJugadores& lista, const tRegJugador& jugador, int& pos) {
bool encontrado = false;
int ini = 0, fin = lista.contador - 1;
encontrado = busquedaRecursiva(lista, jugador, pos, ini, fin);
return encontrado;
}
bool busquedaRecursiva(const tListaJugadores& lista, const tRegJugador& jugador, int& pos, int& ini, int& fin) {
bool encontrado = false;
if (ini <= fin) {
pos = (ini + fin) / 2;
if (jugador < *lista.jugadores[pos]) { //operator<(jugador, *lista.jugadores[pos])
fin = pos - 1;
encontrado = busquedaRecursiva(lista, jugador, pos, ini, fin);
pos = fin;
}
else if (*lista.jugadores[pos] < jugador) { //operator<(*lista.jugadores[pos], jugador)
ini = pos + 1;
encontrado = busquedaRecursiva(lista, jugador, pos, ini, fin);
}
else {
encontrado = true;
}
}
return encontrado;
}
bool actualizar(tListaJugadores& lista, const tRegJugador& jugador) {
bool actualizado = false;
int pos = 0;
if (buscar(lista, jugador, pos)) {
actualizar(*lista.jugadores[pos], jugador.puntos);
actualizado = true;
}
else {
if (lista.contador == lista.capacidad) {
ampliar(lista, lista.capacidad);
}
pos++;
for (int i = lista.contador; i > pos; i--) {
lista.jugadores[i] = lista.jugadores[i - 1];
}
lista.jugadores[pos] = new tRegJugador;
iniciar(*lista.jugadores[pos], jugador.id, jugador.puntos);
lista.contador++;
}
return actualizado;
}
void mostrarXRanking(const tListaJugadores& lista) {
tListaJugadores listaXRanking;
int cont;
//iniciar(listaXRanking);
listaXRanking.capacidad = lista.contador + 1;
listaXRanking.contador = lista.contador;
listaXRanking.jugadores = new tRegJugador*[listaXRanking.capacidad];
for (int i = 0; i < lista.contador; i++) {
cont = i;
listaXRanking.jugadores[i] = lista.jugadores[i];
while ((cont > 0) && ((menorXRanking(*listaXRanking.jugadores[cont - 1], *listaXRanking.jugadores[cont])))) {
listaXRanking.jugadores[listaXRanking.contador] = listaXRanking.jugadores[cont];
listaXRanking.jugadores[cont] = listaXRanking.jugadores[cont - 1];
listaXRanking.jugadores[cont - 1] = listaXRanking.jugadores[listaXRanking.contador];
cont--;
}
}
mostrar(listaXRanking);
delete[] listaXRanking.jugadores;
}
/*//*/
void ampliar(tListaJugadores& lista, int num) {
lista.capacidad += num;
tRegJugador** aux = new tRegJugador*[lista.capacidad];
for (int i = 0; i < lista.contador; i++) {
aux[i] = lista.jugadores[i];
}
delete[] lista.jugadores;
lista.jugadores = aux;
}
void liberar(tListaJugadores& lista) {
for (int i = 0; i < lista.contador; i++){
delete lista.jugadores[i];
}
delete[] lista.jugadores;
}

View File

@ -0,0 +1,34 @@
//Sudoku - Fernando Méndez Torrubiano
#ifndef H_LISTAJUGADORES_H
#define H_LISTAJUGADORES_H
#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include "RegistroJugador.h"
//Constantes:
//const int MAX_JGD = 9;
//Tipos:
typedef struct tListaJugadores {
tRegJugador** jugadores; //El primer asterisco indica que el array es dinámico, el segundo indica que cada campo del array son punteros a datos.
int capacidad;
int contador;
};
//Funciones:
void iniciar(tListaJugadores& lista); //Inicializa lista a lista vacía.
bool cargar(tListaJugadores& lista); //Guarda en lista el contenido del archivo listaJugadores.txt; devuelve un booleano que indica si la carga se ha podido realizar.
void mostrar(const tListaJugadores& lista); //Visualiza en la consola la lista de jugadores dada.
bool guardar(const tListaJugadores& lista); //Almacena en el archivo registroJugadores.txt el contenido de lista y devuelve un valor booleano  indicando si la acción fue posible.Debe respetar el formato indicado para el  archivo.
bool buscar(const tListaJugadores& lista, const tRegJugador& jugador, int& pos); //Busca en lista al jugador; devuelve true y la posición(pos) en la que se encuentra si el jugador está en la lista; devuelve false y la posición(pos) en la que debería estar si el jugador no está en la lista. Debes implementar una búsqueda binaria utilizando el operador < del módulo RegistroJugador.
bool actualizar(tListaJugadores& lista, const tRegJugador& jugador); //Si el jugador se encuentra ya en la lista, actualiza su información con los nuevos puntos; en otro caso, si la lista no está llena, lo inserta ordenadamente en la lista.
void mostrarXRanking(const tListaJugadores& lista); //Muestra los jugadores de la lista dada ordenados por ranking (decrecientemente por puntos, y a igualdad de puntos crecientemente por identificador).
void ampliar(tListaJugadores& lista, int num); //Amplía el tamaño del array dinámico de lista a num elemento más.Los datos de los jugadores que ya existen en la lista deben mantenerse.
void liberar(tListaJugadores& lista); //Libera la memoria dinámica usada por lista.
#endif

View File

@ -0,0 +1,128 @@
//Sudoku - Fernando Méndez Torrubiano
#include "ListaSudokus.h"
using namespace std;
void iniciar(tListaSudokus& lista) {
lista.contador = 0;
for (int i = 0; i < MAX_SDK; i++){
iniciar(lista.registro[i], "", 0);
}
}
int numElems(const tListaSudokus& lista) {
int num = lista.contador;
return num;
}
bool cargar(tListaSudokus& lista) {
bool carga = false;
ifstream archivo;
tListaSudokus aux;
int cont = 0;
iniciar(lista);
archivo.open("registroSudokus.txt");
if (!archivo.is_open()) {
cout << "Error al leer los datos." << endl;
carga = false;
}
else {
while ((lista.contador < MAX_SDK) && (cargar(lista.registro[lista.contador], archivo))) {
cont = lista.contador;
while ((cont > 0) && (lista.registro[cont] < lista.registro[cont - 1])) { //(operator<(lista.registro[cont], lista.registro[cont - 1]))
aux.registro[cont] = lista.registro[cont];
lista.registro[cont] = lista.registro[cont - 1];
lista.registro[cont - 1] = aux.registro[cont];
cont--;
}
lista.contador++;
}
carga = true;
}
archivo.close();
return carga;
}
void mostrar(const tListaSudokus& lista) {
cout << endl << right << setw(22) << "FICHERO DE CARGA" << setw(10) << "NIVEL" << endl;
cout << setfill('-') << setw(45) << "\n" << setfill(char(0));
for (int i = 0; i < lista.contador; i++) {
cout << right << i + 1 << "." << setw(20) << lista.registro[i].nomTablero << setw(10) << lista.registro[i].puntos << endl;
}
cout << setfill('-') << setw(45) << "\n" << setfill(char(0));
}
////
bool guardar(const tListaSudokus& lista) {
ofstream archivo;
bool guardado = false;
int i = 0;
archivo.open("registroSudokus.txt");
if (!archivo.is_open()) {
cout << "Error al guardar." << endl;
}
else {
while ((i < lista.contador) && (!guardado)) {
if (guardar(lista.registro[i], archivo)) {
i++;
}
}
guardado = true;
}
return guardado;
}
bool buscar(const tListaSudokus& lista, string nombArch) {
bool encontrado = false;
int i = 0;
while ((!encontrado) && (i < lista.contador)) {
if (lista.registro[i].nomTablero != nombArch) {
i++;
}
else {
encontrado = true;
}
}
return encontrado;
}
bool insertar(tListaSudokus& lista, const tRegSudoku& sudoku) {
bool insertado = false;
tListaSudokus aux;
int cont = 0;
if (buscar(lista, sudoku.nomTablero)) {
cout << "El tablero ya existe." << endl;
}
else {
if (lista.contador < MAX_SDK) {
cont = lista.contador;
while ((cont > 0) && (operator<(sudoku, lista.registro[cont - 1]))) {
aux.registro[cont] = lista.registro[cont];
lista.registro[cont] = lista.registro[cont - 1];
lista.registro[cont - 1] = aux.registro[cont];
cont--;
}
iniciar(lista.registro[cont], sudoku.nomTablero, sudoku.puntos);
lista.contador++;
insertado = true;
}
else {
cout << "La lista está llena." << endl;
}
}
return insertado;
}

View File

@ -0,0 +1,28 @@
//Sudoku - Fernando Méndez Torrubiano
#ifndef H_LISTASODOKUS_H
#define H_LISTASODOKUS_H
#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include "RegistroSudoku.h"
//Constantes:
//Tipos:
typedef struct tListaSudokus {
tRegSudoku registro[MAX_SDK];
int contador;
};
//Funciones:
void iniciar(tListaSudokus& lista); //Inicializa lista a una lista vacía.
int numElems(const tListaSudokus& lista); //Devuelve el número de elementos de lista.
bool cargar(tListaSudokus& lista); //Guarda en lista el contenido del archivo registroSudokus.txt, devuelve un booleano que indica si la carga se ha podido realizar.
void mostrar(const tListaSudokus& lista); //Visualiza por pantalla la información de los sudokus de la lista dada.
bool guardar(const tListaSudokus& lista); //Almacena en el archivo registroSudokus.txt el contenido de lista y devuelve un valor booleano indicando si la acción fue posible.Debe respetar el formato indicado para el  archivo.
bool buscar(const tListaSudokus& lista, std::string nombArch); //Busca en lista el fichero nombArch; devuelve true si está en la lista; y false en otro caso.
bool insertar(tListaSudokus& lista, const tRegSudoku& sudoku); //Si no existe un sudoku en lista con igual nombre de fichero lo inserta en la posición adecuada respetando el orden existente.Se devuelve un booleano que indica si se pudo añadir, para lo cual también hay que tener en cuenta si la lista  está o no llena.Debe implementarse una inserción ordenada.
#endif

View File

@ -0,0 +1,46 @@
//Sudoku - Fernando Méndez Torrubiano
#include "RegistroJugador.h"
using namespace std;
void iniciar(tRegJugador& jugador, std::string id, int puntos) {
jugador.id = id;
jugador.puntos = puntos;
}
void mostrar(const tRegJugador& jugador) {
cout << right << setw(15) << jugador.id << setw(10) << jugador.puntos << endl;
}
void actualizar(tRegJugador& jugador, int puntos) {
jugador.puntos += puntos;
}
bool operator<(const tRegJugador& regIzq, const tRegJugador& regDer) {
tRegJugador regIzqMinus, regDerMinus;
for (int i = 0; i < regIzq.id.length(); i++) {
regIzqMinus.id += tolower(regIzq.id[i]);
}
for (int i = 0; i < regDer.id.length(); i++) {
regDerMinus.id += tolower(regDer.id[i]);
}
return (regIzqMinus.id < regDerMinus.id);
}
bool menorXRanking(const tRegJugador& jug1, const tRegJugador& jug2) {
bool menor = false;
if (jug1.puntos == jug2.puntos) {
if (jug2 < jug1) { //!operator<(jug1, jug2) || operator(jug2, jug1)
menor = true;
}
}
else {
if ((jug1.puntos < jug2.puntos)) {
menor = true;
}
}
return menor;
}

View File

@ -0,0 +1,29 @@
//Sudoku - Fernando Méndez Torrubiano
#ifndef H_REGISTROJUGADOR_H
#define H_REGISTROJUGADOR_H
#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <stdlib.h>
#include "checkML.h"
//Constantes:
//Tipos:
typedef struct tRegJugador {
std::string id;
int puntos;
};
//Funciones:
void iniciar(tRegJugador& jugador, std::string id, int puntos); //Inicia jugador con los datos id y puntos.
void mostrar(const tRegJugador& jugador); //Visualiza en la consola la información del registro dado.
void actualizar(tRegJugador& jugador, int puntos); //Añade puntos a los puntos que lleva conseguidos el jugador dado.
bool operator<(const tRegJugador& regIzq, const tRegJugador& regDer); //Sobrecarga  del  operador < para  datos  del  tipo  tRegJugador  comparando en base al identificador.
bool menorXRanking(const tRegJugador& jug1, const tRegJugador& jug2); //Devuelve true si el jugador jug1 tiene menos puntos que el jugador jug2, o si tienen los mismos puntos pero el identificador del jugador jug2 es menor que el del jugador jug1; false en caso contrario.
#endif

View File

@ -0,0 +1,36 @@
//Sudoku - Fernando Méndez Torrubiano
#include "RegistroSudoku.h"
using namespace std;
bool cargar(tRegSudoku& sudoku, istream& infile) {
infile >> sudoku.nomTablero;
infile >> sudoku.puntos;
return !infile.fail() ? true : false;
}
void mostrar(const tRegSudoku& sudoku) {
cout << right << setw(7) << "SUDOKU: " << sudoku.nomTablero
<< setw(11) << "NIVEL: " << sudoku.puntos << endl;
}
////
void iniciar(tRegSudoku& registro, string file, int puntos) {
registro.nomTablero = file;
registro.puntos = puntos;
}
bool guardar(const tRegSudoku& registro, ostream& outfile) {
outfile << registro.nomTablero << " ";
outfile << registro.puntos << endl;
return !outfile.fail() ? true : false;
}
bool operator<(const tRegSudoku& regIzq, const tRegSudoku& regDer) {
return((regIzq.puntos < regDer.puntos) || ((regIzq.puntos == regDer.puntos) && (regIzq.nomTablero < regDer.nomTablero))) ? true : false;
}

View File

@ -0,0 +1,28 @@
//Sudoku - Fernando Méndez Torrubiano
#ifndef H_REGISTROSODOKU_H
#define H_REGISTROSODOKU_H
#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include "checkML.h"
//Constantes:
const int MAX_SDK = 9;
//Tipos:
typedef struct tRegSudoku {
int puntos;
std::string nomTablero;
};
//Funciones:
bool cargar(tRegSudoku& sudoku, std::istream& infile); //Lee los datos del siguiente registro del flujo infile en sudoku y devuelve un booleano que indica si la carga se ha podido realizar.
void mostrar(const tRegSudoku& sudoku); //Visualiza en la consola la información del registro dado.
void iniciar(tRegSudoku& registro, std::string file, int puntos); //Inicia el registro con los datos file y puntos.
bool guardar(const tRegSudoku& registro, std::ostream& outfile); //Almacena en outfile el contenido de registro y devuelve un valor booleano  indicando si la acción fue posible.Debe respetar el formato del archivo.
bool operator<(const tRegSudoku& regIzq, const tRegSudoku& regDer); //Sobrecarga del operador < para datos del tipo tRegSudoku de acuerdo con el orden descrito.
#endif

View File

@ -0,0 +1,138 @@
//Sudoku - Fernando Méndez Torrubiano
#include "TableroSudoku.h"
using namespace std;
bool cargar(tTableroSudoku& tablero, string nombreFichero) {
bool carga = false;
ifstream archivo;
char ch; int num;
tablero.numVacias = 0;
archivo.open(nombreFichero);
if (!archivo.is_open()) {
carga = false;
}
else {
for (int i = 0; i < MAXDIM; i++) {
for (int j = 0; j <= MAXDIM; j++) {
if (j != MAXDIM) {
archivo.get(ch);
switch (ch) {
case ' ': iniciar(tablero.casilla[i][j], 0, vacia); tablero.numVacias++; break;
default: num = (int)ch - 48; iniciar(tablero.casilla[i][j], num, fija); break;
}
}
else {
archivo.get(ch);
}
}
}
carga = true;
}
return carga;
}
void mostrar(const tTableroSudoku& tablero) {
for (int i = 0; i < MAXDIM; i++){
if (i % 3 == 0) {
cout << setfill('-') << setw(32) << "\n" << setfill(char(0));
}
for (int j = 0; j < MAXDIM; j++){
if ((j % 3 == 0)) {
cout << "|";
}
mostrar(tablero.casilla[i][j]);
}
cout << "|" << "\n";
}
cout << setfill('-') << setw(32) << "\n" << setfill(char(0));
}
bool actualizar(tTableroSudoku& tablero, tCoor cor, int num) {
bool actualizado = false;
if ((tablero.casilla[cor.fila][cor.col].estado != fija) && (pertenece(tablero.casilla[cor.fila][cor.col].posibles, num))) {
actualizar(tablero.casilla[cor.fila][cor.col], num, rellena);
actualizado = true;
tablero.numVacias--;
}
return actualizado;
}
bool borrar(tTableroSudoku& tablero, tCoor cor) {
bool borrado = false;
if ((tablero.casilla[cor.fila][cor.col].numero != 0) && (tablero.casilla[cor.fila][cor.col].estado != fija)) {
borrado = true;
incluir(tablero.casilla[cor.fila][cor.col].posibles, tablero.casilla[cor.fila][cor.col].numero);
tablero.casilla[cor.fila][cor.col].numero = 0;
tablero.casilla[cor.fila][cor.col].estado = vacia;
tablero.numVacias++;
}
return borrado;
}
void mostrarCandidatos(const tTableroSudoku& tablero, tCoor cor) {
if ((tablero.casilla[cor.fila][cor.col].estado == vacia) || (tablero.casilla[cor.fila][cor.col].estado == rellena)) {
cout << "CANDIDATOS:";
mostrar(tablero.casilla[cor.fila][cor.col].posibles);
}
else {
cout << "La casilla está fija." << endl;
}
cout << endl;
}
void cargarCandidatos(tTableroSudoku& tablero, tCoor cor) {
//FILAS:
for (int i = 0; i < MAXDIM; i++) {
if (tablero.casilla[cor.fila][i].estado != vacia) {
quitar(tablero.casilla[cor.fila][cor.col].posibles, tablero.casilla[cor.fila][i].numero);
}
}
//COLUMNAS:
for (int i = 0; i < MAXDIM; i++) {
if (tablero.casilla[i][cor.col].estado != vacia) {
quitar(tablero.casilla[cor.fila][cor.col].posibles, tablero.casilla[i][cor.col].numero);
}
}
//SUBCUADRADO:
int iniFil = (cor.fila / 3) * 3;
int finFil = iniFil + 3;
int iniCol = (cor.col / 3) * 3;
int finCol = iniCol + 3;
for (int i = iniFil; i < finFil; i++) {
for (int j = iniCol; j < finCol; j++) {
if (tablero.casilla[i][j].estado != vacia) {
quitar(tablero.casilla[cor.fila][cor.col].posibles, tablero.casilla[i][j].numero);
}
}
}
}
void completarSimples(tTableroSudoku& tablero) {
for (int i = 0; i < MAXDIM; i++){
for (int j = 0; j < MAXDIM; j++){
if (actualizarSimple(tablero.casilla[i][j])) {
tablero.numVacias--;
}
}
}
}
int numVacias(const tTableroSudoku& tablero) {
int numV = tablero.numVacias;
return numV;
}

View File

@ -0,0 +1,34 @@
//Sudoku - Fernando Méndez Torrubiano
#ifndef H_TABLEROSODOKU_H
#define H_TABLEROSODOKU_H
#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include "CasillaSudoku.h"
//Constantes:
const int MAXDIM = 9;
//Tipos:
typedef struct tCoor {
int fila, col;
};
typedef struct tTableroSudoku {
tCasillaSudoku casilla[MAXDIM][MAXDIM];
int numVacias;
};
//Funciones:
bool cargar(tTableroSudoku& tablero, std::string nombreFichero); //carga la información almacenada en el archivo de nombre nombreFichero que  contiene el tablero del sudoku a jugar, contando las casillas, y devuelve un  booleano que indica si la carga se ha podido realizar.Los valores posibles de  las casillas deberán quedar convenientemente actualizados.
void mostrar(const tTableroSudoku& tablero); //Muestra por pantalla el tablero dado.
bool actualizar(tTableroSudoku& tablero, tCoor cor, int num); //Coloca el  num en la casilla de coordenadas cor = (fila, col) (ambas en el  intervalo [0, 8]) del tablero tablero; el booleano que devuelve indica si la  acción ha sido posible (para ello la casilla debe ser vacía y num debe ser uno de  los valores posibles de la misma).Si es posible colocar el número dado en la  casilla indicada deberán actualizarse convenientemente los valores candidatos  de las casillas que puedan verse afectadas (las de la misma fila, columna y submatriz  que  la  casilla  dada).También  se  debe  actualizar  el  número  de  casillas vacías.
bool borrar(tTableroSudoku& tablero, tCoor cor); //Borra el número  de la casilla de coordenadas cor = (fila, col)  (ambas en el intervalo [0, 8]) del  tablero tablero y la casilla volverá a estar en estado vacío; el booleano que  devuelve indica si la acción ha sido posible (debe ser una casilla que haya sido  previamente rellenada).Si es posible borrar el número de la casilla indicada  deberán actualizarse convenientemente los valores candidatos de las casillas  que puedan verse afectadas (las de la misma fila, columna y submatriz que la  casilla dada).También se debe actualizar el número de casillas vacías.
void mostrarCandidatos(const tTableroSudoku& tablero, tCoor cor); //Muestra los valores posibles de la casilla, del tablero dado, que tiene   coordenadas cor = (fila, col) (ambas en el intervalo [0, 8]).
void completarSimples(tTableroSudoku& tablero); //En cada casilla que  tiene  un  único  valor  posible  se  pone  dicho  valor  y  se  actualizan  convenientemente  los  valores  posibles  de  las  casillas  que  puedan  verse  afectadas.También se debe actualizar el número de casillas vacías.
int numVacias(const tTableroSudoku& tablero); //Devuelve el número  de casillas vacías del tablero dado.
void cargarCandidatos(tTableroSudoku& tablero, tCoor cor); //Recibe el tablero y unas coordenadas, lee para dichas coordenadas los posibles valores candidatos.
#endif

View File

@ -0,0 +1,20 @@
//Sudoku - Fernando Méndez Torrubiano
#include "UtilidadesWin.h"
using namespace std;
void colorFondo(tColor color) {
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, 15 | (color << 4));
}
void castellano() {
system("chcp 1252"); //Así la consola puede imprimir caracteres especiales del español.
}
void pausa() {
system("PAUSE");
}
void clear() {
system("cls");
}

View File

@ -0,0 +1,20 @@
//Sudoku - Fernando Méndez Torrubiano
#ifndef H_UTILIDADESWIN_H
#define H_UTILIDADESWIN_H
#pragma once
#include <iostream>
#include <string>
#include "Windows.h"
#include "checkML.h"
//Tipos:
typedef unsigned char tColor;
//Funciones:
void colorFondo(tColor color);
void castellano();
void pausa();
void clear();
#endif

View File

@ -0,0 +1,13 @@
//Sudoku - Fernando Méndez Torrubiano
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#ifndef DBG_NEW
#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#define new DBG_NEW
#endif
#endif

View File

@ -0,0 +1,110 @@
//Sudoku - Fernando Méndez Torrubiano
#include "juegoSudoku.h"
#include "ListaSudokus.h"
#include "ListaJugadores.h"
#include "UtilidadesWin.h"
#include <iomanip>
using namespace std;
//Funciones:
char menu();
void ejecutarMenu(tListaSudokus&, tListaJugadores&);
int main() {
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); //Detecta posibles fugas de memoria.
tListaSudokus lista;
tListaJugadores listaJug;
castellano();
if ((cargar(listaJug)) && (cargar(lista))) {
ejecutarMenu(lista, listaJug);
}
else {
cout << "Fin del programa." << endl;
}
if ((guardar(lista)) && (guardar(listaJug))) {
cout << "Guardado correctamente." << endl;
}
else {
cout << "Error al guardar el archivo." << endl;
}
liberar(listaJug);
pausa();
cout << "Good bye :3" << endl;
return 0;
}
void ejecutarMenu(tListaSudokus& lista, tListaJugadores& listaJug) {
tRegSudoku sudoku;
tRegJugador jugador;
char opc = '1';
int numSudo = 0, puntos = 0;
do {
clear();
opc = menu();
switch (opc){
case '1':
mostrar(lista);
do {
cout << "Introduce el número de sudoku al que deseas jugar ('0' para abortar): ";
cin >> numSudo;
} while (numSudo < 0 || numSudo > lista.contador);
if (numSudo != 0) {
iniciar(sudoku, lista.registro[numSudo - 1].nomTablero, lista.registro[numSudo - 1].puntos);
puntos = jugar(sudoku);
cout << "Juego finalizado. Puntos: " << puntos << endl;
if (puntos != 0) {
cout << endl << "Introduzca su ID de usuario: ";
cin >> jugador.id;
jugador.puntos = puntos;
actualizar(listaJug, jugador);
}
}
pausa();
break;
case '2': mostrar(listaJug); pausa(); break;
case '3': mostrarXRanking(listaJug); pausa(); break;
case '4':
mostrar(lista);
cout << "Introduzca el nombre del sudoku a insertar: ";
cin >> sudoku.nomTablero;
cout << "Introduzca la puntuación del sudoku: ";
cin >> sudoku.puntos;
insertar(lista, sudoku);
pausa();
break;
case '0':
break;
default:
break;
}
} while (opc != '0');
}
char menu() {
//Parámetros: no tiene.
//Devuelve: la opción del menú elegida por el usuario.
char opc = '1';
cout << "<" << setfill(char('-')) << setw(25) << "Menu" << setw(22) << ">" << "\n" << setfill(char(0));
cout << "1 - Jugar" << endl;
cout << "2 - Ver jugadores ordenados por identificador." << endl;
cout << "3 - Ver jugadores ordenados por puntos." << endl;
cout << "4 - Incorporar sudoku." << endl;
cout << "0 - Salir" << endl;
cout << "<" << setfill(char('-')) << setw(47) << ">" << "\n" << setfill(char(0));
cout << endl;
cout << "Seleccione una opcion del menu: ";
cin >> opc;
while (opc != '0' && opc != '1' && opc != '2' && opc != '3' && opc != '4') {
cout << "Seleccione una opción del menu (entre 0 y 4): ";
cin >> opc;
}
return opc;
}

View File

@ -0,0 +1,4 @@
sudoku1.txt 1
sudoku2.txt 2
sudoku3.txt 3
sudokuEvil.txt 5

View File

@ -0,0 +1,9 @@
3 172
4
7 149
148 5
28 74
7 268
952 8
3
679 4

View File

@ -0,0 +1,9 @@
5 3 9
9 84 6
4 7 52
6 742 5
5
43 76
6 7
2 5 7
7 9648

View File

@ -0,0 +1,9 @@
2 4 63
46 3 7 8
18
6 8
3978
7 4
93 152
9
56981

View File

@ -0,0 +1,9 @@
1 2 7
67 49
7 6
4 5
16 82
2 8
9 1
32 76
6 8 3