package es.upm.dit.adsw.cifrasyletras.juego;
import es.upm.dit.adsw.cifrasyletras.cifras.Cifras;
import es.upm.dit.adsw.cifrasyletras.cifras.CifrasPracticaCompetitiva;
import es.upm.dit.adsw.cifrasyletras.letras.Letras;
import es.upm.dit.adsw.cifrasyletras.letras.LetrasPracticaCompetitiva;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class JuegoCompetitivo {
//Hay 2 jugadores, por lo que cada ronda devuelve dos soluciones con dos puntuaciones acumuladas
private static final int NUM_LETRAS = 9;
private static final int NUM_CIFRAS = 6;
private final int pruebasCifras;
private final int pruebasLetras;
private final Letras jugadorLetras1;
private final Letras jugadorLetras2;
private final Cifras jugadorCifras1;
private final Cifras jugadorCifras2;
private final MonitorJuegoCompetitivo monitor;
private final ValidadorCifrasConParentesis validadorCifras;
private final ValidadorLetras validadorLetras;
private int puntosJ1 = 0;
private int puntosJ2 = 0;
public static void main(String[] args) {
MonitorJuegoCompetitivo monitor = new MonitorJuegoCompetitivo();
JuegoCompetitivo juego = new JuegoCompetitivo(
3, 3,
new LetrasPracticaCompetitiva(1, monitor),
new LetrasPracticaCompetitiva(2, monitor),
new CifrasPracticaCompetitiva(1, monitor),
new CifrasPracticaCompetitiva(2, monitor),
monitor
);
juego.jugar();
}
public JuegoCompetitivo(int pruebasCifras, int pruebasLetras,
Letras jugadorLetras1, Letras jugadorLetras2,
Cifras jugadorCifras1, Cifras jugadorCifras2,
MonitorJuegoCompetitivo monitor) {
this.pruebasCifras = pruebasCifras;
this.pruebasLetras = pruebasLetras;
this.jugadorLetras1 = jugadorLetras1;
this.jugadorLetras2 = jugadorLetras2;
this.jugadorCifras1 = jugadorCifras1;
this.jugadorCifras2 = jugadorCifras2;
this.monitor = monitor;
this.validadorCifras = new ValidadorCifrasConParentesis();
this.validadorLetras = new ValidadorLetras("data/es.txt");
if (!(jugadorLetras1 instanceof Thread) || !(jugadorLetras2 instanceof Thread)) {
System.err.println("Los solvers de letras deben extender Thread");
System.exit(1);
}
if (!(jugadorCifras1 instanceof Thread) || !(jugadorCifras2 instanceof Thread)) {
System.err.println("Los solvers de cifras deben extender Thread");
System.exit(1);
}
}
public void jugar() {
System.out.println("=== COMENZANDO JUEGO COMPETITIVO ===");
// Arrancar los cuatro hilos
((Thread) jugadorCifras1).start();
((Thread) jugadorCifras2).start();
((Thread) jugadorLetras1).start();
((Thread) jugadorLetras2).start();
System.out.println("Pruebas de letras: " + pruebasLetras);
System.out.println("Pruebas de cifras: " + pruebasCifras);
System.out.println();
jugarPruebasLetras();
jugarPruebasCifras();
imprimirResultadoFinal();
System.exit(0);
}
private void jugarPruebasLetras() {
System.out.println("--- PRUEBAS DE LETRAS ---");
for (int i = 0; i < pruebasLetras; i++) {
String letras = generarPruebaLetrasPorFrecuencias();
System.out.println("\n=== RONDA " + (i + 1) + ": LETRAS ===");
System.out.println("Letras disponibles: " + letras);
String[] soluciones = monitor.publicarPruebaLetras(letras);
String solJ1 = soluciones[0];
String solJ2 = soluciones[1];
System.out.println("J1: " + (solJ1 != null ? solJ1 : "(sin solución)"));
System.out.println("J2: " + (solJ2 != null ? solJ2 : "(sin solución)"));
int[] puntos = calcularPuntosLetras(solJ1, solJ2, letras);
puntosJ1 += puntos[0];
puntosJ2 += puntos[1];
System.out.println("Puntos esta ronda → J1: " + puntos[0] + ", J2: " + puntos[1]);
System.out.println("Acumulado → J1: " + puntosJ1 + ", J2: " + puntosJ2);
}
}
private void jugarPruebasCifras() {
System.out.println("\n--- PRUEBAS DE CIFRAS ---");
for (int i = 0; i < pruebasCifras; i++) {
int objetivo = generarObjetivoCifras();
List<Integer> numeros = generarNumerosCifras();
System.out.println("\n=== RONDA " + (i + 1) + ": CIFRAS ===");
System.out.println("Números disponibles: " + numeros + ", objetivo: " + objetivo);
String[] soluciones = monitor.publicarPruebaCifras(numeros, objetivo);
String solJ1 = soluciones[0];
String solJ2 = soluciones[1];
System.out.println("J1: " + (solJ1 != null ? solJ1 : "(sin solución)"));
System.out.println("J2: " + (solJ2 != null ? solJ2 : "(sin solución)"));
int[] puntos = calcularPuntosCifras(solJ1, solJ2, numeros, objetivo);
puntosJ1 += puntos[0];
puntosJ2 += puntos[1];
System.out.println("Puntos esta ronda → J1: " + puntos[0] + ", J2: " + puntos[1]);
System.out.println("Acumulado → J1: " + puntosJ1 + ", J2: " + puntosJ2);
}
}
/**
* Calcula los puntos de cada jugador para una prueba de cifras.
*
* @param solJ1 solución del jugador 1 en formato "resultado = expresion" (puede ser null)
* @param solJ2 solución del jugador 2
* @param numeros números usados en la prueba
* @param objetivo valor objetivo
* @return array {puntosJ1, puntosJ2}
*/
private int[] calcularPuntosCifras(String solJ1, String solJ2,
List<Integer> numeros, int objetivo) {
int distJ1 = distanciaCifras(solJ1, numeros, objetivo);
int distJ2 = distanciaCifras(solJ2, numeros, objetivo);
return asignarPuntos(distJ1 == 0, distJ2 == 0, distJ1, distJ2); //debe de invocar a este metodo para asignar puntos de la ronda
} // si las distancias es igual a cero es que son perfectas y el de menor distancia sera el que mas se acerque a este
/**
* Calcula los puntos de cada jugador para una prueba de letras.
*
* @param solJ1 palabra del jugador 1 (puede ser null)
* @param solJ2 palabra del jugador 2
* @param letras letras disponibles en la prueba
* @return array {puntosJ1, puntosJ2}
*/
private int[] calcularPuntosLetras(String solJ1, String solJ2, String letras) {
int lenJ1 = longitudLetras(solJ1, letras);
int lenJ2 = longitudLetras(solJ2, letras);
boolean perfectaJ1 = (solJ1 != null && lenJ1 == letras.length());
boolean perfectaJ2 = (solJ2 != null && lenJ2 == letras.length());
// Para letras, "mejor" = más larga, así que usamos como distancia la longitud negada
// (menor distancia = mejor). Aqui adaptamos la logica: mayor longitud gana.
return asignarPuntos(perfectaJ1, perfectaJ2, -lenJ1, -lenJ2);
}
/**
* Aplica la tabla de puntuacion: perfecta=10, ninguna perfecta y mejor=7, empate=5/5.
*
* @param perfectaJ1 si el jugador 1 tiene solucion perfecta
* @param perfectaJ2 si el jugador 2 tiene solucion perfecta
* @param metricaJ1 cuanto mas pequena, mejor para J1 (distancia al objetivo, o -longitud)
* @param metricaJ2 cuanto mas pequena, mejor para J2
* @return {puntosJ1, puntosJ2}
*/
//METODO PARA ASIGNAR PUNTOS
private int[] asignarPuntos(boolean perfectaJ1, boolean perfectaJ2, int metricaJ1, int metricaJ2) {
int[] puntos = new int[2];
if(perfectaJ1 && perfectaJ2) {
puntos[0] = 10; // puntuacion del jugador uno
puntos[1] = 10; // puntuacion del jugador dos
}
else if(perfectaJ1) {
puntos[0] = 10;
puntos[1] = 0;
}
else if(perfectaJ2) {
puntos[0] = 0;
puntos[1] = 10;
}
else if(metricaJ1 > metricaJ2) {
puntos[0] = 0;
puntos[1] = 7;
}
else if(metricaJ2 > metricaJ1) {
puntos[0] = 7;
puntos[1] = 0;
}
else if(metricaJ1 == metricaJ2 && metricaJ1 != Integer.MAX_VALUE ) {
puntos[0] = 5;
puntos[1] = 5;
}
else {
puntos[0] = 0;
puntos[1] = 0;
}
return puntos;
}
/**
* Valida la solucion de cifras y devuelve la distancia al objetivo.
* Devuelve Integer.MAX_VALUE si la solución es nula o inválida.
*/
private int distanciaCifras(String sol, List<Integer> numeros, int objetivo) {
if (sol == null || !validadorCifras.esValida(sol, numeros)) {
return Integer.MAX_VALUE;
}
try {
int resultado = Integer.parseInt(sol.trim().split("\\s*=\\s*")[0].trim());
return Math.abs(resultado - objetivo);
} catch (NumberFormatException e) {
return Integer.MAX_VALUE;
}
}
/**
* Valida la palabra y devuelve su longitud. Devuelve 0 si es nula o inválida.
*/
private int longitudLetras(String sol, String letras) {
if (sol == null || !validadorLetras.esValida(sol, letras)) {
return 0;
}
return sol.length();
}
private void imprimirResultadoFinal() {
System.out.println("\n==============================");
System.out.println("=== RESULTADO FINAL ===");
System.out.println("Jugador 1: " + puntosJ1 + " puntos");
System.out.println("Jugador 2: " + puntosJ2 + " puntos");
if (puntosJ1 > puntosJ2) {
System.out.println("¡Gana el Jugador 1!");
} else if (puntosJ2 > puntosJ1) {
System.out.println("¡Gana el Jugador 2!");
} else {
System.out.println("¡Empate!");
}
System.out.println("==============================");
}
// -------- Generadores de pruebas (igual que JuegoConcurrente) --------
public String generarPruebaLetrasPorFrecuencias() {
String letrasPonderadas =
"AAAAAAAAAAAAEEEEEEEEEEEEOOOOOOOOOIIIIIIUUUUSSSSSSSNNNNNNRRRRRRLLLLLDDDDDCCCCTTTTMMMPPPBBGGVYQHFJZXÑ"
.toLowerCase();
StringBuilder mano = new StringBuilder();
Random r = new Random();
for (int i = 0; i < NUM_LETRAS; i++) {
mano.append(letrasPonderadas.charAt(r.nextInt(letrasPonderadas.length())));
}
return mano.toString();
}
public int generarObjetivoCifras() {
return Math.abs((int) (Math.random() * 899)) + 101;
}
public List<Integer> generarNumerosCifras() {
List<Integer> numeros = new ArrayList<>();
List<Integer> posibles = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 25, 50, 75, 100));
for (int i = 0; i < NUM_CIFRAS; i++) {
int n = posibles.get((int) (Math.random() * posibles.size()));
if (n >= 25) {
posibles.remove((Integer) n);
}
numeros.add(n);
}
return numeros;
}
To embed this project on your website, copy the following code and paste it into your website's HTML: