Autor Tema: Cómo programar un juego por turnos en Java con personajes y niveles dificultad  (Leído 15314 veces)

Heroic

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 6
    • Ver Perfil
Hola soy nuevo en esto de la programación y solicito ayuda para el siguiente programa:

Un programa en java que contenga dos personajes: caballero y mago.

Ambos personajes tienen:

  • Nivel de ataque
  • Nivel de defensa
  • Nivel de vida
  • Nombre

El caballero tiene una función especial invocar relámpago

El mago tiene una función especial de curar sus heridas y lanzar hechizos.

Cuando se crea una instancia de la clase de caballero o mago, tienes que pasar sus parámetros de ataque, defensa y nivel de vida para crearlo.

El juego comienza con un enemigo que tiene el doble de niveles y es un tipo de caballero.

El juego pregunta si quieren defenderse o atacar, si atacan invocan el poder con un número aleatorio y con este ataque bajan puntos de vida a su oponente.

A continuación, al azar su oponente pide atacar o defender, si ataca, el ataque hará un número aleatorio y se repetirá hasta que uno de los personajes alcance su nivel de vida a cero.

El mago en cada turno puede elevar su nivel de vida en 1.

Solo tengo la súper clase de ahí en adelante no se que tengo que hacer, agradecería mucho su ayuda, adjunto el código de la súper clase

Código: [Seleccionar]
class Nivel {
    protected String nombre;
    protected int ataque;
    protected int defensa;
    protected int vida;
    public Nivel (){
           nombre = "Desconocido";
           ataque = 0;
           defensa = 0;
           vida = 0;
    }
    public Nivel (String nombre, int ataque, int defensa, int vida){
       this.nombre = nombre;
        this.ataque = ataque;
        this.defensa = defensa;
        this.vida = vida;
    }
   
    public void setnombre (String nom){
        this.nombre = nom;
    }
    public void setataque (String atac){
        this.nombre = atac;
    }
    public void setdefensa (String defn){
        this.nombre = defn;
    }
    public void setvida (String pv){
        this.nombre = pv;
    }
   
    public String getnombre (){
        return this.nombre;
    }
    public int getataque (){
        return this.ataque;
    }
    public int getdefensa (){
        return this.defensa;
    }
    public int getvida (){
        return this.vida;
    }
   
}
« Última modificación: 18 de Abril 2021, 11:12 por Ogramar »

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: Ayuda con un programa de juego por turnos en java
« Respuesta #1 en: 11 de Febrero 2021, 02:44 »
Hola.
Lo primero es recomendar escoger un nombre más adecuado para la super clase.

Puesto que vamos a crear "personajes", pues así es como llamaría yo a la superclase: Personaje

Lo segundo, como el enunciado es algo parco en detalles (suele ser habitual), debemos decidir y tener claras las mecánicas del juego.

¿Qué ha de pasar si el jugador decide defender y no atacar? El enunciado no dice nada.

¿Qué es eso del ataque relámpago? ¿Es el ataque normal o es un ataque especial?
Es decir, ¿el Caballero va a tener dos tipos de ataque, "normal" y Relámpago?
Y si es así, ¿el Relámpago se escoge? ¿O es algo que va a ocurrir al azar?
Si es al azar, ¿que porcentaje de posibilidades decidimos que ocurra?
¿Y en que consiste? ¿Doble de daño? ¿Triple de daño?...

Y el Mago puede recuperar un punto de vida, vale, pero... ¿Siempre? ¿Al azar?
Si es al azar, ¿que porcentaje de posibilidades decidimos que ocurra?


A ver, lo que yo haría, para no complicar en exceso.

Los Personajes atacan y defienden.
Así que la superclase Personaje tendrá un método para atacar() y otro para defender().
Luego las clases hijas puede que modifiquen a su manera estos métodos.

¿Y en que van a consistir estos métodos de atacar y defender?
Pues podemos hacer que generen un número al azar entre 1 y su nivel de ataque si ataca o nivel de defensa si defiende.

Así decidimos la intensidad de su ataque o defensa.
Vale ¿y que hacemos con este número al azar?

Atacar está claro que restará vida al oponente. Si obtenemos un 25, pues el oponente recibiría 25 puntos de daño.

Defender, en cambio, lo que puede hacer es restar intensidad al ataque que se va a recibir.

Si se recibe un ataque de 25, pero en nuestro turno hemos elegido defender y el método defensa() nos ha dado por ejemplo un 10.
Pues los daños recibidos se reducen a 15 (25 - 10 = 15)
Incluso si la defensa es mayor o igual al ataque, este habría quedado bloqueado por completo y no se recibiría daño alguno.

Aunque esta mecánica de restar vida, restar intensidad al ataque recibido... se programará después, en el programa principal.

Ahora mismo solo necesitamos completar la clase Personaje con esos dos métodos: atacar() y defender().
Y que retornen un valor int al azar, entre 1 y su nivel de ataque/defensa

Código: [Seleccionar]
import java.util.Random;

public class Personaje {
protected String nombre;
protected int ataque;
protected int defensa;
protected int vida;

public Personaje() {
nombre = "Desconocido";
ataque = 0;
defensa = 0;
vida = 0;
}
public Personaje(String nombre, int ataque, int defensa, int vida){
this.nombre = nombre;
this.ataque = ataque;
this.defensa = defensa;
this.vida = vida;
}

public void setNombre (String nom){
this.nombre = nom;
}
public void setAtaque (String atac){
this.nombre = atac;
}
public void setDefensa (String defn){
this.nombre = defn;
}
public void setVida (String pv){
this.nombre = pv;
}

public String getNombre (){
return this.nombre;
}
public int getAtaque (){
return this.ataque;
}
public int getDefensa (){
return this.defensa;
}
public int getVida (){
return this.vida;
}

public int atacar() {
Random azar = new Random();
//Ataque mínimo: 1, Maximo: según nivel de ataque
int puntosAtaque = azar.nextInt(ataque) + 1;

return puntosAtaque;
}

public int defender() {
Random azar = new Random();
//Defensa mínima: 1, Maxima: según nivel de defensa
int puntosDefensa = azar.nextInt(defensa) + 1;

return puntosDefensa;
}

}

Bueno, a ver ahora las clases hijas.

Caballero, ¿qué hacemos con lo del Relámpago?

Yo lo consideraría un ataque especial que puede ocurrir al azar, una especie de "ataque crítico".
Podemos darle un 10% de posibilidades de que ocurra y que su efecto sea que duplique los puntos de ataque.
Ya que las posibilidades son bajas, al menos que su efecto sea potente.

Para esto, sobreescribimos el método atacar() que hereda de su superclase Personaje

Código: [Seleccionar]
import java.util.Random;

public class Caballero extends Personaje{

public Caballero() {
super();
}

public Caballero(String nombre, int ataque, int defensa, int vida) {
super(nombre, ataque, defensa, vida);
}

@Override
public int atacar() {
/*
* Caballero puede conseguir duplicar el daño de ataque
* con su habilidad "Ataque Relampago".
*/
int puntosAtaque = super.atacar();

//Damos un 10% de posibilidad de obtener un "Ataque Relampago"
Random azar = new Random();
int valor = azar.nextInt(100);

if (valor%10 == 0) { //Comprobamos si es multiplo de 10
System.out.println("¡" + nombre + " consigue un Ataque Relampago!");
//Un "Ataque Relampago" duplica el daño del ataque
return puntosAtaque * 2;
}
else
return puntosAtaque;
}

}


Sobre el Mago, puede recuperar 1 punto de vida en cada turno.
Podemos hacer que esto tenga un 20% de posibilidades de que ocurra.

Y decimos que puede ocurrir en cada turno, tanto si elige atacar como si elige defender.

Así que podemos escribirle a Mago un método privado que se encargue de decidir si recupera el punto de vida o no.
Y luego sobreescribimos los métodos atacar() y defender() de su superclase para que antes de que retorne el valor int generado al azar, se decida si recupera punto de vida o no.

Código: [Seleccionar]
import java.util.Random;

public class Mago extends Personaje{

public Mago() {
super();
}

public Mago(String nombre, int ataque, int defensa, int vida) {
super(nombre, ataque, defensa, vida);
}

private void recuperarVida() {
/*
* 20% posibilidad de recuperar 1 punto de vida
* en cada turno de juego
*/
Random azar = new Random();
int valor = azar.nextInt(100);
if (valor%5 == 0) {//Comprobamos si es múltiplo de 5
System.out.println("¡" + nombre + " recupera 1 punto de vida!");
vida++;
}
}

@Override
public int atacar() {
//Posibilidad de recuperar vida en turno de aque
recuperarVida();
return super.atacar();
}

@Override
public int defender() {
//Posibilidad de recuperar vida en turno de defensa
recuperarVida();
return super.defender();
}

}


Y con esto tendríamos las clases para los personajes.

Ahora habría que escribir el programa principal para crear personaje y combatir contra la máquina.
Antes de meternos en eso (además, tengo que irme  :P , se me acabó el tiempo...) repasa bien estas clases que he escrito.
Comprueba que entiendes estos códigos y pregunta si algo no te queda claro.
Decide si te parece bien lo que propongo, o si tienes un enunciado más completo con más datos de los que has publicado, indica si hay algo que no hacemos bien, o no hemos tenido en cuenta, o lo que sea...

Un saludo.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Heroic

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 6
    • Ver Perfil
Ayuda con el main de un programa de juego por turnos en java
« Respuesta #2 en: 11 de Febrero 2021, 04:22 »
Hola solicito ayuda para crear el main del siguiente programa:

Un programa en java que contenga dos personales:

Caballero
Mago

Ambos personajes tienen:
Nivel de ataque
Nivel de defensa
Nivel de vida
Nombre

El caballero tiene una función especial invocar relámpago (Aquí el caballero debe tener la opción de usar la habilidad, aunque que sea golpe critico me gusto y no se como dejarlo)

El mago tiene una función especial de curar sus heridas y lanzar hechizos (Aquí el mago debe tener la opción de curarse así mismo 50 puntos vida y el hechizo es igual que el relampago del caballero).

Cuando se crea una instancia de la clase de caballero y mago, tienes que pasar sus parámetros de ataque, defensa y nivel de vida para crearlo.

El juego comienza con un enemigo que tiene el doble de niveles y es un tipo de caballero (El enemigo tiene las mismas habilidades que la clase caballero).

El juego pregunta si quieren defenderse o atacar, si atacan invocan el poder con un número aleatorio y con este ataque bajan puntos de vida a su oponente.

A continuación, al azar su oponente pide atacar o defender, si ataca, el ataque hará un número aleatorio y se repetirá hasta que uno de los personajes alcance su nivel de vida a cero.

El mago en cada turno puede elevar su nivel de vida en 1.

Gracias a Kabuto por ayudarme al definir la súper clase y las clases hijas, he llegado a comprenderlas, además he especificado unas partes que eran ambiguas,aquí adjunto todo

Súper clase personaje

Código: [Seleccionar]
import java.util.Random;

public class Personaje {
protected String nombre;
protected int ataque;
protected int defensa;
protected int vida;

public Personaje() {
nombre = "Desconocido";
ataque = 0;
defensa = 0;
vida = 0;
}
public Personaje(String nombre, int ataque, int defensa, int vida){
this.nombre = nombre;
this.ataque = ataque;
this.defensa = defensa;
this.vida = vida;
}

public void setNombre (String nom){
this.nombre = nom;
}
public void setAtaque (String atac){
this.nombre = atac;
}
public void setDefensa (String defn){
this.nombre = defn;
}
public void setVida (String pv){
this.nombre = pv;
}

public String getNombre (){
return this.nombre;
}
public int getAtaque (){
return this.ataque;
}
public int getDefensa (){
return this.defensa;
}
public int getVida (){
return this.vida;
}

public int atacar() {
Random azar = new Random();
//Ataque mínimo: 1, Maximo: según nivel de ataque
int puntosAtaque = azar.nextInt(ataque) + 1;

return puntosAtaque;
}

public int defender() {
Random azar = new Random();
//Defensa mínima: 1, Maxima: según nivel de defensa
int puntosDefensa = azar.nextInt(defensa) + 1;

return puntosDefensa;
}

}

Clase Caballero

Código: [Seleccionar]
import java.util.Random;

public class Caballero extends Personaje{

public Caballero() {
super();
}

public Caballero(String nombre, int ataque, int defensa, int vida) {
super(nombre, ataque, defensa, vida);
}

@Override
public int atacar() {
/*
* Caballero puede conseguir duplicar el daño de ataque
* con su habilidad "Ataque Relampago".
*/
int puntosAtaque = super.atacar();

//Damos un 10% de posibilidad de obtener un "Ataque Relampago"
Random azar = new Random();
int valor = azar.nextInt(100);

if (valor%10 == 0) { //Comprobamos si es multiplo de 10
System.out.println("¡" + nombre + " consigue un Ataque Relampago!");
//Un "Ataque Relampago" duplica el daño del ataque
return puntosAtaque * 2;
}
else
return puntosAtaque;
}

}

Clase Mago

Código: [Seleccionar]
import java.util.Random;

public class Mago extends Personaje{

public Mago() {
super();
}

public Mago(String nombre, int ataque, int defensa, int vida) {
super(nombre, ataque, defensa, vida);
}

private void recuperarVida() {
/*
* 20% posibilidad de recuperar 1 punto de vida
* en cada turno de juego
*/
Random azar = new Random();
int valor = azar.nextInt(100);
if (valor%5 == 0) {//Comprobamos si es múltiplo de 5
System.out.println("¡" + nombre + " recupera 1 punto de vida!");
vida++;
}
}

@Override
public int atacar() {
//Posibilidad de recuperar vida en turno de aque
recuperarVida();
return super.atacar();
}

@Override
public int defender() {
//Posibilidad de recuperar vida en turno de defensa
recuperarVida();
return super.defender();
}

}

La verdad he intentado hacer el main por mi cuenta pero no pude :"( te he fallado Kabuto, si alguien es amable de ayudarme por favor, se lo agradeceria de por vida   
« Última modificación: 11 de Febrero 2021, 04:42 por Heroic »

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: Ayuda con un programa de juego por turnos en java
« Respuesta #3 en: 12 de Febrero 2021, 00:30 »
He combinado los dos temas en uno solo, para que la información no quede dispersa.
« Última modificación: 12 de Febrero 2021, 23:54 por Kabuto »
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: Ayuda con el main de un programa de juego por turnos en java
« Respuesta #4 en: 12 de Febrero 2021, 02:01 »
Veo que das algunos detalles más sobre los ataques de los personajes:

Citar
El caballero tiene una función especial invocar relámpago (Aquí el caballero debe tener la opción de usar la habilidad, aunque que sea golpe critico me gusto y no se como dejarlo)

El mago tiene una función especial de curar sus heridas y lanzar hechizos (Aquí el mago debe tener la opción de curarse así mismo 50 puntos vida y el hechizo es igual que el relampago del caballero).

Parece que los "ataques especiales" si son opcionales y no algo que deba ocurrir al azar.

Bien, podemos hacer que TODOS los personajes tengan la probabilidad de conseguir un ataque crítico. Así que esto lo incluiremos en la superclase.

Luego a parte, cada clase hija tendrá sus ataques especiales opcionales durante el combate.

El Caballero tendrá el Ataque Relámpago, que para distinguirlo del "ataque crítico" que habíamos ideado antes, pues podemos hacer que en lugar de un número al azar, la potencia del golpe sea el nivel de ataque total del personaje, incrementado un 50%.
Así siempre será un ataque poderoso.
Los "ataques críticos" no siempre son poderosos porque lo que hace es duplicar el valor de ataque obtenido al azar..., y si resulta que al azar hemos obtenido un paupérrimo 1.. pues ese 1 multiplicado por 2 tampoco es que sea una maravilla je je..

El Mago tendría dos habilidades, curarse 50 puntos y además un hechizo equivalente al Ataque Relámpago.

Bien, estas habilidades resultan muy ventajosas y quizás podría ser interesante ponerles algún límite. Como poder usarla solo un número determinado de veces, o que tras usarla no pudiera volver a seleccionarla hasta que transcurran 5 turnos...

Pero bueno, para no complicar más las cosas, y como el personaje se va a tener que enfrentar a un enemigo que es el doble de poderoso..., pues dejaremos que pueda escoger siempre esas habilidades.


Bien, pues si estamos de acuerdo con esto, la superclase Personaje quedaría modificada de la siguiente forma para dotarla de la probabilidad de conseguir un ataque crítico.
Así, tanto Mago como Caballero contarán con esta posibilidad.

Código: [Seleccionar]
import java.util.Random;

public class Personaje {
protected String nombre;
protected int ataque;
protected int defensa;
protected int vida;

public Personaje() {
nombre = "Desconocido";
ataque = 0;
defensa = 0;
vida = 0;
}
public Personaje(String nombre, int ataque, int defensa, int vida){
this.nombre = nombre;
this.ataque = ataque;
this.defensa = defensa;
this.vida = vida;
}

public void setNombre (String nom){
this.nombre = nom;
}
public void setAtaque (String atac){
this.nombre = atac;
}
public void setDefensa (String defn){
this.nombre = defn;
}
public void setVida (String pv){
this.nombre = pv;
}

public String getNombre (){
return this.nombre;
}
public int getAtaque (){
return this.ataque;
}
public int getDefensa (){
return this.defensa;
}
public int getVida (){
return this.vida;
}

public int atacar() {
Random azar = new Random();
//Ataque mínimo: 1, Maximo: según nivel de ataque
int puntosAtaque = azar.nextInt(ataque) + 1;

//Damos un 10% de posibilidad de obtener un "Ataque Crítico"
int valor = azar.nextInt(100);

if (valor%10 == 0) { //Comprobamos si es multiplo de 10
System.out.println("¡" + nombre + " consigue un Ataque Crítico!");
//Un "Ataque Crítico" duplica el daño del ataque
return puntosAtaque * 2;
}
else
return puntosAtaque;
}

public int defender() {
Random azar = new Random();
//Defensa mínima: 1, Maxima: según nivel de defensa
int puntosDefensa = azar.nextInt(defensa) + 1;

return puntosDefensa;
}

}

La clase Caballero hereda esa posibilidad de conseguir un crítico. Ahora el "Ataque Relámpago" es un tipo de ataque opcional al ataque normal y garantiza el daño máximo según nivel de ataque, incrementado un 50%.

Código: [Seleccionar]
public class Caballero extends Personaje{

public Caballero() {
super();
}

public Caballero(String nombre, int ataque, int defensa, int vida) {
super(nombre, ataque, defensa, vida);
}

public int ataqueRelampago() {
/*
* Nivel de ataque máximo, incrementado un 50%
*/
return (int)(ataque * 1.5);
}

@Override
public String toString() {
return String.format("Caballero: %s / Nivel de Vida: %d", nombre, vida);
}

}

Le he sobreescrito el método toString() para conseguir de forma fácil la clase de Personaje, nombre y nivel de vida.
Esta info la querremos mostrar en pantalla durante el combate, así que de este modo ya tenemos un String construido con esos datos.

Bueno, yo he optado por solo mostrar esos datos. Se puede modificar para que se muestren también nivel de ataque y defensa.

Para el Mago haremos lo mismo.
Esta clase ahora tiene dos habilidades opcionales.

Un "hechizo de ataque", que es equivalente al "ataque relámpago" del caballero.

Un "hechizo de curación" para recuperar 50 puntos de vida.
Ojo a este hechizo porque no es tan fácil como simplemente sumar +50 a la vida del personaje.
Los personajes tienen un nivel de vida inicial que decide al construir el objeto Personaje, ¿Qué pasa si lanzo este hechizo cuándo tengo la vida completa?
Pues entonces no debería curar nada, porque aún no hemos perdido vida. Si dejamos que se sumen los 50 puntos de vida siempre que elijamos este hechizo, podríamos incrementar el nivel de vida hasta el infinito..

Solo debe sumar 50 puntos de vida cuando nos falten esos 50 puntos respecto al nivel de vida inicial, o más.

Y si nos falta vida, pero la diferencia es menos de 50 puntos, pues entonces deberíamos sumar solo lo justo para cubrir esa diferencia.

Para controlar esto, a Mago le añado un atributo extra, una constante, para saber cuál es la vida máxima que el mago puede conseguir.
Así, cuando el usuario elija el hechizo de curar 50 puntos, curará más o menos según la vida que hayamos perdido. Incluso puede que no cure nada porque ya estamos al máximo de vida (y el usuario habrá mal gastado este turno)

Luego además tiene la posibilidad extra de recuperar 1 punto de vida (si es que le falta vida) con una probabilidad del 20%.
El método que se encarga de esto, antes lo puse como private y lo incluí como parte de los métodos de atacar y defender que se heredaban de la superclase.
Pero como ahora se amplían las posibilidades, he decidido no incluirlo en ningún método.
Será un método público al que invocaremos desde el programa principal durante el combate.

Código: [Seleccionar]
import java.util.Random;

public class Mago extends Personaje{

private final int VIDA_MAX; //Los hechizos de curación no pueden rebasar este límite

public Mago() {
super();
VIDA_MAX = vida; //Vida inicial es el límite máximo
}

public Mago(String nombre, int ataque, int defensa, int vida) {
super(nombre, ataque, defensa, vida);
VIDA_MAX = vida; //Vida inicial es el límite máximo
}

public void recuperarVida() {
/*
* 20% posibilidad de recuperar 1 punto de vida
* en cada turno de juego.
* Pero solo sí no se tiene ya la vida al máximo
*/
if (vida < VIDA_MAX) {
Random azar = new Random();
int valor = azar.nextInt(100);
if (valor%5 == 0) {//Comprobamos si es múltiplo de 5
System.out.println("¡" + nombre + " recupera 1 punto de vida!");
vida++;
}
}
}

public void curar50puntos() {

if (vida == VIDA_MAX)//No se puede recuperar vida porque ya está en su límite
System.out.println("El hechizo de curación no tiene ningún efecto");
else {
/*
* Calculamos diferencia entre vica actual y vida maxima
* para saber si podemos recuperar 50 puntos o menos.
*/
int diferencia = VIDA_MAX - vida;
if (diferencia >= 50) {
vida += 50;
System.out.println("¡" + nombre + " recupera 50 puntos de vida!");
}
else {
vida += diferencia;
System.out.println("¡" + nombre + " recupera " + diferencia + " puntos de vida!");
}
}
}

public int hechizoAtaque() {
/*
* Nivel de ataque máximo, incrementado un 50%
*/
return (int)(ataque * 1.5);
}

@Override
public String toString() {
return String.format("Mago: %s / Nivel de Vida: %d", nombre, vida);
}

}
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: Ayuda con el main de un programa de juego por turnos en java
« Respuesta #5 en: 12 de Febrero 2021, 02:13 »
Ahora que tenemos ya más o menos establecidas las clases de los personajes, podemos pensar en hacer el main del programa.
Por desgracia, me quedo sin tiempo, pero puedo adelantar algo.

Creo que es interesante que al iniciarse el programa, lo primero que se encuentre el usuario es la posibilidad de crear su personaje, decidir la clase, nombre y los niveles de los atributos.
Para los niveles de ataque, defensa y vida he establecido unos límites mínimos y máximos.
Tu ya decides si quieres modificarlos.

Una vez creado el personaje, automáticamente se crea el Caballero que manejará la CPU y se muestra en pantalla las características del este personaje.

A partir de aquí debería comenzar el combate.
Mostrar menú para que el usuario elija atacar, defender o habilidades especiales (distintas según si maneja un Caballero o un Mago).
También habrá que decidir cómo ha de actuar la CPU. Esta deberá elegir al azar entre atacar, defender o Relámpago.

Y bueno, no me da tiempo para más por hoy. :-\
Solo he podido hacer la idea de la creación del personaje:

Código: [Seleccionar]
import java.util.Scanner;

public class Combate {

private static Scanner teclado = new Scanner(System.in);
private static Personaje jugador; //Podrá ser un Mago o un Caballero
private static Caballero CPU; //La CPU siempre es un Caballero

public static void main(String[] args) {

crearPersonaje();

//TODO Combatir...
}


private static void crearPersonaje() {
System.out.println("\t\tCREAR PERSONAJE");
System.out.println("\t\t----- ---------");
System.out.println("Clases disponibles:");
System.out.println("[1] -> Caballero");
System.out.println("[2] -> Mago");

System.out.print("Elige clase: ");
int clase = Integer.parseInt(teclado.nextLine());

System.out.print("\nNombre: ");
String nombre = teclado.nextLine();

System.out.print("Nivel de Ataque(min = 1/max = 10): ");
int ataque = Integer.parseInt(teclado.nextLine());
//Forzamos que el nivel escogido se ciña a los límites
if (ataque < 1)
ataque = 1;
else if (ataque > 10)
ataque = 10;

System.out.print("Nivel de Defensa(min = 1/max = 10): ");
int defensa = Integer.parseInt(teclado.nextLine());
if (defensa < 1)
defensa = 1;
else if (defensa > 10)
defensa = 10;

System.out.print("Nivel de Vida(min = 100/max = 1000): ");
int vida = Integer.parseInt(teclado.nextLine());
if (vida < 100)
vida = 100;
else if (vida > 1000)
vida = 1000;

//Tenemos todos los atributos necesarios, creamos Personaje
if (clase == 1) //Ha elegido Caballero
jugador = new Caballero(nombre, ataque, defensa, vida);
else //Mago
jugador = new Mago(nombre, ataque, defensa, vida);

System.out.println("\nEste es tu personaje:");
System.out.println(jugador);
pausa();

//Ahora creamos el Caballero CPU, con doble de potencia que el Jugador
CPU = new Caballero("Thanos", (ataque*2), (defensa*2), (vida*2));

System.out.println("Y este será tu rival:");
System.out.println(CPU);
System.out.println("Nivel de Ataque: " + CPU.getAtaque()
+ " / Nivel de Defensa: " + CPU.getDefensa());

pausa();
}


private static void pausa() {
System.out.println("\n\t\tPULSA ENTER PARA SEGUIR\n");
teclado.nextLine();
}
}
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Heroic

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 6
    • Ver Perfil
Re: Ayuda con el main de un programa de juego por turnos en java
« Respuesta #6 en: 12 de Febrero 2021, 22:14 »
Muchas gracias Kabuto por tu ayuda en verdad te lo agradezco, ya solo si me pudieras ayudar con la parte del combate, intente hacerlo por mi cuenta pero igual no me salió y eso que estuve un buen rato :"(, gracias a tu ayuda he comprendido mas como funciona el programa y como actúan los métodos, la súper clase y sus clases hijas, muchas gracias de verdad, ya solo falta la parte del combate en serio si me ayudas me harías muy feliz.

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: Ayuda con un programa de juego por turnos en java
« Respuesta #7 en: 13 de Febrero 2021, 03:19 »
Bien, a ver, he vuelto a cambiar las clases de Personajes  :o

La superclase he quitado los setters, no son necesarios e incluso uno estaba mal. El setVida() recibía un String que lo seteaba al atributo nombre. Debería recibir un int para el atributo vida.
Pero en cualquier caso, no son necesarios los setters para este programa.
A cambio le añado un método llamado perderVida(), que recibe un int con la cantidad de daños sufridos en un turno, para que lo reste de la vida.

Código: [Seleccionar]
import java.util.Random;

public class Personaje {
protected String nombre;
protected int ataque;
protected int defensa;
protected int vida;

public Personaje() {
nombre = "Desconocido";
ataque = 0;
defensa = 0;
vida = 0;
}
public Personaje(String nombre, int ataque, int defensa, int vida){
this.nombre = nombre;
this.ataque = ataque;
this.defensa = defensa;
this.vida = vida;
}

public String getNombre (){
return this.nombre;
}
public int getAtaque (){
return this.ataque;
}
public int getDefensa (){
return this.defensa;
}
public int getVida (){
return this.vida;
}

public void perderVida(int danos) {
vida -= danos;
if (vida < 0) //Evitamos valores negativos en nivel de vida
vida = 0;
}

public int atacar() {
System.out.println(nombre + " ataca.");
Random azar = new Random();
//Ataque mínimo: 1, Maximo: según nivel de ataque
int puntosAtaque = azar.nextInt(ataque) + 1;

//Damos un 10% de posibilidad de obtener un "Ataque Crítico"
int valor = azar.nextInt(100);

if (valor%10 == 0) { //Comprobamos si es multiplo de 10
System.out.println("¡" + nombre + " consigue un Ataque Crítico!");
//Un "Ataque Crítico" duplica el daño del ataque
return puntosAtaque * 2;
}
else
return puntosAtaque;
}

public int defender() {
System.out.println(nombre + " se defiende.");
Random azar = new Random();
//Defensa mínima: 1, Maxima: según nivel de defensa
int puntosDefensa = azar.nextInt(defensa) + 1;

return puntosDefensa;
}

}

Caballero y Mago cambian muy ligeramente. Ahora son ellos mismos quienes muestran mensajes en pantalla para cada acción que realizan, mensajes tipo: "Caballero hace un ataque Relámpago"
Al principio había pensado lanzar esos mensajes desde el programa principal, pero mejor que cada método de estas clases se encargue de eso.

Código: [Seleccionar]
public class Caballero extends Personaje{

public Caballero() {
super();
}

public Caballero(String nombre, int ataque, int defensa, int vida) {
super(nombre, ataque, defensa, vida);
}

public int ataqueRelampago() {
/*
* Nivel de ataque máximo, incrementado un 50%
*/
System.out.println(nombre + " usa su ataque RELÁMPAGO");
return (int)(ataque * 1.5);
}

@Override
public String toString() {
return String.format("Caballero: %s / Nivel de Vida: %d", nombre, vida);
}

}

Código: [Seleccionar]
import java.util.Random;

public class Mago extends Personaje{

private final int VIDA_MAX; //Los hechizos de curación no pueden rebasar este límite

public Mago() {
super();
VIDA_MAX = vida; //Vida inicial es el límite máximo
}

public Mago(String nombre, int ataque, int defensa, int vida) {
super(nombre, ataque, defensa, vida);
VIDA_MAX = vida; //Vida inicial es el límite máximo
}

public boolean recuperarVida() {
/*
* 20% posibilidad de recuperar 1 punto de vida
* en cada turno de juego.
* Pero solo sí no se tiene ya la vida al máximo
*/
if (vida < VIDA_MAX) {
Random azar = new Random();
int valor = azar.nextInt(100);
if (valor%5 == 0) {//Comprobamos si es múltiplo de 5
System.out.println("¡" + nombre + " recupera 1 punto de vida!");
vida++;
return true;
}
}
return false;
}

public void curar50puntos() {

System.out.println(nombre + " usa su hechizo de SANACIÓN");

if (vida == VIDA_MAX)//No se puede recuperar vida porque ya está en su límite
System.out.println("El hechizo no tiene ningún efecto");
else {
/*
* Calculamos diferencia entre vica actual y vida maxima
* para saber si podemos recuperar 50 puntos o menos.
*/
int diferencia = VIDA_MAX - vida;
if (diferencia >= 50) {
vida += 50;
System.out.println("¡" + nombre + " recupera 50 puntos de vida!");
}
else {
vida += diferencia;
System.out.println("¡" + nombre + " recupera " + diferencia + " puntos de vida!");
}
}
}

public int hechizoAtaque() {
/*
* Nivel de ataque máximo, incrementado un 50%
*/
System.out.println(nombre + " usa su hechizo de ATAQUE");
return (int)(ataque * 1.5);
}

@Override
public String toString() {
return String.format("Mago: %s / Nivel de Vida: %d", nombre, vida);
}

}

Bien, sobre el programa principal,el main...
Habíamos hecho un método para poder crear un Personaje.
A partir de este Personaje, se autocrea el rival controlado por la CPU.

Ahora había que iniciar el motor del juego, un sistema de combate por turnos donde cada jugador elige una acción para actuar sobre el otro.

Esto básicamente se consigue con un bucle while(), que se repita mientras ambos jugadores sigan con vida.
Código: [Seleccionar]
//Comienza el combate...
while(jugador.getVida() > 0 && CPU.getVida() > 0) {
En cuanto uno de los dos muere (o ambos mueren, puede ocurrir...) el bucle while terminará.

Dentro de este bucle, el usuario ha de poder escoger una acción mediante un menú.
Este menú será algo distinto según si ha creado un Caballero, o un Mago, ya que tienen habilidades distintas.

Esto lo podemos hacer mediante este método. Muestra el menú adecuado según la clase de Jugador y retorna lo que elija el usuario:

Código: [Seleccionar]
private static int menuCombateJugador() {
System.out.println("\nTurno de " + jugador.getNombre());
//Opciones comunes a todos los jugadores
System.out.println("[1] -> Atacar");
System.out.println("[2] -> Defender");
//Opciones según la clase de Jugador
if (jugador instanceof Caballero) {
System.out.println("[3] -> Ataque RELÁMPAGO");
}
else {
System.out.println("[3] -> Hechizo de ATAQUE");
System.out.println("[4] -> Hechizo de SANACIÓN");
}
System.out.print("Elige acción: ");
return Integer.parseInt(teclado.nextLine());
}

Cuando nos retorne esta elección, desde el main la evaluaremos mediante un switch para invocar el método adecuado a lo que haya escogido:
atacar(), defender(), ataqueRelampago(), etc...

Estos métodos nos devuelve un int con una potencia de ataque o de defensa.
¿Y que hacemos con este int?
Se me ha ocurrido usar unas variables para recoger estos int.
Primero recogemos el ataque o defensa del jugador
Luego la CPU elige su acción y también recogeremos su ataque o defensa.

Y cuando lo tengamos, evaluamos daños.
El jugador recibe daños si el ataqueCPU supera a la defensaJugador
Y CPU recibe daños, si ataqueJugador supera defensaCPU.
Ojo, no me refiero al valor de sus atributos, si no a la potencia que los métodos atacar(), defender(), etc... consiguen de forma aleatoria, en base al valor de esos atributos.

Una vez hemos confrontado los ataques de uno con la defensa del otro (que será 0 si no eligió la acción defender() ) podemos mostrar en pantalla cuántos daños ha sufrido cada uno, y si ha muerto o no.

Bien, así que recapitulando, la mecánica es que el Jugador humano elige acción, y en base a su elección obtenemos unos valores de ataque y defensa.
Luego elige la CPU y así obtendremos sus valores de ataque y defensa.
Confrontamos estos valores y sabremos si alguien recibe daños, si alguien ha logrado bloquear por completo el ataque del otro y si alguien muere.

Y este proceso es lo que se repetirá dentro del bucle while.


Bien, hacer que elija el Jugador, es fácil, ya he puesto antes el método que hará eso.

Hacer que elija la CPU, también es fácil. Como la CPU siempre es un Caballero, solo tiene tres posibles acciones: atacar, defender, y relámpago.
Así que basta con que genera un número al azar entre 1 y 3.

Sin embargo, al llegar a este punto, se me ha ocurrido incluir una funcionalidad extra en el programa, un nivel de dificultad seleccionable.

El jugador podrá elegir entre modo normal o difícil. Este modo se controla mediante una variable boolean global

Código: [Seleccionar]
private static void elegirDificultad() {
System.out.println("\n\t\tNIVEL DIFICULTAD");
System.out.println("\n\t\t----- ----------");
System.out.println("[1] -> Modo NORMAL(Por defecto)");
System.out.println("[2] -> Modo DIFICIL(La CPU será más inteligente)");
System.out.print("Elige modo: ");
int modo = Integer.parseInt(teclado.nextLine());
//si teclea 2, pasa a modo dificil
if (modo == 2)
modoDificil = true;
//Si teclea 1 o cualquier otra cosa, no se cambia el modo
}

Normal, es que la CPU hace elecciones al azar, como hemos dicho. Es el modo por defecto.

Difícil, en cambio, consistiría en dotar a la CPU de cierta inteligencia, para depender menos del azar.
En este modo, la CPU analizaría los valores de ataque y defensa que ha conseguido previamente el jugador humano. Y según estos valores, dará más o menos probabilidades a las distintas acciones.
Por ejemplo, si el humano a elegido defender, es decir, no va a atacar en este turno, entonces la CPU no hay riesgo de recibir daños. Así que en este caso, la CPU nunca elegirá defenderse, se centrará en atacar. Y cuanto mayor sea la defensa que ha conseguido el jugador, más favorecerá un ataque Relámpago para intentar causar los mayores daños.

En cambio, si la CPU detecta que el jugador Humano está atacando, y ha conseguido un ataque potente... entonces dará mayor probabilidades a la acción defender, para protegerse de este ataque.

Así pues, el programa tendrá dos métodos para que la CPU escoja acción.
Este sería para el modo normal, simplemente, un número al azar:
Código: [Seleccionar]
private static int CPUmodoNormal() {
/*
* En el modo normal las acciones de la CPU
* se eligen completamente por azar.
*/
Random azar = new Random();
//Al ser un Caballero, solo tiene 3 posibles acciones, entre 1 y 3
//Si retorna 1, atacará
//Si es 2, se defenderá
//3, ¡¡Ataque Relámpago!!
return azar.nextInt(3) + 1;
}

Y a continuación el método para el modo difícil, donde la CPU estará dotada con una sencilla IA, para ser más estratégica en base a las acciones del jugador humano.
Código: [Seleccionar]
private static int CPUmodoDificil(int ataqueJugador, int defensaJugador) {
/*
* En el modo difícil, las acciones van a depender menos del azar.
* La CPU evaluará si el jugador ataca o se defiende,
* y con que intensidad, para favorecer más unas acciones u otras.
*/
int[] arrayAcciones = new int[10];
/*
* Las acciones de la CPU se escogerán al azar desde un array de int.
* Este array tendrá varios valores entre 1 y 3, que son las posibles acciones a escoger.
* (1 = ataque; 2 = defender; 3 = ataque Relámpago)
*
* Este array se fabricará según el analisis de la jugada del Jugador Humano.
* Si por ejemplo el humano está defendiendo, el array no tendrá valor 2(defensa)
* porque la CPU no querrá defenderse, querrá atacar.
* En cambio, si detecta que el humano ha conseguido un ataque muy fuerte, si habrá más
* cantidad de valores 2 en el array, para favorecer que la CPU se defienda en lugar de atacar
*/

//Evaluamos acciones del Jugador
if (defensaJugador > 0) {
/*
* Jugador se está defendiendo, así que la CPU
* NO se va a defender ya que sería desperdiciar este turno.

* Atacará al jugador, y además favorecerá un "Ataque Relámpago"
* si detecta que la defensa del Jugador es muy alta.
*/
if (defensaJugador >= 9) //Defensa muy alta, mayor probabilidad de ataque relámpago
arrayAcciones = new int[]{1, 3, 3, 1, 3, 3, 1, 3, 3, 3};
else if (defensaJugador >= 5) //Defensa media, ataque relámpago un poco más probable
arrayAcciones = new int[]{1, 3, 1, 1, 3, 3, 1, 3, 3, 1};
else //Defensa baja, menos probabilidad de ataque Relámpago
arrayAcciones = new int[]{1, 3, 1, 1, 3, 1, 1, 3, 1, 1};
}
else { //Jugador no se defiende, está atacando o usando hechizo curación (si es un Mago)
//Según la fuerza de ataque, se favorecerá más o menos la defensa.
if (ataqueJugador >= 9) //Ataque fuerte, mucha defensa
arrayAcciones = new int[]{1, 2, 2, 3, 2, 2, 3, 2, 2, 3};
else if (ataqueJugador >= 5) //Ataque medio
arrayAcciones = new int[]{1, 1, 2, 3, 2, 2, 1, 2, 2, 3};
else if (ataqueJugador > 0) //Ataque bajo
arrayAcciones = new int[]{1, 1, 2, 3, 2, 3, 1, 1, 2, 3};
else if (ataqueJugador == 0) //Ataque es 0,.. ¡¡y defensa también es 0!!
//Esto solo ocurre cuando el jugador es un Mago usando hechizo de sanacion
//En este caso, CPU no se defiende, y además se favorece el ataque Relámpago
arrayAcciones = new int[]{1, 3, 3, 1, 3, 3, 1, 3, 3, 3};
}
/*
* Ya se ha conformado un array de acciones acorde
* según el análisis de la jugada del humano.
* Ahora retornaremos una accion al azar de este array
*/
Random azar = new Random();
return arrayAcciones[azar.nextInt(10)];
}

Por supuesto este añadido es una idea mía. Si no quieres implementarlo en tu programa, basta con quedarse solo con el modo normal.
(Sigue a continuación..)
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: Ayuda con un programa de juego por turnos en java
« Respuesta #8 en: 13 de Febrero 2021, 03:23 »
Bueno, pues esta es la explicación a grandes rasgos.
A continuación pongo el código completo de la clase main.
Con lo que he explicado, y la cantidad de comentarios que incluye el código, creo que se puede entender bastante bien como funciona.
Sin embargo, no dudes en preguntar lo que sea.

Por favor, no te conformes con tener un programa que funciona. Asegúrate de que además lo entiendes.

Código: [Seleccionar]
import java.util.Random;
import java.util.Scanner;

public class Combate {

private static Scanner teclado = new Scanner(System.in);
private static Personaje jugador; //Podrá ser un Mago o un Caballero
private static Caballero CPU; //La CPU siempre es un Caballero
private static boolean modoDificil = false; //Nivel de dificultad

public static void main(String[] args) {

crearPersonaje();

elegirDificultad();

//Comienza el combate...
while(jugador.getVida() > 0 && CPU.getVida() > 0) {
/*
* Las siguientes variables recogerán los valores de ataques o defensas
* de los combatientes, según la acción que escojan, en cada turno.
*/
int ataqueJugador = 0, ataqueCPU = 0;
int defensaJugador = 0, defensaCPU = 0;
System.out.println("\n\n\t\tCOMBATIENDO...");
System.out.println("> Jugador: " + jugador);
System.out.println("> CPU: " + CPU);
//Recogemos acción del jugador
int accionJugador = menuCombateJugador();
System.out.println(); //Salto de línea
//Evaluamos la acción escogida
switch(accionJugador) {
case 1: //Ataque normal
ataqueJugador = jugador.atacar();
System.out.println("Consigues un ATAQUE de " + ataqueJugador + " pts.");
break;
case 2: //Defender
defensaJugador = jugador.defender();
System.out.println("Consigues una DEFENSA de " + defensaJugador + " pts.");
break;
case 3: //Ataque relámpago o hechizo ataque, según clase
if (jugador instanceof Caballero) {
ataqueJugador = ((Caballero)jugador).ataqueRelampago();
System.out.println("Consigues un ATAQUE de " + ataqueJugador + " pts.");
}
else {
ataqueJugador = ((Mago)jugador).hechizoAtaque();
System.out.println("Consigues un ATAQUE de " + ataqueJugador + " pts.");
}
break;
case 4: //Hechizo sanación 50 puntos, solo sirve para Mago
if (jugador instanceof Caballero)
System.out.println("La acción no es válida. Pierdes tu turno");
else
((Mago)jugador).curar50puntos();
break;
default:
System.out.println("La acción no es válida. Pierdes tu turno");
}
pausa();
//A continuación elige acción la CPU
int accionCPU;
if (modoDificil)
accionCPU = CPUmodoDificil(ataqueJugador, defensaJugador);
else
accionCPU = CPUmodoNormal();
//Analizamos accion de CPU
switch(accionCPU) {
case 1:
ataqueCPU = CPU.atacar();
break;
case 2:
defensaCPU = CPU.defender();
break;
case 3:
ataqueCPU = CPU.ataqueRelampago();
}
pausa();
//Ambos Jugadores han actuado, evaluamos daños conseguidos
int danoRecibeJugador = ataqueCPU - defensaJugador;
int danoRecibeCPU = ataqueJugador - defensaCPU;
//Qué ha pasaso con Jugador
if (danoRecibeJugador > 0) {
System.out.println("\n" + jugador.getNombre() + " recibe daños.");
System.out.println("Pierde " + danoRecibeJugador + " puntos de vida.");
jugador.perderVida(danoRecibeJugador);
if (jugador.getVida() == 0)
System.out.println("¡" + jugador.getNombre() + " ha muerto!");
}
else {
//No recibe daños, comunicamos que ha conseguido bloquear ataque CPU
//Excepto si se debe a que CPU no atacó, por estar defendiendose.
if (accionCPU != 2)
System.out.println("\n" + jugador.getNombre() + " consigue bloquear ataque de "
+ CPU.getNombre());
}
//Qué ha pasado con CPU
if (danoRecibeCPU > 0) {
System.out.println("\n" + CPU.getNombre() + " recibe daños.");
System.out.println("Pierde " + danoRecibeCPU + " puntos de vida.");
CPU.perderVida(danoRecibeCPU);
if (CPU.getVida() == 0)
System.out.println("¡" + CPU.getNombre() + " ha muerto!");
}
else {
if (accionJugador == 1 || accionJugador == 3) {
System.out.println("\n" + CPU.getNombre() + " consigue bloquear ataque de "
+ jugador.getNombre());
}
}
pausa();
/*
* Acciones completadas, pero aún queda la probabilidad de que
* si el jugador humano es Mago, pueda recuperar un punto de vida.
* En caso de que el Mago estuviera muerto, ¡¡esto le da la posibilidad de resucitar!!
* aunque solo con un miserable punto de vida.
*/
if (jugador instanceof Mago) {
if (((Mago)jugador).recuperarVida()) {
//Comprobamos si estamos ante el milagro de la resurrección xD
if (jugador.getVida() == 1)
System.out.println("¡" + jugador.getNombre() + " ha resucitado!");

pausa();
}
}
/*
* Ahora sí se ha completado el turno.
* El bucle de combate se repetirá, excepto si alguien ha muerto
*/
}
//Fin bucle combate, comprobamos quien vive y quien no
if (jugador.getVida() > 0) {
System.out.println("\nVictoria para:");
System.out.println(jugador);
}
else if (CPU.getVida() > 0) {
System.out.println("\nVictoria para:");
System.out.println(CPU);
}
else //¡Ambos personajes han muerto!
System.out.println("\nNo hay ganador. Ambos jugadores se han destruido.");

System.out.println("\n\n\t\tFIN DE PROGRAMA");
}


private static void crearPersonaje() {
System.out.println("\t\tCREAR PERSONAJE");
System.out.println("\t\t----- ---------");
System.out.println("Clases disponibles:");
System.out.println("[1] -> Caballero");
System.out.println("[2] -> Mago");

System.out.print("Elige clase: ");
int clase = Integer.parseInt(teclado.nextLine());

System.out.print("\nNombre: ");
String nombre = teclado.nextLine();

System.out.print("Nivel de Ataque(min = 1/max = 10): ");
int ataque = Integer.parseInt(teclado.nextLine());
//Forzamos que el nivel escogido se ciña a los límites
if (ataque < 1)
ataque = 1;
else if (ataque > 10)
ataque = 10;

System.out.print("Nivel de Defensa(min = 1/max = 10): ");
int defensa = Integer.parseInt(teclado.nextLine());
if (defensa < 1)
defensa = 1;
else if (defensa > 10)
defensa = 10;

System.out.print("Nivel de Vida(min = 100/max = 1000): ");
int vida = Integer.parseInt(teclado.nextLine());
if (vida < 100)
vida = 100;
else if (vida > 1000)
vida = 1000;

//Tenemos todos los atributos necesarios, creamos Personaje
if (clase == 1) //Ha elegido Caballero
jugador = new Caballero(nombre, ataque, defensa, vida);
else //Mago
jugador = new Mago(nombre, ataque, defensa, vida);

System.out.println("\nEste es tu personaje:");
System.out.println(jugador);
pausa();

//Ahora creamos el Caballero CPU, con doble de potencia que el Jugador
CPU = new Caballero("Thanos", (ataque*2), (defensa*2), (vida*2));

System.out.println("Y este será tu rival:");
System.out.println(CPU);
System.out.println("Nivel de Ataque: " + CPU.getAtaque()
+ " / Nivel de Defensa: " + CPU.getDefensa());

pausa();
}

private static void elegirDificultad() {
System.out.println("\n\t\tNIVEL DIFICULTAD");
System.out.println("\n\t\t----- ----------");
System.out.println("[1] -> Modo NORMAL(Por defecto)");
System.out.println("[2] -> Modo DIFICIL(La CPU será más inteligente)");
System.out.print("Elige modo: ");
int modo = Integer.parseInt(teclado.nextLine());
//si teclea 2, pasa a modo dificil
if (modo == 2)
modoDificil = true;
//Si teclea 1 o cualquier otra cosa, no se cambia el modo
}

private static int menuCombateJugador() {
System.out.println("\nTurno de " + jugador.getNombre());
//Opciones comunes a todos los jugadores
System.out.println("[1] -> Atacar");
System.out.println("[2] -> Defender");
//Opciones según la clase de Jugador
if (jugador instanceof Caballero) {
System.out.println("[3] -> Ataque RELÁMPAGO");
}
else {
System.out.println("[3] -> Hechizo de ATAQUE");
System.out.println("[4] -> Hechizo de SANACIÓN");
}
System.out.print("Elige acción: ");
return Integer.parseInt(teclado.nextLine());
}

private static int CPUmodoNormal() {
/*
* En el modo normal las acciones de la CPU
* se eligen completamente por azar.
*/
Random azar = new Random();
//Al ser un Caballero, solo tiene 3 posibles acciones, entre 1 y 3
//Si retorna 1, atacará
//Si es 2, se defenderá
//3, ¡¡Ataque Relámpago!!
return azar.nextInt(3) + 1;
}

private static int CPUmodoDificil(int ataqueJugador, int defensaJugador) {
/*
* En el modo difícil, las acciones van a depender menos del azar.
* La CPU evaluará si el jugador ataca o se defiende,
* y con que intensidad, para favorecer más unas acciones u otras.
*/
int[] arrayAcciones = new int[10];
/*
* Las acciones de la CPU se escogerán al azar desde un array de int.
* Este array tendrá varios valores entre 1 y 3, que son las posibles acciones a escoger.
* (1 = ataque; 2 = defender; 3 = ataque Relámpago)
*
* Este array se fabricará según el analisis de la jugada del Jugador Humano.
* Si por ejemplo el humano está defendiendo, el array no tendrá valor 2(defensa)
* porque la CPU no querrá defenderse, querrá atacar.
* En cambio, si detecta que el humano ha conseguido un ataque muy fuerte, si habrá más
* cantidad de valores 2 en el array, para favorecer que la CPU se defienda en lugar de atacar
*/

//Evaluamos acciones del Jugador
if (defensaJugador > 0) {
/*
* Jugador se está defendiendo, así que la CPU
* NO se va a defender ya que sería desperdiciar este turno.

* Atacará al jugador, y además favorecerá un "Ataque Relámpago"
* si detecta que la defensa del Jugador es muy alta.
*/
if (defensaJugador >= 9) //Defensa muy alta, mayor probabilidad de ataque relámpago
arrayAcciones = new int[]{1, 3, 3, 1, 3, 3, 1, 3, 3, 3};
else if (defensaJugador >= 5) //Defensa media, ataque relámpago un poco más probable
arrayAcciones = new int[]{1, 3, 1, 1, 3, 3, 1, 3, 3, 1};
else //Defensa baja, menos probabilidad de ataque Relámpago
arrayAcciones = new int[]{1, 3, 1, 1, 3, 1, 1, 3, 1, 1};
}
else { //Jugador no se defiende, está atacando o usando hechizo curación (si es un Mago)
//Según la fuerza de ataque, se favorecerá más o menos la defensa.
if (ataqueJugador >= 9) //Ataque fuerte, mucha defensa
arrayAcciones = new int[]{1, 2, 2, 3, 2, 2, 3, 2, 2, 3};
else if (ataqueJugador >= 5) //Ataque medio
arrayAcciones = new int[]{1, 1, 2, 3, 2, 2, 1, 2, 2, 3};
else if (ataqueJugador > 0) //Ataque bajo
arrayAcciones = new int[]{1, 1, 2, 3, 2, 3, 1, 1, 2, 3};
else if (ataqueJugador == 0) //Ataque es 0,.. ¡¡y defensa también es 0!!
//Esto solo ocurre cuando el jugador es un Mago usando hechizo de sanacion
//En este caso, CPU no se defiende, y además se favorece el ataque Relámpago
arrayAcciones = new int[]{1, 3, 3, 1, 3, 3, 1, 3, 3, 3};
}
/*
* Ya se ha conformado un array de acciones acorde
* según el análisis de la jugada del humano.
* Ahora retornaremos una accion al azar de este array
*/
Random azar = new Random();
return arrayAcciones[azar.nextInt(10)];
}


private static void pausa() {
System.out.println("\n\t\tPULSA ENTER PARA SEGUIR\n");
teclado.nextLine();
}
}
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: Ayuda con un programa de juego por turnos en java
« Respuesta #9 en: 13 de Febrero 2021, 03:23 »
He jugado un par de partidas, en modo difícil.. y sí, es muy difícil.  ;D
Entre que el enemigo es el doble de potente, y que encima tiene cierta inteligencia...
Citar
      CREAR PERSONAJE
      ----- ---------
Clases disponibles:
[1] -> Caballero
[2] -> Mago
Elige clase: 2

Nombre: Gandalf
Nivel de Ataque(min = 1/max = 10): 10
Nivel de Defensa(min = 1/max = 10): 10
Nivel de Vida(min = 100/max = 1000): 150

Este es tu personaje:
Mago: Gandalf / Nivel de Vida: 150

      PULSA ENTER PARA SEGUIR


Y este será tu rival:
Caballero: Thanos / Nivel de Vida: 300
Nivel de Ataque: 20 / Nivel de Defensa: 20

      PULSA ENTER PARA SEGUIR



      NIVEL DIFICULTAD

      ----- ----------
[1] -> Modo NORMAL(Por defecto)
[2] -> Modo DIFICIL(La CPU será más inteligente)
Elige modo: 2


      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 150
> CPU: Caballero: Thanos / Nivel de Vida: 300

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 1

Gandalf ataca.
Consigues un ATAQUE de 8 pts.

      PULSA ENTER PARA SEGUIR


Thanos se defiende.

      PULSA ENTER PARA SEGUIR



Thanos consigue bloquear ataque de Gandalf

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 150
> CPU: Caballero: Thanos / Nivel de Vida: 300

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 2

Gandalf se defiende.
Consigues una DEFENSA de 9 pts.

      PULSA ENTER PARA SEGUIR


Thanos ataca.

      PULSA ENTER PARA SEGUIR



Gandalf consigue bloquear ataque de Thanos

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 150
> CPU: Caballero: Thanos / Nivel de Vida: 300

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 3

Gandalf usa su hechizo de ATAQUE
Consigues un ATAQUE de 15 pts.

      PULSA ENTER PARA SEGUIR


Thanos se defiende.

      PULSA ENTER PARA SEGUIR



Thanos recibe daños.
Pierde 10 puntos de vida.

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 150
> CPU: Caballero: Thanos / Nivel de Vida: 290

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 1

Gandalf ataca.
Consigues un ATAQUE de 1 pts.

      PULSA ENTER PARA SEGUIR


Thanos se defiende.

      PULSA ENTER PARA SEGUIR



Thanos consigue bloquear ataque de Gandalf

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 150
> CPU: Caballero: Thanos / Nivel de Vida: 290

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 1

Gandalf ataca.
Consigues un ATAQUE de 4 pts.

      PULSA ENTER PARA SEGUIR


Thanos se defiende.

      PULSA ENTER PARA SEGUIR



Thanos consigue bloquear ataque de Gandalf

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 150
> CPU: Caballero: Thanos / Nivel de Vida: 290

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 3

Gandalf usa su hechizo de ATAQUE
Consigues un ATAQUE de 15 pts.

      PULSA ENTER PARA SEGUIR


Thanos usa su ataque RELÁMPAGO

      PULSA ENTER PARA SEGUIR



Gandalf recibe daños.
Pierde 30 puntos de vida.

Thanos recibe daños.
Pierde 15 puntos de vida.

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 120
> CPU: Caballero: Thanos / Nivel de Vida: 275

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 1

Gandalf ataca.
¡Gandalf consigue un Ataque Crítico!
Consigues un ATAQUE de 8 pts.

      PULSA ENTER PARA SEGUIR


Thanos usa su ataque RELÁMPAGO

      PULSA ENTER PARA SEGUIR



Gandalf recibe daños.
Pierde 30 puntos de vida.

Thanos recibe daños.
Pierde 8 puntos de vida.

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 90
> CPU: Caballero: Thanos / Nivel de Vida: 267

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 4

Gandalf usa su hechizo de SANACIÓN
¡Gandalf recupera 50 puntos de vida!

      PULSA ENTER PARA SEGUIR


Thanos ataca.

      PULSA ENTER PARA SEGUIR



Gandalf recibe daños.
Pierde 4 puntos de vida.

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 136
> CPU: Caballero: Thanos / Nivel de Vida: 267

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 1

Gandalf ataca.
Consigues un ATAQUE de 1 pts.

      PULSA ENTER PARA SEGUIR


Thanos se defiende.

      PULSA ENTER PARA SEGUIR



Thanos consigue bloquear ataque de Gandalf

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 136
> CPU: Caballero: Thanos / Nivel de Vida: 267

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 3

Gandalf usa su hechizo de ATAQUE
Consigues un ATAQUE de 15 pts.

      PULSA ENTER PARA SEGUIR


Thanos se defiende.

      PULSA ENTER PARA SEGUIR



Thanos recibe daños.
Pierde 1 puntos de vida.

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 136
> CPU: Caballero: Thanos / Nivel de Vida: 266

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 1

Gandalf ataca.
¡Gandalf consigue un Ataque Crítico!
Consigues un ATAQUE de 12 pts.

      PULSA ENTER PARA SEGUIR


Thanos se defiende.

      PULSA ENTER PARA SEGUIR



Thanos recibe daños.
Pierde 6 puntos de vida.

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 136
> CPU: Caballero: Thanos / Nivel de Vida: 260

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 1

Gandalf ataca.
Consigues un ATAQUE de 5 pts.

      PULSA ENTER PARA SEGUIR


Thanos se defiende.

      PULSA ENTER PARA SEGUIR



Thanos consigue bloquear ataque de Gandalf

      PULSA ENTER PARA SEGUIR


¡Gandalf recupera 1 punto de vida!

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 137
> CPU: Caballero: Thanos / Nivel de Vida: 260

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 3

Gandalf usa su hechizo de ATAQUE
Consigues un ATAQUE de 15 pts.

      PULSA ENTER PARA SEGUIR


Thanos usa su ataque RELÁMPAGO

      PULSA ENTER PARA SEGUIR



Gandalf recibe daños.
Pierde 30 puntos de vida.

Thanos recibe daños.
Pierde 15 puntos de vida.

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 107
> CPU: Caballero: Thanos / Nivel de Vida: 245

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 3

Gandalf usa su hechizo de ATAQUE
Consigues un ATAQUE de 15 pts.

      PULSA ENTER PARA SEGUIR


Thanos usa su ataque RELÁMPAGO

      PULSA ENTER PARA SEGUIR



Gandalf recibe daños.
Pierde 30 puntos de vida.

Thanos recibe daños.
Pierde 15 puntos de vida.

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 77
> CPU: Caballero: Thanos / Nivel de Vida: 230

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 1

Gandalf ataca.
Consigues un ATAQUE de 2 pts.

      PULSA ENTER PARA SEGUIR


Thanos usa su ataque RELÁMPAGO

      PULSA ENTER PARA SEGUIR



Gandalf recibe daños.
Pierde 30 puntos de vida.

Thanos recibe daños.
Pierde 2 puntos de vida.

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 47
> CPU: Caballero: Thanos / Nivel de Vida: 228

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 3

Gandalf usa su hechizo de ATAQUE
Consigues un ATAQUE de 15 pts.

      PULSA ENTER PARA SEGUIR


Thanos se defiende.

      PULSA ENTER PARA SEGUIR



Thanos recibe daños.
Pierde 11 puntos de vida.

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 47
> CPU: Caballero: Thanos / Nivel de Vida: 217

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 1

Gandalf ataca.
Consigues un ATAQUE de 5 pts.

      PULSA ENTER PARA SEGUIR


Thanos usa su ataque RELÁMPAGO

      PULSA ENTER PARA SEGUIR



Gandalf recibe daños.
Pierde 30 puntos de vida.

Thanos recibe daños.
Pierde 5 puntos de vida.

      PULSA ENTER PARA SEGUIR




      COMBATIENDO...
> Jugador: Mago: Gandalf / Nivel de Vida: 17
> CPU: Caballero: Thanos / Nivel de Vida: 212

Turno de Gandalf
[1] -> Atacar
[2] -> Defender
[3] -> Hechizo de ATAQUE
[4] -> Hechizo de SANACIÓN
Elige acción: 1

Gandalf ataca.
Consigues un ATAQUE de 10 pts.

      PULSA ENTER PARA SEGUIR


Thanos usa su ataque RELÁMPAGO

      PULSA ENTER PARA SEGUIR



Gandalf recibe daños.
Pierde 30 puntos de vida.
¡Gandalf ha muerto!

Thanos recibe daños.
Pierde 10 puntos de vida.

      PULSA ENTER PARA SEGUIR



Victoria para:
Caballero: Thanos / Nivel de Vida: 202


      FIN DE PROGRAMA
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Heroic

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 6
    • Ver Perfil
Re: Ayuda con un programa de juego por turnos en java
« Respuesta #10 en: 13 de Febrero 2021, 04:05 »
Eres un crack Kabuto, muchas gracias por tu enorme ayuda, voy a estudiar todo el código desde el principio para comprenderlo aun mejor, la verdad si esta muy bien explicado en serio muchas gracias por tu ayuda, te mando un gran abrazo ;), saludos para ti.

Fede2808

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 1
    • Ver Perfil
Hola! Tienen el codigo completo? Me interesaria ver bien como funciona. Desde ya, muchas gracias!

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Adjunto un zip en este mensaje con el código.
Por cierto, aunque este tema es largo, es interesante leerlo para ver como fue la evolución de la creación del programa y entenderlo mejor.

Si surge alguna duda, consultadla por aquí.

Un saludo.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kaos

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 3
    • Ver Perfil
Hola buenas, ¿cómo sería si el caballero o el mago tuvieran que elegir entre dos armas diferentes, y cada arma incluye una bonificación diferente, por ejemplo, hacer más daño o aumentar la protección.
Esa elección se realizaria en la clase Combate, pero la especificación de esa elección, pudiendo ser diferente tanto para el caballero como para el mago, donde se especificaría. Es decir, si el caballero elige la opcion 1 es una espada y la bonificación de mas protección, ¿eso lo especifico en la clase Caballero?

Espero que alguien me pueda ayudar.

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil

Hasta ahora durante el combate el usuario tiene 4 opciones:
1- Ataque normal
2- Defender
3- Ataque "Especial", que es distinto según Caballero o Mago
4- Hechizo Sanación, solo válido para el Mago. Si el Caballero elige esta opción, pierde turno

Entonces, aquí pueden haber dos planteamientos.
Añadir una opción más a ese menú:
1- Ataque normal
2- Ataque alternativo
3- Defender
4- Ataque "Especial".
5- Hechizo Sanación.

El otro planteamiento sería hacer que al elegir 1-Ataque Normal, se abra un submenú para escoger entre las dos armas distintas.
Esto podría ser un poco más laborioso, porque además el submenú sería distinto según si es caballero o mago ya que habría que indicar la descripción de las distintas armas.

Yo escogería el primer planteamiento.

Eso en cuanto al menú de opciones.


Sobre donde especificar ese "ataque alternativo" o como queramos llamarlo.
Pues también depende de cuáles son las "reglas" de ese ataque.

Si van a ser distintas según el personaje, entonces sí será mejor definirlo en las clases Caballero y Mago.

Por ejemplo, queremos que el ataque alternativo del Caballero sea un poco más potente que el ataque normal, pero menos que el "Relámpago", basta con añadir un nuevo método a Caballero
Citar
public class Caballero extends Personaje{

   public Caballero() {
      super();
   }

   public Caballero(String nombre, int ataque, int defensa, int vida) {
      super(nombre, ataque, defensa, vida);
   }
   
   public int ataqueRelampago() {
      /*
       * Nivel de ataque máximo, incrementado un 50%
       */
      System.out.println(nombre + " usa su ataque RELÁMPAGO");
      return (int)(ataque * 1.5);
   }
   
   public int ataqueAlternativo() {
      /*
       * Nivel de ataque máximo, incrementado un 25%
       */
      System.out.println(nombre + " usa la Espada Ancestral");
      return (int)(ataque * 1.25);
   }

   
   @Override
   public String toString() {
      return String.format("Caballero: %s / Nivel de Vida: %d", nombre, vida);
   }
   
}

Y luego en la clase Combate, donde habremos añadido una nueva opción al menu y un nuevo case al switch, pues bastará con llamar a ese método:
Citar
         //Evaluamos la acción escogida
         switch(accionJugador) {
         case 1: //Ataque normal
            ataqueJugador = jugador.atacar();
            System.out.println("Consigues un ATAQUE de " + ataqueJugador + " pts.");
            break;
         case 2: //Ataque alternativo, según clase
            if (jugador instanceof Caballero) {
               ataqueJugador = ((Caballero)jugador).ataqueAlternativo();
               System.out.println("Consigues un ATAQUE de " + ataqueJugador + " pts.");
            }
            else {
               //Ataque Mago alternativo aún no definido
            }
            break;
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kaos

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 3
    • Ver Perfil
Muchisimas gracias. Estoy haciendo un proyecto muy parecido y esto me esta ayudando mucho.
Me ha surgido una duda, y es que al hacer que el jugador ataque siempre antes del enemigo crea una ventaja a su favor. Se me ha ocurrido implementar una "tirada de dados" y que el que saque el mayor numero es quien realiza la acción y además esto implementarlo durante todo el enfrentamiento para añadirle un poco más de juego. Ya tengo el codigo de tirada de los dados, pero ¿como se implementaría en el enfrentamiento?
Adjunto el código de la clase que tengo para la tirada de dados.

Citar
public class Dado {

    public static void LanzamientoDados() {

        int dado1 = 0;
        int dado2 = 0;

        dado1 = (int)(Math.random()*6)+1;
        System.out.println("Dado del primer jugador: "+dado1);
        dado2 = (int)(Math.random()*6)+1;
        System.out.println("Dado del segundo jugador: "+dado2);

    }


}
« Última modificación: 22 de Diciembre 2022, 12:39 por Kaos »

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Hola.

En ese caso, lo ideal sería trasladar el código donde los personajes realizan sus acciones de combate, a distintos métodos, uno para el JUGADOR y otro para la CPU.

De esa forma, según los resultados de los dados, podemos decidir quién realizará primero sus acciones.

Para que todo funcione bien, al menos en el código que escribimos en este hilo, habría que trasladar también algunas variables que íbamos declarando a lo largo del main, para declararlas como atributos de clase.
Así serán visibles para los métodos que vamos a tener que crear.
Citar
public class Combate {
   
   private static Scanner teclado = new Scanner(System.in);
   private static Personaje jugador; //Podrá ser un Mago o un Caballero
   private static Caballero CPU; //La CPU siempre es un Caballero
   private static boolean modoDificil = false; //Nivel de dificultad
   private static int accionJugador = 0; //Recoge la acción que escoge el jugador en su menu
   private static int accionCPU = 0; //Recoge la acción que escoge CPU
   //Stats de jugador y CPU
   private static int ataqueJugador = 0, ataqueCPU = 0;
   private static int defensaJugador = 0, defensaCPU = 0;



Luego, creamos los métodos donde jugador y CPU elegirán sus acciones.
Es simplemente copiar y pegar lo que antes estaba en el main, dentro de estos métodos.

Método para JUGADOR:
Código: [Seleccionar]
private static void atacaJugador() {
//Recogemos acción del jugador
accionJugador = menuCombateJugador();
System.out.println(); //Salto de línea
//Evaluamos la acción escogida
switch(accionJugador) {
case 1: //Ataque normal
ataqueJugador = jugador.atacar();
System.out.println("Consigues un ATAQUE de " + ataqueJugador + " pts.");
break;
case 2: //Ataque alternativo, según clase
if (jugador instanceof Caballero) {
ataqueJugador = ((Caballero)jugador).ataqueAlternativo();
System.out.println("Consigues un ATAQUE de " + ataqueJugador + " pts.");
}
else {
//Ataque Mago alternativo aún no definido
}
break;
case 3: //Defender
defensaJugador = jugador.defender();
System.out.println("Consigues una DEFENSA de " + defensaJugador + " pts.");
break;
case 4: //Ataque relámpago o hechizo ataque, según clase
if (jugador instanceof Caballero) {
ataqueJugador = ((Caballero)jugador).ataqueRelampago();
System.out.println("Consigues un ATAQUE de " + ataqueJugador + " pts.");
}
else {
ataqueJugador = ((Mago)jugador).hechizoAtaque();
System.out.println("Consigues un ATAQUE de " + ataqueJugador + " pts.");
}
break;
case 5: //Hechizo sanación 50 puntos, solo sirve para Mago
if (jugador instanceof Caballero)
System.out.println("La acción no es válida. Pierdes tu turno");
else
((Mago)jugador).curar50puntos();
break;
default:
System.out.println("La acción no es válida. Pierdes tu turno");
}
pausa();
}

Método para CPU:
Código: [Seleccionar]
private static void atacaCPU() {
//A continuación elige acción la CPU
if (modoDificil)
accionCPU = CPUmodoDificil(ataqueJugador, defensaJugador);
else
accionCPU = CPUmodoNormal();
//Analizamos accion de CPU
switch(accionCPU) {
case 1:
ataqueCPU = CPU.atacar();
break;
case 2:
defensaCPU = CPU.defender();
break;
case 3:
ataqueCPU = CPU.ataqueRelampago();
}
pausa();
}


Ahora, un tercer método para la tirada de dados.
Partiendo del código que has publicado, yo lo modificaría para hacer que retorne un int.
Si la tirada la ha ganado JUGADOR, que retorne valor 1, por ejemplo.
Si la ha ganado CPU, pues que retorne valor 2.

Además le añadiría código para que la tirada se repita en caso de empate, y para que muestre el nombre de los jugadores:
Código: [Seleccionar]
private static int tirarDado() {
int dado1 = 0;
        int dado2 = 0;

        while (dado1 == dado2) {
        dado1 = (int)(Math.random()*6)+1;
        System.out.println("Dado de " + jugador.getNombre() + ": " + dado1);
        dado2 = (int)(Math.random()*6)+1;
        System.out.println("Dado de " + CPU.getNombre() + ": " + dado2);
        if (dado1 == dado2) {
        System.out.println("Empate, se repetirá lanzamiento de dados");
        pausa();
        }
        }
       
        if (dado1 > dado2) {
        System.out.println("Primer turno es para " + jugador.getNombre());
        return 1;
        }
        else {
        System.out.println("Primer turno es para " + CPU.getNombre());
        return 2;
        }
       
}

Con esto, ahora en el main, en la parte donde hemos extraído el código donde JUGADOR y CPU elegían sus acciones, ahora colocaremos un if para analizar que valor nos retorna el método que tira los dados.
Si retorna 1, pues el primer turno ser para JUGADOR. De lo contrario, será para CPU:

Citar
      
      ............................
      ............................
      ............................
      //Comienza el combate...
      while(jugador.getVida() > 0 && CPU.getVida() > 0) {
         /*
          * Las siguientes variables recogerán los valores de ataques o defensas
          * de los combatientes, según la acción que escojan, en cada turno.
          */
         
         
         System.out.println("\n\n\t\tCOMBATIENDO...");
         System.out.println("> Jugador: " + jugador);
         System.out.println("> CPU: " + CPU);
         
         System.out.println("Se decidirá primer turno con una tirada de dados.");   
         pausa();

         
         if (tirarDado() == 1) {
            atacaJugador();
            atacaCPU();
         }
         else {
            atacaCPU();
            atacaJugador();
         }

            
         
         //Ambos Jugadores han actuado, evaluamos daños conseguidos
         int danoRecibeJugador = ataqueCPU - defensaJugador;
         int danoRecibeCPU = ataqueJugador - defensaCPU;
         //Qué ha pasaso con Jugador
         if (danoRecibeJugador > 0) {
      ............................
      ............................
      ............................

Así queda implementado este sistema para elegir turno al azar.

Es cierto que antes JUGADOR tenía ventaja por ser siempre el primero, pero era para compensar que CPU siempre es el doble de potente que JUGADOR.

Ahora JUGADOR, las va a pasar canutas... ;D


Un saludo.
« Última modificación: 22 de Diciembre 2022, 21:19 por Kabuto »
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

GameBoy

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 1
    • Ver Perfil
Hola buenas
¿En este juego como se podría implementar el uso del multijugador incluyendo la implementación de jugadores cpu?
Por ejemplo un máximo de 6 jugadores y si no se rellenan con usuarios, que se autocompleten con jugadores cpu. Luego, a la hora del combate como se podría hacer para que de forma aleatoria toque un jugador contra otro, o un jugador contra una cpu o una cpu contra otra cpu. Y que se vayan enfrentando 1vs1 hasta que solo quede un ganador.

Gracias

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Se puede hacer, claro.
Pero habría que añadir bastante código extra.

Así a bote pronto, lo que se me ocurre sería usar una matriz de 2xN, donde N comenzaría por ejemplo con valor 4 y a lo largo del programa iría menguando según se van eliminando contendientes.

Es decir, si empezamos con 2x4, ya tenemos a 8 contendientes en la matriz, ya sean humanos o CPU.
Citar
[HUM][CPU][CPU][HUM]
[CPU][HUM][CPU][CPU]
Y esto funcionaría como una eliminatoria, los cuatro contendientes de la fila 0 se enfrentan con los de la fila 1.

Al final de esto tendremos cuatro eliminados y cuatro ganadores. Pues con esos 4 ganadores habría que crear una nueva matriz de 2x2
Citar
[CPU][HUM]
[HUM][CPU]

De nuevo hacemos enfrentarse los de la fila 0 con la fila 1, quedando dos contendientes con los que crear una nueva matriz de 2x1
Citar
[HUM]
[HUM]

Y de aquí ya saldría el ganador definitivo.

En fin, hacer esto, no es cuestión de añadir 4 líneas de código.
Habría que añadir bastante más y modificar parte de lo que ya hay escrito.
El código actual está pensado para que se enfrente un humano vs CPU. Pero ahora puede ocurrir que se enfrenten humano vs humano, o CPU vs CPU.

Habría que rediseñar los métodos para las acciones de combate para que recibieran como argumentos los personajes que se van a enfrentar, analice quién es humano, quién es CPU y aplique distintas reglas de combate según cada caso.

Hará falta código para poder crear varios personajes, para ir reconstruyendo la matriz con distintos tamaños según se van eliminando personajes, para que haga un "sorteo" aleatorio para elegir quien se enfrenta a quién...
Y bueno, esto es lo que se me ocurre en un primer pensamiento, luego irían surgiendo imprevistos y tal...

Sería interesante hacerlo, pero en estas fechas, el tiempo libre escasea... :o
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kaos

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 3
    • Ver Perfil
Muchisimas gracias Kabuto, me ha ayudado muchisimo. Una ultima pregunta. ¿Como se podria hacer que el usuario del jugador pudiera volcar toda la batalla en un fichero? Es decir, lo que aparece en la terminal, que el usuario tenga la opción de meterlo en un fichero.
Muchas gracias por todo otra vez y felices fiestas :))

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".