miércoles, 20 de noviembre de 2013

Juego orientado a Sistemas Distribuidos (Ahorcado)

El juego de "El ahorcado" es un juego de lápiz y papel, en el que el objetivo es adivinar una palabra o frase.

En este ocasión hemos automatizado el juego. Al comenzar aparecerá un "muñequito" formado por caracteres ASCII, y una raya en lugar de cada letra de la palabra a adivinar.

Instrucciones de juego


Luego el jugador deberá intentar adivinar las letras que le parece que puede contener la palabra, y una por una  ir ingresando mediante el teclado, seguido de un enter cada letra, que crea el usuario sea la correcta. Si acierta, se escriben todas las letras coincidentes. Si la letra no está,  se elimina una parte del cuerpo del "muñequito".  La cantidad de errores o de fallas permitidas antes de completar el cuerpo son un máximo de seis. Se gana el juego si se completa la palabra, y se pierde si se elimina el cuerpo antes de terminar la palabra.

Clases Utilizadas


ClienteAhorcadoint.java  (Interfaz)



public interface ClienteAhorcadoint{

    public  void enviarMensaje();
public  String crearMensajeRespuesta();
public  int getEstadoJuego();
public  char getLetra();
public  int getNroIntentos();
public  String getPalabraEnProgreso();
public  void setEstadoJuego(int estadoJuego);
public  void setLetra(char letra);
public  void leerMensaje(String mensaje);
public  void imprimirMensajeEnPantalla();
public String getPalabraActualGuionBajo();
public  String mostrarEstado();
public  void imprimirEntrada();
public  void imprimirSalida();
}

Servidor.java 



import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Servidor {
//DECLARACIONES
private static final int INACTIVO = 0;
private static final int JUGANDO = 1;
private static final int GANO = 2;
private static final int PERDIO = 3;
private static final int SOLICITANDO_JUEGO_NUEVO = 4;
//ATRIBUTOS DEL SERVIDOR
private static final int nroPuerto = 10026;
private static boolean SocketDisponible = true;
private static int conexionesRealizadas = 0;
private static Socket con;
//ATRIBUTOS DEL JUEGO
private static int estadoJuego = INACTIVO;
private static char letra = '?';
private static String palabra = "?";
private static String palabraEnProgreso = "?";
private static int nroIntentos = 6;
//PALABRAS EN EL SERVIDOR
static private final String[] palabrasAhorcado = {"reingenieria", "cubeta","tunelizacion", "protocolo", "puertos", "conexion", "broadcasting", "direccion","internet", "router", "switch", "wifi", "estandar", "socket", "transporte","enlace", "capas", "arquitectura", "cliente", "servidor", "proxy", "firewall","redes", "LAN", "WAN", "MAN", "hub", "concentrador", "datagrama", "puente","fibra", "TCP", "UDP", "mascara", "gateway", "servidor", "DNS", "cliente","conmutacion", "circuito", "satelite", "coaxial", "microondas", "señal","ingrarrojos", "token", "anillo", "bus", "control", "flujo", "congestion","enrutamiento", "aplicacion", "correo", "peertopeer", "reingenieria", "cubeta","tunelizacion", "protocolo", "puertos", "conexion", "broadcasting", "direccion","internet", "router", "switch", "wifi", "estandar", "socket", "transporte","enlace", "capas", "arquitectura", "cliente", "servidor", "proxy", "firewall","redes", "LAN", "WAN", "MAN", "hub", "concentrador", "datagrama", "puente","fibra", "TCP", "UDP", "mascara", "gateway", "servidor", "DNS", "cliente","conmutacion", "circuito", "satelite", "coaxial", "microondas", "señal","ingrarrojos", "token", "anillo", "bus", "control", "flujo", "congestion","enrutamiento", "aplicacion", "correo", "peertopeer"};
private static int nroMensaje = 0;
public static void main(String[] args) throws IOException {
   ServerSocket socketDeServicio = null;
try {
   socketDeServicio = new ServerSocket(nroPuerto);
BufferedReader entrada;
DataOutputStream salida;
while (true) {
  try {
      if (SocketDisponible) {
     //EL SOCKET ESTA DISPONIBLE, POR LO TANTO ACA NO SE ESTA EN JUEGO
 if (estadoJuego == INACTIVO) {
     System.out.println("\nesperando cliente...");
 con = socketDeServicio.accept();
 System.out.println("conexion aceptada...\n");
 salida = new DataOutputStream(con.getOutputStream());
 entrada = new BufferedReader(new InputStreamReader(con.getInputStream()));
 conexionesRealizadas++;
 System.out.println("SERVIDOR : conexion aceptada a cliente " +conexionesRealizadas);
 /*leer primer mensaje, peticion de inicio de juego desde el*cliente.*/
 leerMensaje(entrada.readLine());
 // imprimirEntrada();
 procesarMensaje();
 salida.writeBytes(responderMensaje());
 // imprimirSalida();
 }} else {
  entrada = new BufferedReader(new InputStreamReader(con.getInputStream()));
  salida = new DataOutputStream(con.getOutputStream());
  //EL SOCKET ESTA OCUPADO, POR LO TANTO ACA SE ESTA EN JUEGO
  if (estadoJuego == JUGANDO) {
  leerMensaje(entrada.readLine());
  // imprimirEntrada();
  procesarMensaje();
  salida.writeBytes(responderMensaje());
  // imprimirSalida();
  if (estadoJuego == GANO || estadoJuego == PERDIO) {
  estadoJuego = INACTIVO;SocketDisponible = true;
  System.out.println("JUEGO NRO " + conexionesRealizadas + "TERMINADO...");
  }}}
   } catch (java.net.SocketException e) {
   System.out.println("TERMINO ABRUPTO DE LA CONEXION CON EL CLIENTE.");
estadoJuego = INACTIVO;
SocketDisponible = true;
System.out.println("JUEGO NRO " + conexionesRealizadas + " TERMINADO...");}}
} catch (IOException BindException) {
   System.out.println("La maquina virtual de java ya esta ocupando el socket"+ "en ese puerto, intente iniciar el servicio con otro puerto");}}

private static void leerMensaje(String mensaje) {
            StringTokenizer stk = new StringTokenizer(mensaje, "#");
while (stk.hasMoreTokens()) {
   estadoJuego = Integer.valueOf(stk.nextToken());
nroIntentos = Integer.valueOf(stk.nextToken());
letra = stk.nextToken().toUpperCase().charAt(0);
palabraEnProgreso = stk.nextToken().toUpperCase();
nroMensaje = Integer.valueOf(stk.nextToken());}
nroMensaje++;}
private static void procesarMensaje() {
            if (estadoJuego == SOLICITANDO_JUEGO_NUEVO) {
   setSocketDisponible(false);
setEstadoJuego(JUGANDO);
setNroIntentos(6);
setLetra('?');
setPalabra(escojerPalabraJuegoNuevo());
setPalabraEnProgreso();
} else {
 if (estadoJuego == JUGANDO) {
     if (huboAcierto()) {
 reemplazarLetra();
 if (ganoJuego()) {estadoJuego = GANO;
 System.out.println("SERVIDOR : CLIENTE HA GANADO JUEGO");} 
         else {System.out.println("SERVIDOR : CLIENTE HA ACERTADO PALABRA");}} 
     else {
 nroIntentos--;
 System.out.println("SERVIDOR : SE LE HA DISMINUIDO UN INTENTO AL CLIENTE POR NOHABER ACERTADO");
 if (nroIntentos == 0) { 
  estadoJuego = PERDIO;
  System.out.println("SERVIDOR : CLIENTE HA PERDIDO JUEGO");}}} 
  else {
    try {
    System.out.println("SERVIDOR : cerrando conexion...");
con.shutdownOutput();
SocketDisponible = true;
System.out.println("SERVIDOR : conexion finalizada.");
} catch (IOException ex) {
 Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);}}}
}

private static String responderMensaje() {
            String a = estadoJuego + "#" + nroIntentos + "#" + letra + "#" + palabraEnProgreso + "#" +nroMensaje + "\n";
return a;}
public static void setSocketDisponible(boolean SocketDisponible) {
           Servidor.SocketDisponible = SocketDisponible;
}
public static void setConexionesRealizadas(int conexionesRealizadas) {
          Servidor.conexionesRealizadas = conexionesRealizadas;}
 
public static void setEstadoJuego(int estadoJuego) {
          Servidor.estadoJuego = estadoJuego;}
 
public static void setLetra(char letra) {
          Servidor.letra = letra;}
 
public static void setNroIntentos(int nroIntentos) {
          Servidor.nroIntentos = nroIntentos;}
 
public static void setPalabra(String palabra) {
          Servidor.palabra = palabra;}
 
public static void setPalabraEnProgreso(String palabraEnProgreso) {
           Servidor.palabraEnProgreso = palabraEnProgreso;}
  
private static String escojerPalabraJuegoNuevo() {
          return palabrasAhorcado[(int) (Math.random() * palabrasAhorcado.length)];}
 
private static void setPalabraEnProgreso() {
          String p = "";
 for (int i = 0; i < palabra.length(); i++) {
     p += "_";}
 palabraEnProgreso = p;}
 
private static boolean huboAcierto() {
         boolean tuvoAcierto = true;
//PRIMERO DEBEMOS COMPROBAR QUE LA LETRA NO SE PREPITA CON LO QUE//YA TENEMOS COMPLETADO ACTUALMENTE
tuvoAcierto = !seRepite(letra, palabraEnProgreso) && esParteDeLaPalabra(letra, palabra);
return tuvoAcierto;}
 
private static boolean seRepite(char l, String enProgreso) {
         boolean repite = false;
char[] prog = enProgreso.toCharArray();
for (int i = 0; i < prog.length; i++) {
    if (l == prog[i]) {repite = true;}}
    return repite;}
 
private static boolean esParteDeLaPalabra(char letra, String palabra) {
         boolean esParte = false;
char[] pa = palabra.toUpperCase().toCharArray();
for (int i = 0; i < pa.length; i++) {
    if (letra == pa[i]) {esParte = true;}}
return esParte;}
private static void reemplazarLetra() {
         String[] enProg = palabraEnProgreso.split("");
String[] pal = palabra.split("");
String reemplazada = "";
for (int i = 0; i < pal.length; i++) {
    if (String.valueOf(letra).equalsIgnoreCase(pal[i])) {
    enProg[i] = String.valueOf(letra);}
    reemplazada += enProg[i];}
palabraEnProgreso = reemplazada;}
 
private static boolean ganoJuego() {
         if (palabraEnProgreso.equalsIgnoreCase(palabra)) {
return true;} 
else {return false;}}
 
private static String mostrarEstado() {
    if (estadoJuego == 0) {return "INACTIVO";} 
else {if (estadoJuego == 1) {
  return "JUGANDO";} 
else {if (estadoJuego == 2) {
   return "GANO";} 
    else {if (estadoJuego == 3) {
   return "PERDIO";} 
else {if (estadoJuego == 4) {
   return "SOLICITANDO_JUEGO_NUEVO";} 
else {
   return "JUEGO_TERMINADO";}}}}}}
private static void imprimirEntrada() {
    String a = estadoJuego + "#" + nroIntentos + "#" + letra + "#" + palabraEnProgreso + "#" +nroMensaje;
System.out.println("\nLEIDO POR SERVIDOR: " + a + "\n" + mostrarEstado());}
private static void imprimirSalida() {
    String a = estadoJuego + "#" + nroIntentos + "#" + letra + "#" + palabraEnProgreso + "#" +nroMensaje;
System.out.println("\nENVIADO POR SERVIDOR: " + a + "\n" + mostrarEstado());}
}

Cliente.java


import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.StringTokenizer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.JOptionPane;

public class Cliente extends JFrame implements ClienteAhorcadoint{

private static final int Juego_inactivo = 0;
private static final int Juego_Activo = 1;
private static final int GANO = 2;
private static final int PERDIO = 3;
private static final int Solicitud_con = 4;
private static final int Juego_fin = 5;
//ATRIBUTOS DE LA CONEXION
private static final int puerto = 10028;
private static BufferedReader in = null;
private static DataOutputStream out = null;
private static Socket conexion;
public static Cliente aux;
//ATRIBUTOS DEL JUEGO
private static String letra_enviar="";
private static int estadoJuego = Juego_inactivo;
private static int intentosRestantes = 6;
private static char letra = '*';
private static String palabraEnProgreso = "*";
private static Integer nroMensaje = 0;

public static  ImageIcon image0 = new ImageIcon("Intento_0.jpg");
public static  JLabel label_intento0 = new JLabel("", image0, JLabel.CENTER);
public static  ImageIcon image1 = new ImageIcon("Intento_1.jpg");
public static  JLabel label_intento1 = new JLabel("", image1, JLabel.CENTER);
public static  ImageIcon image2 = new ImageIcon("Intento_2.jpg");
public static  JLabel label_intento2 = new JLabel("", image2, JLabel.CENTER);
public static  ImageIcon image3 = new ImageIcon("Intento_3.jpg");
public static  JLabel label_intento3 = new JLabel("", image3, JLabel.CENTER);
public static  ImageIcon image4 = new ImageIcon("Intento_4.jpg");
public static  JLabel label_intento4 = new JLabel("", image4, JLabel.CENTER);
public static  ImageIcon image5 = new ImageIcon("Intento_5.jpg");
public static  JLabel label_intento5 = new JLabel("", image5, JLabel.CENTER);
public static  ImageIcon image6 = new ImageIcon("Intento_6.jpg");
public static  JLabel label_intento6 = new JLabel("", image6, JLabel.CENTER);

public static JLabel Ingrese;
public static JTextField txt_letra;
public static JButton enviar;

public Cliente() {

setTitle("Juego Ahorcado");
setSize(394, 280);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout dis = new FlowLayout();
setLayout(dis);

add(label_intento0);
add(label_intento1);
add(label_intento2);
add(label_intento3);
add(label_intento4);
add(label_intento5);
add(label_intento6);

Ingrese=new JLabel ("Ingrese letra: "); //label de Ingrese letra
Ingrese.setBounds(15,330,150,27);
//add(Ingrese);

txt_letra=new JTextField(""); //cuadro donde se ingresa la letra
txt_letra.setColumns(10);
txt_letra.setBackground(new java.awt.Color(251,248,248));
//add(txt_letra);

enviar=new JButton ("Enviar"); // Enviar
enviar.setBounds(360,330,140,25);
enviar.setToolTipText("Enviar letra");
//add(enviar);

label_intento0.setVisible(false);
label_intento1.setVisible(false);
label_intento2.setVisible(false);
label_intento3.setVisible(false);
label_intento4.setVisible(false);
label_intento5.setVisible(true);
label_intento6.setVisible(false);


 setVisible(true);
 enviar.addActionListener(oyente);
}

public static void main(String[] args) {
     
try {

conexion = new Socket("192.168.0.48", 10028);
BufferedReader entradaUsuario = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Iniciando Conexion con el servidor...");
in = new BufferedReader(new InputStreamReader(conexion.getInputStream()));
out = new DataOutputStream(conexion.getOutputStream());
System.out.println("Conexion Exitosa...");
aux = new Cliente();
boolean jugando = true;
Cliente app = new Cliente();
while (jugando == true) {
if (estadoJuego == Juego_inactivo) {
aux.setEstadoJuego(Solicitud_con);
aux.enviarMensaje();
// imprimirSalida();
} else {
  //LEER MENSAJE DESDE SERVIDOR
  aux.leerMensaje(in.readLine());
  // imprimirEntrada();
if (estadoJuego == Juego_Activo) {
//IMPRIMIR MENSAJE EN PANTALLA Y LEER UNA LETRA DEL CLIENTE
aux.imprimirMensajeEnPantalla();
System.out.println("Por favor ingrese una letra: ");
//SETEAR LA LETRA LEIDA POR EL CLIENTE

aux.setLetra(entradaUsuario.readLine().charAt(0));
aux.enviarMensaje();
} else {
 if (estadoJuego == GANO) {
aux.setEstadoJuego(Juego_fin);
aux.imprimirMensajeEnPantalla();
jugando = false;
System.out.println("¡¡¡Congratulations!!!");
System.out.println("Has ganado el juego :)");
 }
 if (estadoJuego == PERDIO) {
 aux.setEstadoJuego(Juego_fin);
 aux.imprimirMensajeEnPantalla();
 jugando = false;
 System.out.println("No quedan mas intentos");
 System.out.println("Has perdido");
 }
System.out.println("programa terminado...");
}
}
}
}catch (IOException ex) {
  System.out.println("ERROR DE ENRADA/SALIDA");
  System.out.println("No fue posible realizar la conexion, posiblemente el servidor esteinactivo.");
  }
    }

ActionListener oyente=new ActionListener(){
        public void actionPerformed(ActionEvent evento){

             if (evento.getSource() == enviar)
            {
                aux.setLetra(txt_letra.getText().charAt(0));
            }
}
};

public  void enviarMensaje() {
 
  try {
     if (estadoJuego == Solicitud_con) {
    out.writeBytes(aux.crearMensajeRespuesta());
} else {
out.writeBytes(aux.crearMensajeRespuesta());
}
}catch (IOException iOException) {
   System.out.println("ERROR AL ENVIAR EL MENSAJE");
}}

public  String crearMensajeRespuesta() {
    return estadoJuego + "#" + intentosRestantes + "#" + letra + "#" + palabraEnProgreso + "#" +nroMensaje + "\n";
}

public  int getEstadoJuego() {
    return estadoJuego;}

public  char getLetra() {
    return letra;
}

public  int getNroIntentos() {
    return intentosRestantes;
}

public  String getPalabraEnProgreso() {
    return palabraEnProgreso;
}

public  void setEstadoJuego(int estadoJuego) {
    Cliente.estadoJuego = estadoJuego;
}

public  void setLetra(char letra) {
    Cliente.letra = letra;
}

public  void leerMensaje(String mensaje) {
    StringTokenizer stk = new StringTokenizer(mensaje, "#");
while (stk.hasMoreTokens()) {
    estadoJuego = Integer.valueOf(stk.nextToken());
intentosRestantes = Integer.valueOf(stk.nextToken());
letra = stk.nextToken().charAt(0);
palabraEnProgreso = stk.nextToken();
nroMensaje = Integer.valueOf(stk.nextToken());
}}

public  void imprimirMensajeEnPantalla() {
   
    //IMPRIMIENDO MENSAJE EN PANTALLA
System.out.println("¨¨¨¨¨¨¨¨ JUEGO EL AHORCADO ************");
imprimirAhorcado(intentosRestantes);
System.out.println("\nPALABRA ACTUAL: " + aux.getPalabraActualGuionBajo());
System.out.println("INTENTOS RESTANTES: " + intentosRestantes);}

public  String getPalabraActualGuionBajo() {
    String[] a = palabraEnProgreso.split("");
String impr = "";
for (int i = 0; i < a.length; i++) {
   impr += a[i] + " ";}
return impr;}

public  String mostrarEstado() {
    if (estadoJuego == 0) {
   return "Juego_inactivo";}
    else {
   if (estadoJuego == 1) {
return "Juego_Activo";}
else {
   if (estadoJuego == 2) {
return "GANO";}
else {
   if (estadoJuego == 3) {
return "PERDIO";}
else {
   if (estadoJuego == 4) {
return "Solicitud_con";}
else {
   return "Juego_fin";}}}}}}

public  void imprimirEntrada() {
   
    String a = estadoJuego + "#" + intentosRestantes + "#" + letra + "#" + palabraEnProgreso +"#" + nroMensaje;
System.out.println("LEIDO POR CLIENTE: " + a + "\n" + aux.mostrarEstado());}

public  void imprimirSalida() {
   
    String a = estadoJuego + "#" + intentosRestantes + "#" + letra + "#" + palabraEnProgreso +"#" + nroMensaje;
System.out.println("ENVIADO POR CLIENTE: " + a + "\n" + aux.mostrarEstado());}

public  void imprimirAhorcado(int intentosRestantes) {
if (intentosRestantes < 1) {
   label_intento0.setVisible(false);
label_intento1.setVisible(false);
label_intento2.setVisible(false);
label_intento3.setVisible(false);
label_intento4.setVisible(false);
label_intento5.setVisible(false);
label_intento6.setVisible(true);
}
else {
   if (intentosRestantes < 2) {
   label_intento0.setVisible(false);
label_intento1.setVisible(false);
label_intento2.setVisible(false);
label_intento3.setVisible(false);
label_intento4.setVisible(false);
label_intento5.setVisible(true);
label_intento6.setVisible(false);
}
else {
    if (intentosRestantes < 3) {
label_intento0.setVisible(false);
label_intento1.setVisible(false);
label_intento2.setVisible(false);
label_intento3.setVisible(false);
label_intento4.setVisible(true);
label_intento5.setVisible(false);
label_intento6.setVisible(false);
}
else {
    if (intentosRestantes < 4) {
label_intento0.setVisible(false);
label_intento1.setVisible(false);
label_intento2.setVisible(false);
label_intento3.setVisible(true);
label_intento4.setVisible(false);
label_intento5.setVisible(false);
label_intento6.setVisible(false);
}
else {
    if (intentosRestantes < 5) {
label_intento0.setVisible(false);
label_intento1.setVisible(false);
label_intento2.setVisible(true);
label_intento3.setVisible(false);
label_intento4.setVisible(false);
label_intento5.setVisible(false);
label_intento6.setVisible(false);
label_intento5.setVisible(false);
}
else {
    if (intentosRestantes < 6) {
label_intento0.setVisible(false);
label_intento1.setVisible(true);
label_intento2.setVisible(false);
label_intento3.setVisible(false);
label_intento4.setVisible(false);
label_intento5.setVisible(false);
label_intento6.setVisible(false);
}
else {
    if (intentosRestantes < 7) {
label_intento0.setVisible(true);
label_intento1.setVisible(false);
label_intento2.setVisible(false);
label_intento3.setVisible(false);
label_intento4.setVisible(false);
label_intento5.setVisible(false);
label_intento6.setVisible(false);

}}}}}}}
}
}

Conclusión:


Los sockets son basicamente formas en las que podemos interconectar 2 (o mas) programas mediante el uso de la internet. En java se utilizan para poder crear conexiones utilizando basicamente una IP/hostname y un puerto para establecer la conexión, en base a esto,  podemos realizar un sin fin de aplicaciones, que van desde sencillos juegos, ventanas de chat, hasta complejas actividades como administrar varias computadoras a la vez.

El modelo mas basico de los sockets consta de 2 simples programas, un servidor y un cliente. Basicamente el programa servidor comienza a “escuchar” en un puerto determinado(nosotros lo especificamos), y posteriormente el programa que la hace de “cliente” debe conocer la ip o nombre de dominio/hostname del servidor y el puerto que esta escuchando, al saber esto simplemente solicita establecer una conexión con el servidor. Es aqui cuando el servidor acepta esa conexión y se puede decir que estos programas estan “conectados”, de este modo pueden intercambiar información. 

3 comentarios: