Anexos diversos.¶
Compartición de código entre proyectos Gradle de Netbeans¶
El proceso es sencillo:
Localiza el archivo JAR que contiene las clases que quieres importar y aprovechar en tu proyecto. Probablemente la ruta sea algo como «c:userspepeNetbeansProjectProyectobuildslibsarchivo.jar».
Ve a tu proyecto Gradle de Netbeans y localiza el archivo
build.gradle
.Dentro de
build.gradle
encuentra la seccióndependencies
y añade dentro esta línea ``implementation files(c:\users\pepe\NetbeansProject\Proyecto\builds\libs\archivo.jar)
Observa que en el último paso hemos duplicado la barra diagonal.
Compartición de código entre proyectos Maven en Netbeans¶
La clase UtilidadesFicheros
¶
A continuación se muestra el código completo de la clase UtilidadesFicheros
:
public class UtilidadesFicheros {
public static BufferedReader getBufferedReader(
String nombreFichero) throws
FileNotFoundException {
FileReader lector;
lector = new FileReader(nombreFichero);
BufferedReader bufferedReader;
bufferedReader = new BufferedReader(lector);
return bufferedReader;
}
public static PrintWriter getPrintWriter(
String nombreFichero) throws IOException {
PrintWriter printWriter;
FileWriter fileWriter;
fileWriter = new FileWriter(nombreFichero);
printWriter = new PrintWriter(fileWriter);
return printWriter;
//Fin de getPrintWriter
}
public static ArrayList<String> getLineasFichero(
String nombreFichero) throws IOException {
ArrayList<String> lineas = new ArrayList<String>();
BufferedReader bfr = getBufferedReader(nombreFichero);
//Leemos líneas del fichero...
String linea = bfr.readLine();
while (linea != null) {
//Y las añadimos al array
lineas.add(linea);
linea = bfr.readLine();
}
//Fin del bucle que lee líneas
return lineas;
}
//Fin de getLineasFichero
public static long getSuma(String[]
listaNombresFichero) {
long suma = 0;
ArrayList<String> lineas;
String lineaCantidad;
long cantidad;
for (String nombreFichero : listaNombresFichero) {
try {
//Recuperamos todas las lineas
lineas = getLineasFichero(nombreFichero);
//Pero solo nos interesa la primera
lineaCantidad = lineas.get(0);
//Convertimos la linea a número
cantidad = Long.parseLong(lineaCantidad);
//Y se incrementa la suma total
suma = suma + cantidad;
} catch (IOException e) {
System.err.println("Fallo al procesar el fichero "
+ nombreFichero);
//Fin del catch
}
//Fin del for que recorre los nombres de fichero
}
return suma;
}
}
Solución al problema del simulador de Casino¶
Se ha optado por un diseño muy simple y con un acoplamiento muy alto. En pocas palabras hay solo dos clases:
La clase
Banca
: ejecuta toda la simulación y acepta apuestas de jugadores. La banca crea los Jugadores (que serán hilos), y luego pasará a ejecutar la simulación, que puede pasar por diversos estados. Algunos métodos de la banca deben sersynchronized
, ya que todos los hilos Jugador tienen una referencia a la claseBanca
y por lo tanto puede haber varios hilos intentando entrar en un cierto método.La clase
Jugador
: no necesita métodossynchronized
, ya que cadaJugador
accede solo a su propia información. Sin embargo, si hubiese más de una banca (quizá porque un Jugador jugase a varias ruletas a la vez) la situación sería muy distinta.En realidad, la clase
Jugador
es solo una base para poder crear distintos tipos de Jugador que siguen distintas estrategias.
En las secciones siguientes se ilustra el código de las distintas clases.
La clase Banca¶
public class Banca {
protected long saldo;
protected boolean enBancarrota;
protected Random generador;
protected boolean sePuedenHacerApuestas;
protected int numeroGanador;
public enum Estado {
INICIO, ACEPTANDO_APUESTAS, RULETA_GIRANDO, PAGANDO_APUESTAS, EN_BANCARROTA
}
;
private Estado estadoRuleta;
private ArrayList<Jugador> apostadores;
public Banca(long saldoInicial) {
saldo = saldoInicial;
enBancarrota = false;
estadoRuleta = Estado.INICIO;
generador = new Random();
apostadores = new ArrayList<Jugador>();
}
public synchronized boolean enBancarrota() {
return enBancarrota;
}
public synchronized void sumarSaldo(
long cantidad) {
saldo = saldo + cantidad;
}
public synchronized void restarSaldo(
long cantidad) {
if (saldo - cantidad <= 0) {
saldo = 0;
estadoRuleta = Estado.EN_BANCARROTA;
return;
}
saldo = saldo - cantidad;
}
public synchronized void aceptarApuesta(
Jugador jugador) {
if (estadoRuleta == Estado.ACEPTANDO_APUESTAS) {
apostadores.add(jugador);
}
}
public synchronized boolean aceptaApuestas() {
if (estadoRuleta == Estado.ACEPTANDO_APUESTAS) {
return true;
}
return false;
}
public void comunicarNumeroGanador(int numero) {
/* Al pasar el número a los jugadores, ellos nos
* irán restando el saldo que les corresponda por haber ganado */
int numApostadores = apostadores.size();
for (Jugador apostador : apostadores) {
apostador.comunicarNumero(numeroGanador);
}
/* Una vez comunicadas todas las apuestas, borramos
* el vector. La partida va a volver a empezar */
apostadores.clear();
}
public void girarRuleta() throws
InterruptedException {
int segundosAzar;
System.out.println("Empieza el juego!");
while (estadoRuleta != Estado.EN_BANCARROTA) {
estadoRuleta = Estado.ACEPTANDO_APUESTAS;
/* Se eligen unos milisegundos al azar para que los jugadores
* elijan, aunque quizá no todos puedan llegar a apostar
*/
segundosAzar = 1 + generador.nextInt(3);
System.out.println("Hagan juego, tienen Vds " +
segundosAzar + " segundos");
Thread.sleep(1000 * segundosAzar);
System.out.println("Ya no va más, señores. ¡Girando!");
estadoRuleta = Estado.RULETA_GIRANDO;
Thread.sleep(3000);
numeroGanador = generador.nextInt(37);
System.out.println("El número ganador es el :" +
numeroGanador);
estadoRuleta = Estado.PAGANDO_APUESTAS;
this.comunicarNumeroGanador(numeroGanador);
System.out.println("El saldo de la banca es ahora:"
+ saldo);
}
}
public void simular(int jugadoresPar,
int jugadoresMartingala,
int jugadoresClasicos) throws
InterruptedException {
Thread[] hilosJugadoresPares = new Thread[jugadoresPar];
for (int i = 0; i < jugadoresPar; i++) {
JugadorParImpar jugador = new JugadorParImpar(
1000, this);
hilosJugadoresPares[i] = new Thread(jugador);
hilosJugadoresPares[i].setName("Apostador par/impar "
+ i);
hilosJugadoresPares[i].start();
}
Thread[] hilosJugadoresMartingala = new Thread[jugadoresMartingala];
for (int i = 0; i < jugadoresMartingala; i++) {
JugadorMartingala jugador = new JugadorMartingala(
1000, this);
hilosJugadoresMartingala[i] = new Thread(jugador);
hilosJugadoresMartingala[i].setName("Apostador martingala "
+ i);
hilosJugadoresMartingala[i].start();
}
Thread[] hilosJugadoresClasico = new Thread[jugadoresClasicos];
for (int i = 0; i < jugadoresClasicos; i++) {
JugadorClasico jugador = new JugadorClasico(1000,
this);
hilosJugadoresClasico[i] = new Thread(jugador);
hilosJugadoresClasico[i].setName("Apostador clasico "
+ i);
hilosJugadoresClasico[i].start();
}
this.girarRuleta();
}
public static void main(String[] args) throws
InterruptedException {
Banca b = new Banca(50000);
b.simular(5, 5, 5);
}
}
La clase Jugador¶
public abstract class Jugador implements
Runnable {
protected long saldo;
protected boolean enBancarrota;
protected long cantidadApostada;
protected boolean apuestaRealizada;
protected Banca banca;
protected String nombreHilo;
protected Random generador;
public Jugador(long saldoInicial, Banca b) {
saldo = saldoInicial;
banca = b;
apuestaRealizada = false;
generador = new Random();
}
public void sumarSaldo(long cantidad) {
saldo = saldo + cantidad;
}
public void restarSaldo(long cantidad) {
if (saldo - cantidad <= 0) {
saldo = 0;
enBancarrota = true;
return;
}
saldo = saldo - cantidad;
}
public boolean enBancarrota() {
return enBancarrota;
}
/* Lo usa la banca para comunicarnos el número*/
public abstract void comunicarNumero(int numero);
public abstract void hacerApuesta();
/* Todos los jugadores hacen lo mismo:
* Mientras no estemos en bancarrota ni la
* banca tampoco, hacemos apuestas. La banca
* nos dirá el número que haya salido y en
* ese momento (y si procede) incrementaremos
* nuestro saldo
*/
@Override
public void run() {
nombreHilo = Thread.currentThread().getName();
while ((!enBancarrota)
&& (!banca.enBancarrota())) {
int msAzar;
/* Mientras la ruleta no acepte apuestas, dormimos un
* periodo al azar */
while (!banca.aceptaApuestas()) {
msAzar = this.generador.nextInt(500);
try {
//System.out.println(nombreHilo+":banca ocupada, durmiendo...");
Thread.sleep(msAzar);
} catch (InterruptedException e) {
return;
}
if (banca.enBancarrota()) {
return;
}
}
hacerApuesta();
}
String nombre = Thread.currentThread().getName();
if (enBancarrota) {
System.out.println(nombre +
": ¡¡Me arruiné!!");
return;
}
if (banca.enBancarrota()) {
System.out.println(nombre +
" hizo saltar la banca");
}
}
}
La clase JugadorClasico¶
public class JugadorClasico extends Jugador {
int numeroElegido;
public JugadorClasico(long saldoInicial,
Banca b) {
super(saldoInicial, b);
}
@Override
public void comunicarNumero(int numero) {
/* No hace falta comprobar si el numero es
* 0, ya que este jugador no lo elige nunca */
if (numero == numeroElegido) {
System.out.println(nombreHilo +
": ¡Gana 36 veces lo jugado, 360 euros");
banca.restarSaldo(360);
sumarSaldo(360);
}
System.out.println(nombreHilo +
" queda con un saldo de " + saldo);
apuestaRealizada = false;
}
@Override
public void hacerApuesta() {
if (!banca.aceptaApuestas())
return;
if (apuestaRealizada)
return;
/* Elegimos del 1 al 36 (no se puede elegir el 0*/
numeroElegido = 1 + generador.nextInt(36);
banca.sumarSaldo(10);
restarSaldo(10);
apuestaRealizada = true;
banca.aceptarApuesta(this);
}
}
La clase JugadorParImpar¶
public class JugadorParImpar extends Jugador {
public JugadorParImpar(long saldoInicial,
Banca b) {
super(saldoInicial, b);
}
protected boolean jugamosAPares;
@Override
public void hacerApuesta() {
if (!banca.aceptaApuestas())
return;
if (apuestaRealizada)
return;
/* Elegimos una apuesta...*/
if (generador.nextBoolean() == true) {
//System.out.println(nombreHilo+" elige apostar a par");
jugamosAPares = true;
} else {
//System.out.println(nombreHilo+" elige apostar a impar");
jugamosAPares = false;
}
banca.sumarSaldo(10);
restarSaldo(10);
apuestaRealizada = true;
/* Y pedimos a la banca que nos la acepte*/
banca.aceptarApuesta(this);
}
public boolean esGanador(int num) {
/* Este jugador necesita comprobar si ha salido el 0,
* aunque no lo elige nunca, ya que si hemos apostado
* Par podríamos pensar que hemos ganado cuando no es así */
if (num == 0) {
return false;
} else {
if ((num % 2 == 0) && (jugamosAPares)) {
return true;
}
if ((num % 2 != 0) && (!jugamosAPares)) {
return true;
}
}
//Fin del else externo
return false;
//Fin de esGanador
}
@Override
public void comunicarNumero(int numero) {
if (esGanador(numero)) {
/*Ganamos y cogemos a la banca 20 euros*/
System.out.println(nombreHilo +
" gana 20 euros por acertar impar");
banca.restarSaldo(20);
this.sumarSaldo(20);
}
System.out.println(nombreHilo +
" se queda con un saldo de " + saldo);
/* Sea como sea, al terminar indicamos que ya no tenemos
* una apuesta realizada. Es decir, permitirmos al
* jugador volver a apostar */
apuestaRealizada = false;
}
}
La clase JugadorMartingala¶
public class JugadorMartingala extends Jugador {
private int cantidadAApostar;
private int numeroElegido;
public JugadorMartingala(long saldoInicial,
Banca b) {
super(saldoInicial, b);
cantidadAApostar = 1;
}
@Override
public void comunicarNumero(int numero) {
if (numero == 0) {
System.out.println(nombreHilo + " pierde " +
cantidadAApostar);
cantidadAApostar = cantidadAApostar * 2;
return;
}
if (numeroElegido == numero) {
int beneficios = cantidadAApostar * 36;
banca.restarSaldo(beneficios);
sumarSaldo(beneficios);
cantidadAApostar = 1;
}
if (numeroElegido != numero) {
//System.out.println(nombreHilo + " pierde "+cantidadAApostar);
cantidadAApostar = cantidadAApostar * 2;
}
System.out.println(nombreHilo +
" queda con un saldo de " + saldo);
apuestaRealizada = false;
}
@Override
public void hacerApuesta() {
if (!banca.aceptaApuestas())
return;
if (apuestaRealizada)
return;
/* Elegimos del 1 al 36 (no se puede elegir el 0*/
numeroElegido = 1 + generador.nextInt(36);
banca.sumarSaldo(cantidadAApostar);
restarSaldo(cantidadAApostar);
apuestaRealizada = true;
banca.aceptarApuesta(this);
}
}