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
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<61>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<73> vac<61>a y tiene un <20>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<61>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<7A>c<EFBFBD>al<61>conjunto<74>vac<61>o.
void iniLLeno(tConjunto_1_9& c); //Inicializa<7A>c<EFBFBD>al<61>conjunto<74>formado<64>por<6F>todos<6F>los<6F>enteros<6F>del<65>intervalo<6C>[1, 9].
bool pertenece(const tConjunto_1_9& c, int e); //Devuelve un booleano<6E>que<75>indica<63>si<73>el<65>elemento<74>e (n<><6E>entero<72><6F> [1, 9])<29>se<73>encuentra<72>en<65>el conjunto<74>c.
void incluir(tConjunto_1_9& c, int e); //Mete<74>el<65>elemento<74>e<EFBFBD>(<28><>[1, 9])<29>en<65> el<65>conjunto<74>c.
void quitar(tConjunto_1_9& c, int e); //Saca<63>el<65>elemento<74>e<EFBFBD>(<28><>[1, 9])<29>del<65> conjunto<74>c.
int numElems(const tConjunto_1_9& c); //Devuelve<76>el<65>n<EFBFBD><6E>de<64>elementos<6F>que<75> hay<61>en<65>el<65>conjunto<74>c.
void mostrar(const tConjunto_1_9& c); //Visualiza<7A> en<65> la<6C> consola<6C> los<6F> elementos<6F>del<65>conjunto<74>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<61>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<63>n y volver al men<65> 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<63>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<69>mico, el segundo indica que cada campo del array son punteros a datos.
int capacidad;
int contador;
};
//Funciones:
void iniciar(tListaJugadores& lista); //Inicializa<7A>lista<74>a<EFBFBD>lista<74>vac<61>a.
bool cargar(tListaJugadores& lista); //Guarda<64>en<65>lista<74>el<65>contenido del<65>archivo<76>listaJugadores.txt;<3B>devuelve<76>un<75>booleano<6E>que<75>indica<63>si<73>la<6C>carga<67>se<73>ha<68>podido<64>realizar.
void mostrar(const tListaJugadores& lista); //Visualiza<7A>en<65>la<6C>consola la<6C>lista<74>de<64>jugadores<65>dada.
bool guardar(const tListaJugadores& lista); //Almacena<6E>en<65>el<65>archivo registroJugadores.txt<78>el<65>contenido<64>de<64>lista<74>y<EFBFBD>devuelve<76>un<75>valor<6F>booleano<6E> indicando<64>si<73>la<6C>acci<63>n<EFBFBD>fue<75>posible.Debe<62>respetar<61>el<65>formato<74>indicado<64>para<72>el<65> archivo.
bool buscar(const tListaJugadores& lista, const tRegJugador& jugador, int& pos); //Busca en lista al jugador; devuelve true y la posici<63>n(pos) en la que se encuentra si el jugador est<73> en la lista; devuelve false y la posici<63>n(pos) en la que deber<65>a estar si el jugador no est<73> en la lista. Debes implementar una b<>squeda binaria utilizando el operador < del m<>dulo RegistroJugador.
bool actualizar(tListaJugadores& lista, const tRegJugador& jugador); //Si<53>el<65>jugador<6F>se<73>encuentra<72>ya<79>en<65>la<6C>lista, actualiza<7A>su<73>informaci<63>n<EFBFBD>con<6F>los nuevos puntos; en otro caso, si la lista no<6E>est<73><74>llena, lo inserta<74>ordenadamente<74>en<65>la<6C>lista.
void mostrarXRanking(const tListaJugadores& lista); //Muestra<72>los jugadores<65>de la lista dada ordenados por ranking<6E>(decrecientemente<74>por puntos, y<>a<EFBFBD>igualdad<61>de<64>puntos<6F>crecientemente<74>por<6F>identificador).
void ampliar(tListaJugadores& lista, int num); //Ampl<70>a el tama<6D>o del array din<69>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<69>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<73> 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<7A>lista<74>a<EFBFBD>una<6E>lista<74>vac<61>a.
int numElems(const tListaSudokus& lista); //Devuelve<76>el<65>n<EFBFBD>mero de elementos<6F>de<64>lista.
bool cargar(tListaSudokus& lista); //Guarda<64>en<65>lista<74>el<65>contenido<64>del archivo<76>registroSudokus.txt,<2C>devuelve<76>un<75>booleano<6E>que<75>indica<63>si<73>la<6C>carga<67>se ha<68>podido<64>realizar.
void mostrar(const tListaSudokus& lista); //Visualiza<7A>por<6F>pantalla<6C>la<6C>informaci<63>n<EFBFBD>de<64>los<6F>sudokus<75>de<64>la<6C>lista<74>dada.
bool guardar(const tListaSudokus& lista); //Almacena<6E>en<65>el<65>archivo registroSudokus.txt<78>el<65>contenido<64>de<64>lista<74>y<EFBFBD>devuelve<76>un<75>valor<6F>booleano indicando<64>si<73>la<6C>acci<63>n<EFBFBD>fue<75>posible.Debe<62>respetar<61>el<65>formato<74>indicado<64>para<72>el<65> archivo.
bool buscar(const tListaSudokus& lista, std::string nombArch); //Busca en<65>lista<74>el<65>fichero<72>nombArch;<3B>devuelve<76>true<75>si<73>est<73><74>en<65>la<6C>lista;<3B>y<EFBFBD>false<73>en otro<72>caso.
bool insertar(tListaSudokus& lista, const tRegSudoku& sudoku); //Si<53>no<6E>existe<74>un<75>sudoku<6B>en<65>lista<74>con<6F>igual<61>nombre<72>de<64>fichero<72>lo<6C>inserta<74>en<65>la<6C>posici<63>n<EFBFBD>adecuada<64>respetando<64>el<65>orden<65>existente.Se<53>devuelve<76>un<75>booleano<6E>que indica<63>si<73>se<73>pudo<64>a<EFBFBD>adir, para<72>lo<6C>cual<61>tambi<62>n<EFBFBD>hay<61>que<75>tener<65>en<65>cuenta<74>si<73>la<6C>lista<74> est<73><74>o<EFBFBD>no<6E>llena.Debe<62>implementarse<73>una<6E>inserci<63>n<EFBFBD>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<69>jugador<6F>con<6F>los<6F>datos<6F>id<69>y<EFBFBD>puntos.
void mostrar(const tRegJugador& jugador); //Visualiza<7A>en<65>la<6C>consola<6C>la<6C>informaci<63>n<EFBFBD>del<65>registro<72>dado.
void actualizar(tRegJugador& jugador, int puntos); //A<>ade<64>puntos<6F>a<EFBFBD>los<6F>puntos<6F>que<75>lleva<76>conseguidos<6F>el<65>jugador<6F>dado.
bool operator<(const tRegJugador& regIzq, const tRegJugador& regDer); //Sobrecarga<67> del<65> operador<6F>< para<72> datos<6F> del<65> tipo<70> tRegJugador<6F> comparando<64>en<65>base<73>al<61>identificador.
bool menorXRanking(const tRegJugador& jug1, const tRegJugador& jug2); //Devuelve<76>true<75>si<73>el<65>jugador<6F>jug1<67>tiene<6E>menos<6F>puntos<6F>que<75>el<65>jugador<6F>jug2, o<>si<73>tienen<65>los<6F>mismos<6F>puntos<6F>pero<72>el<65>identificador<6F>del<65>jugador<6F>jug2<67>es menor<6F>que<75>el<65>del<65>jugador<6F>jug1;<3B>false<73>en<65>caso<73>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<65>los<6F>datos<6F>del<65>siguiente<74>registro<72>del<65>flujo<6A>infile<6C>en<65>sudoku<6B>y<EFBFBD>devuelve<76>un<75>booleano<6E>que<75>indica<63>si<73>la<6C>carga<67>se<73>ha<68>podido<64>realizar.
void mostrar(const tRegSudoku& sudoku); //Visualiza<7A>en<65>la<6C>consola<6C>la informaci<63>n<EFBFBD>del<65>registro<72>dado.
void iniciar(tRegSudoku& registro, std::string file, int puntos); //Inicia<69>el<65>registro<72>con<6F>los<6F>datos<6F>file<6C>y<EFBFBD>puntos.
bool guardar(const tRegSudoku& registro, std::ostream& outfile); //Almacena<6E>en<65>outfile<6C>el<65>contenido<64>de<64>registro<72>y<EFBFBD>devuelve<76>un<75>valor<6F>booleano<6E> indicando<64>si<73>la<6C>acci<63>n<EFBFBD>fue<75>posible.Debe<62>respetar<61>el<65>formato<74>del<65>archivo.
bool operator<(const tRegSudoku& regIzq, const tRegSudoku& regDer); //Sobrecarga<67>del operador < para<72>datos del<65>tipo tRegSudoku de acuerdo<64>con<6F>el<65>orden<65>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<73> 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<67>la<6C>informaci<63>n<EFBFBD>almacenada<64>en<65>el<65>archivo<76>de<64>nombre<72>nombreFichero<72>que<75> contiene<6E>el<65>tablero<72>del<65>sudoku<6B>a<EFBFBD>jugar, contando<64>las<61>casillas, y<>devuelve<76>un<75> booleano<6E>que<75>indica<63>si<73>la<6C>carga<67>se<73>ha<68>podido<64>realizar.Los<6F>valores<65>posibles<65>de<64> las<61>casillas<61>deber<65>n<EFBFBD>quedar<61>convenientemente<74>actualizados.
void mostrar(const tTableroSudoku& tablero); //Muestra<72>por<6F>pantalla<6C>el<65>tablero<72>dado.
bool actualizar(tTableroSudoku& tablero, tCoor cor, int num); //Coloca<63>el<65>n<EFBFBD><6E>num<75>en<65>la<6C>casilla<6C>de<64>coordenadas<61>cor = (fila, col)<29>(ambas<61>en<65>el<65> intervalo<6C>[0, 8])<29>del<65>tablero<72>tablero;<3B>el<65>booleano<6E>que<75>devuelve<76>indica<63>si<73>la<6C> acci<63>n<EFBFBD>ha<68>sido<64>posible<6C>(para<72>ello<6C>la<6C>casilla<6C>debe<62>ser<65>vac<61>a<EFBFBD>y<EFBFBD>num<75>debe<62>ser<65>uno<6E>de<64> los<6F>valores<65>posibles<65>de<64>la<6C>misma).Si<53>es<65>posible<6C>colocar<61>el<65>n<EFBFBD>mero<72>dado<64>en<65>la<6C> casilla<6C>indicada<64>deber<65>n<EFBFBD>actualizarse<73>convenientemente<74>los<6F>valores<65>candidatos<6F> de<64>las<61>casillas<61>que<75>puedan<61>verse<73>afectadas<61>(las<61>de<64>la<6C>misma<6D>fila, columna<6E>y submatriz<69> que<75> la<6C> casilla<6C> dada).Tambi<62>n<EFBFBD> se<73> debe<62> actualizar<61> el<65> n<>mero<72> de<64> casillas<61>vac<61>as.
bool borrar(tTableroSudoku& tablero, tCoor cor); //Borra<72>el<65>n<EFBFBD>mero<72> de<64>la<6C>casilla<6C>de<64>coordenadas<61>cor = (fila, col)<29><>(ambas<61>en<65>el<65>intervalo<6C>[0, 8])<29>del<65> tablero<72>tablero<72>y<EFBFBD>la<6C>casilla<6C>volver<65><72>a<EFBFBD>estar<61>en<65>estado<64>vac<61>o;<3B>el<65>booleano<6E>que<75> devuelve<76>indica<63>si<73>la<6C>acci<63>n<EFBFBD>ha<68>sido<64>posible<6C>(debe<62>ser<65>una<6E>casilla<6C>que<75>haya<79>sido<64> previamente<74>rellenada).Si<53>es<65>posible<6C>borrar<61>el<65>n<EFBFBD>mero<72>de<64>la<6C>casilla<6C>indicada<64> deber<65>n<EFBFBD>actualizarse<73>convenientemente<74>los<6F>valores<65>candidatos<6F>de<64>las<61>casillas<61> que<75>puedan<61>verse<73>afectadas<61>(las<61>de<64>la<6C>misma<6D>fila, columna<6E>y<EFBFBD>submatriz<69>que<75>la<6C> casilla<6C>dada).Tambi<62>n<EFBFBD>se<73>debe<62>actualizar<61>el<65>n<EFBFBD>mero<72>de<64>casillas<61>vac<61>as.
void mostrarCandidatos(const tTableroSudoku& tablero, tCoor cor); //Muestra<72>los<6F>valores<65>posibles<65>de<64>la<6C>casilla, del<65>tablero<72>dado, que<75>tiene<6E><65> coordenadas<61>cor = (fila, col)<29>(ambas<61>en<65>el<65>intervalo<6C>[0, 8]).
void completarSimples(tTableroSudoku& tablero); //En<45>cada<64>casilla<6C>que<75> tiene<6E> un<75> <20>nico<63> valor<6F> posible<6C> se<73> pone<6E> dicho<68> valor<6F> y<> se<73> actualizan<61> convenientemente<74> los<6F> valores<65> posibles<65> de<64> las<61> casillas<61> que<75> puedan<61> verse<73> afectadas.Tambi<62>n<EFBFBD>se<73>debe<62>actualizar<61>el<65>n<EFBFBD>mero<72>de<64>casillas<61>vac<61>as.
int numVacias(const tTableroSudoku& tablero); //Devuelve<76>el<65>n<EFBFBD>mero<72> de<64>casillas<61>vac<61>as<61>del<65>tablero<72>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<41> la consola puede imprimir caracteres especiales del espa<70>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<63>n del sudoku: ";
cin >> sudoku.puntos;
insertar(lista, sudoku);
pausa();
break;
case '0':
break;
default:
break;
}
} while (opc != '0');
}
char menu() {
//Par<61>metros: no tiene.
//Devuelve: la opci<63>n del men<65> 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<63>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