CLIENTE
CLASE PRINCIPAL
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package socketcliente_multiples;
/**
*
* @author glop
*/
public class Socketcliente_multiples {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
clientes cliente = new clientes(); // Instancia que representa un cliente
cliente.start(); // Se inicia el hilo del cliente. Ya se encargará el servidor de asignarle un id
}
}
CLASE HILO CLIENTES
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package socketcliente_multiples;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.Socket;
/**
*
* @author glop
*/
public class clientes extends Thread {
public clientes() {
}
@Override
public void run() {
BufferedReader lector = new BufferedReader(new InputStreamReader(System.in)); // Buffer que lee lo escrito por cliente
try {
Socket socket = new Socket("localhost",2000); // Se crea el socket del cliente con la conexión local y el puerto 2000
System.out.println("Conectado");
// Buffers de entrada y salida de datos. Necesarios para la comunicaciones entre el cliente y el servidor
DataOutputStream salida = new DataOutputStream (socket.getOutputStream());
DataInputStream entrada = new DataInputStream (socket.getInputStream());
int numeroCliente=-1; // Variable que almacena el número introducido por el cliente. Al iniciarse el juego es -1
int correcto = -1; // Variable que indica si se ha acertado el número. Al iniciarse es -1
int intentos=0; // Variable que contabiliza los intentos
System.out.println("Intenta averiguar el número secreto"); // Presentación del juego
while(correcto!=1) { // Sigo pidiento datos al cliente hasta que el servidor envíe el 1 que es la clave
// de que ha acertado
numeroCliente=-1; // Se resetea el valor del número del cliente
while(numeroCliente==-1) { // Comprueba que es un número válido
try {
System.out.println("¿Número?"); // Pido el número
numeroCliente = Integer.parseInt(lector.readLine()); // Lo guardo en una variable numérica
} catch (Exception ex) { // Si no es un número válido me lanza un error y vuelve a pedirlo
System.out.println("No es un número válido");
}
}
salida.writeInt(numeroCliente); // Envío lo que recibo por teclado
correcto=entrada.readInt(); // Recibo la respuesta del servidor
if (correcto==0) { // Si recibo un 0 es que el número es menor
System.out.println("El número secreto es menor a " + numeroCliente);
} else if (correcto==2) { // Si recibo un 2 es que el número es mayor
System.out.println("El número secreto es mayor a " + numeroCliente);
}
intentos++; // Se contabiliza un nuevo intento
}
// Como ya he salido del while, he ganado y lo comunico al cliente
System.out.println("Efectivamente, el número secreto es " + numeroCliente);
System.out.println("¡¡EL JUEGO HA TERMINADO LO HAS CONSEGUIDO EN " + intentos + " INTENTOS!!");
System.out.println("Desconectando conexión ...");
// Se cierra el socket y los flujos
entrada.close();
salida.close();
socket.close();
} catch (Exception ex) { // Si ocurriera alguna excepción, la capturo e informo
System.out.println("Ocurrio un error en la comunicación con el servidor");
}
}
}
SERVIDOR
CLASE PRINCIPAL
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package socketservidor_multiples;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
/**
*
* @author glop
*/
public class servidor extends Thread {
private Socket cliente;
private int id;
DataOutputStream salida;
DataInputStream entrada;
public servidor(Socket sock, int idd) {
this.cliente = sock;
this.id = idd;
try {
// Buffers de entrada y salida de datos. Necesarios para la comunicaciones entre el cliente y el servidor
salida = new DataOutputStream (cliente.getOutputStream());
entrada = new DataInputStream (cliente.getInputStream());
} catch (Exception ex) {
}
}
@Override
public void run() {
System.out.println("El cliente " + id + " está jugando");
Random aleatorio = new Random(); // Generador de números aleatorios
int n = aleatorio.nextInt(100); // Variable que almacena un número de 0 a 100
int numeroCliente = -1; // Variable que almacena el número que me manda el cliente
try {
// Hasta que el número que me envíe el cliente no sea el número secreto, sigo comparándolos
// y no dejo que la comunicación acabe
while (n!=numeroCliente) {
numeroCliente = entrada.readInt(); // Recibo el número de la parte del cliente
if (numeroCliente>n) {
salida.writeInt(0); // Le indico que es menor mediante el envío de un 0
}
if (numeroCliente<n) {
salida.writeInt(2); // Le indico que es mayor mediante el envío de un 2
}
}
salida.writeInt(1); // Le indico que el número es correcto mediante el envío de un 1
// Como ya he salido del while, he ganado, se lo indico mandando un 1 que es la clave.
System.out.println("¡¡EL CLIENTE " + id + " HA ACERTADO!!");
System.out.println("Desconectando conexión con el cliente " + id + " ...");
cliente.close(); // Cierro cliente
} catch (Exception ex) { // Si ocurriera algún error, lo capturo e informo
System.out.println("Ocurrio un error en la comunicación con el cliente " + id);
}
}
}
CLASE HILO SERVIDOR
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package socketservidor_multiples;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
/**
*
* @author glop
*/
public class servidor extends Thread {
private Socket cliente;
private int id;
DataOutputStream salida;
DataInputStream entrada;
public servidor(Socket sock, int idd) {
this.cliente = sock;
this.id = idd;
try {
// Buffers de entrada y salida de datos. Necesarios para la comunicaciones entre el cliente y el servidor
salida = new DataOutputStream (cliente.getOutputStream());
entrada = new DataInputStream (cliente.getInputStream());
} catch (Exception ex) {
}
}
@Override
public void run() {
System.out.println("El cliente " + id + " está jugando");
Random aleatorio = new Random(); // Generador de números aleatorios
int n = aleatorio.nextInt(100); // Variable que almacena un número de 0 a 100
int numeroCliente = -1; // Variable que almacena el número que me manda el cliente
try {
// Hasta que el número que me envíe el cliente no sea el número secreto, sigo comparándolos
// y no dejo que la comunicación acabe
while (n!=numeroCliente) {
numeroCliente = entrada.readInt(); // Recibo el número de la parte del cliente
if (numeroCliente>n) {
salida.writeInt(0); // Le indico que es menor mediante el envío de un 0
}
if (numeroCliente<n) {
salida.writeInt(2); // Le indico que es mayor mediante el envío de un 2
}
}
salida.writeInt(1); // Le indico que el número es correcto mediante el envío de un 1
// Como ya he salido del while, he ganado, se lo indico mandando un 1 que es la clave.
System.out.println("¡¡EL CLIENTE " + id + " HA ACERTADO!!");
System.out.println("Desconectando conexión con el cliente " + id + " ...");
cliente.close(); // Cierro cliente
} catch (Exception ex) { // Si ocurriera algún error, lo capturo e informo
System.out.println("Ocurrio un error en la comunicación con el cliente " + id);
}
}
}
Tiro con arco
CLASE PRINCIPAL
package PaquetePrincipal;
import java.util.concurrent.Semaphore;
/******************************************************************************
* Clase donde reside el método main() que inicia la aplicación
*
* @author IFU
*/
public class Main {
/**************************************************************************
* Define los parámetros necesarios para construir hilos tiradores (ver el
* constructor de la clase Tirador). Se crean los 5 tiradores, y los inicia.
*
* @param args the command line arguments
*/
public static void main(String[] args) {
//número de tiradores. Cada tirador se identifica por un índice del 0 al 4
//número de arcos de las que disponen los tiradores para disparar
int tiradores = 5;
int arcos = 2;
//Aqui ira el código para declarar un semaforo con los permisos correspondientes
//a los arcos de los que se disponen.
Semaphore arco = new Semaphore(arcos,true);
//Aqui ira el codigo para iniciar los hilos de los cinco tiradores.
//Se debe tener en cuenta la forma del constructor tirador.
for (int c=0;c<tiradores;c++) {
Tirador tirador = new Tirador(c,arco);
tirador.start();
}
}
}
CLASE HILO TIRADORES
package PaquetePrincipal;
import java.util.concurrent.Semaphore;
/*****************************************************************************
* Hilo tirador. Su método run() realiza un bucle infinito que consite en
* invocar a los métodos cogerArco, disparar, soltarArco...
*
* @author IFU
*/
public class Tirador extends Thread{
//indice del Tirador actual
private int miIndice;
//referencia al semáforo externo
private Semaphore semaforoArco;
/****************************************************************************
* constructor de dos parámetros, cada uno de los cuales se guardará en una
* variable local para usarla cuando sea neceario
*
* @param miIndice índice que identifica al tirador (un entero del 0 al 4)
* @param semaforoArco semáforo con número de permisos igual al de arcos
*/
public Tirador(int miIndice, Semaphore semaforoArco){
this.miIndice= miIndice;
this.semaforoArco = semaforoArco;
}
/**************************************************************************
* bucle infinito: llamada al método cogerArco(),
* llamada al método disparar(),
* llamada al método soltarArco()
*/
@Override
public void run() {
//Aqui ira el codigo para que el hilo este en un bucle infinito en el que
//el tirador coge el arco, dispara y suelta el arco.
while(true) {
cogerArco();
disparar();
soltarArco();
}
}
/****************************************************************************
* método cogerArco(): mostrará un mensaje en la Salida de que el
* 'Tirador ' N ' quiere disparar', mientras trata de conseguir un
* Arco para disparar. Una vez conseguida,
* mostrará un mensaje de que el 'Tirador ' N ' coge un arco'.
*/
public void cogerArco() {
System.out.println("Tirador " + (miIndice+1) + " quiere disparar");
//Aqui ira el codigo para que el hilo intente adquirir el recurso compartido
//que en esta caso es un arco
try {
semaforoArco.acquire(1);
} catch (InterruptedException iex) {
System.out.println("Ocurrió un error cuando el tirador " + (miIndice + 1) + " intentaba coger el arco");
}
System.out.println("Tirador " + (miIndice+1) + " coge un arco");
}
/****************************************************************************
* método disparar(): mostrará un mensaje en la Salida de que el
* 'Tirador ' N ' disparando'
* Para simular esta actividad, dormirá el hilo un tiempo aleatorio.
*/
public void disparar(){
//Aqui ira el codigo para mostrar un mensaje indicando
//que el tirador número .... está disparando
//Aqui ira el codigo para dormir el hilo un tiempo aleatorio para simular
System.out.println("Tirador " + (miIndice+1) + " está disparando");
try {
sleep(5000);
} catch (InterruptedException iex) {
System.out.println("Ocurrió un error cuando el tirador " + (miIndice+1) + " estaba disparando");
}
}
/****************************************************************************
* método soltarArco(): mostrará un mensaje en la Salida de que el
* 'Tirador ' N ' ha disparado y Suelta el Arco' y liberá la Arco.
*/
public void soltarArco(){
//termina de disparar
System.out.println("Tirador " + (miIndice+1) + " ha disparado. Suelta un arco.");
//Aqui ira el codigo para liberar el recurso compartido, es decir el arco
semaforoArco.release(1);
}
}
package PaquetePrincipal;
import java.util.concurrent.Semaphore;
/******************************************************************************
* Clase donde reside el método main() que inicia la aplicación
*
* @author IFU
*/
public class Main {
/**************************************************************************
* Define los parámetros necesarios para construir hilos tiradores (ver el
* constructor de la clase Tirador). Se crean los 5 tiradores, y los inicia.
*
* @param args the command line arguments
*/
public static void main(String[] args) {
//número de tiradores. Cada tirador se identifica por un índice del 0 al 4
//número de arcos de las que disponen los tiradores para disparar
int tiradores = 5;
int arcos = 2;
//Aqui ira el código para declarar un semaforo con los permisos correspondientes
//a los arcos de los que se disponen.
Semaphore arco = new Semaphore(arcos,true);
//Aqui ira el codigo para iniciar los hilos de los cinco tiradores.
//Se debe tener en cuenta la forma del constructor tirador.
for (int c=0;c<tiradores;c++) {
Tirador tirador = new Tirador(c,arco);
tirador.start();
}
}
}
CLASE HILO TIRADORES
package PaquetePrincipal;
import java.util.concurrent.Semaphore;
/*****************************************************************************
* Hilo tirador. Su método run() realiza un bucle infinito que consite en
* invocar a los métodos cogerArco, disparar, soltarArco...
*
* @author IFU
*/
public class Tirador extends Thread{
//indice del Tirador actual
private int miIndice;
//referencia al semáforo externo
private Semaphore semaforoArco;
/****************************************************************************
* constructor de dos parámetros, cada uno de los cuales se guardará en una
* variable local para usarla cuando sea neceario
*
* @param miIndice índice que identifica al tirador (un entero del 0 al 4)
* @param semaforoArco semáforo con número de permisos igual al de arcos
*/
public Tirador(int miIndice, Semaphore semaforoArco){
this.miIndice= miIndice;
this.semaforoArco = semaforoArco;
}
/**************************************************************************
* bucle infinito: llamada al método cogerArco(),
* llamada al método disparar(),
* llamada al método soltarArco()
*/
@Override
public void run() {
//Aqui ira el codigo para que el hilo este en un bucle infinito en el que
//el tirador coge el arco, dispara y suelta el arco.
while(true) {
cogerArco();
disparar();
soltarArco();
}
}
/****************************************************************************
* método cogerArco(): mostrará un mensaje en la Salida de que el
* 'Tirador ' N ' quiere disparar', mientras trata de conseguir un
* Arco para disparar. Una vez conseguida,
* mostrará un mensaje de que el 'Tirador ' N ' coge un arco'.
*/
public void cogerArco() {
System.out.println("Tirador " + (miIndice+1) + " quiere disparar");
//Aqui ira el codigo para que el hilo intente adquirir el recurso compartido
//que en esta caso es un arco
try {
semaforoArco.acquire(1);
} catch (InterruptedException iex) {
System.out.println("Ocurrió un error cuando el tirador " + (miIndice + 1) + " intentaba coger el arco");
}
System.out.println("Tirador " + (miIndice+1) + " coge un arco");
}
/****************************************************************************
* método disparar(): mostrará un mensaje en la Salida de que el
* 'Tirador ' N ' disparando'
* Para simular esta actividad, dormirá el hilo un tiempo aleatorio.
*/
public void disparar(){
//Aqui ira el codigo para mostrar un mensaje indicando
//que el tirador número .... está disparando
//Aqui ira el codigo para dormir el hilo un tiempo aleatorio para simular
System.out.println("Tirador " + (miIndice+1) + " está disparando");
try {
sleep(5000);
} catch (InterruptedException iex) {
System.out.println("Ocurrió un error cuando el tirador " + (miIndice+1) + " estaba disparando");
}
}
/****************************************************************************
* método soltarArco(): mostrará un mensaje en la Salida de que el
* 'Tirador ' N ' ha disparado y Suelta el Arco' y liberá la Arco.
*/
public void soltarArco(){
//termina de disparar
System.out.println("Tirador " + (miIndice+1) + " ha disparado. Suelta un arco.");
//Aqui ira el codigo para liberar el recurso compartido, es decir el arco
semaforoArco.release(1);
}
}
Cena de los filósofos
CLASE PRINCIPAL
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package cena_filosofos;
import java.util.concurrent.Semaphore;
/**
*
* @author glop
*/
public class Cena_filosofos {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Semaphore[] palillos = new Semaphore[5]; // Se crea el array de semáforos.
// Mediante un bucle for, se recorre el array de semáforos y se le da a cada uno un permiso único de uso.
for (int c = 0; c < 5; c++) {
palillos[c] = new Semaphore(1,true);
}
// Se instancian los cinco filósofos aportando los datos: posiciones de los dos palillos, nombre, y los dos palillos
// que le pertenecen y actúan como semáforos de uso compartido y excluyente
filosofo f1 = new filosofo(5,1, "Filósofo 1",palillos[4],palillos[0]);
filosofo f2 = new filosofo(1,2, "Filósofo 2",palillos[0],palillos[1]);
filosofo f3 = new filosofo(2,3, "Filósofo 3",palillos[1],palillos[2]);
filosofo f4 = new filosofo(3,4, "Filósofo 4",palillos[2],palillos[3]);
filosofo f5 = new filosofo(4,5, "Filósofo 5",palillos[3],palillos[4]);
// Se inician los cinco hilos.
f1.start();
f2.start();
f3.start();
f4.start();
f5.start();
}
}
CLASE HILO FILÓSOFO
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package cena_filosofos;
// Importo las clases necesarias para trabajar
import java.util.Random;
import java.util.concurrent.Semaphore;
/**
*
* @author glop
*/
public class filosofo extends Thread{
private static final Random aleatorio = new Random(); // Generador de números aleatorios
private Semaphore palilloder; // Semáforo que representa el palillo derecho
private Semaphore palilloizq; // Semñaforo que representa en palillo izquierdo
int posder=-1; // Toma la posición del palillo correspondiente para informar al usuario
int posizq=-1; // Toma la posición del palillo correspondiente para informar al usuario
String nombre; // Nombre del filósofo
// Construye el filósofo con los datos proporcionados. Éstos son; la posición de los dos palillos que le pertencen.
// el nombre del filósofo y los dos palillos que utilizará que son semáforos de uso compartido y excluyente
public filosofo(int posd,int posiz,String nomb,Semaphore palder,Semaphore palizq) {
this.posder = posd;
this.posizq = posiz;
this.nombre = nomb;
this.palilloder = palder;
this.palilloizq = palizq;
}
// Método que representa al filósofo pensando
private void pensar() {
try {
System.out.println(this.nombre + " está pensando");
sleep(aleatorio.nextInt(5000)) ; // El tiempo que transcurre pensando se calcula aleatoriamente hasta 5 segundos
} catch(InterruptedException ex) {
}
}
// Método que representa al filósofo comiendo
private void comer() {
try { // Intenta tomar los palillos
palilloder.acquire(); // Toma el palillo derecho, si este palillo estuviera en uso se entraría en una disputa,
// el hilo se interrumpiría,
// y el proceso iría al finally donde lo suelta
if (!palilloizq.tryAcquire()) { // Si el palillo izquierdo esta siendo usado el filósofo espera.
System.out.println(this.nombre + " está hambriento"); // Se lanza un mensaje por pantalla indicando
// que el filósofo está hambriento
return; // Irá inmediatamente al finally donde soltará el palillo derecho que es quien primero tomó
}
// Si ha llegado hasta aquí es que el palillo izquierdo también ha sido tomado con éxito. ¡Ya puede empezar!
// Se lanza el mensaje por pantalla de que el filósofo ha empezado a comer.
// También se indica, a efectos informativos, los palillos que utiliza
System.out.println(this.nombre + " está comiendo con los palillos : " + this.posder + " y " + this.posizq);
sleep(aleatorio.nextInt(5000)); // Se calcula la demora en comer aleatoriamente hasta 5 segundos
// Se lanza el mensaje por pantalla de que el filósofo ha terminado de comer.
// También se indica, a efectos informativos, los palillos que ha utilizado y ahora libera
System.out.println(this.nombre + " ha terminado de comer y libera los palillos : "+ this.posder + " y " + this.posizq);
palilloizq.release(); // Como ya ha terminado de comer, suelta el palillo izquierdo.
} catch (InterruptedException ex) {
} finally {
// En cualquier caso, soltará el palillo derecho.
palilloder.release();
}
}
@Override
public void run() {
while(true) { // En un bucle infinito, piensa y come, piensa y come ...
pensar();
comer();
}
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package cena_filosofos;
import java.util.concurrent.Semaphore;
/**
*
* @author glop
*/
public class Cena_filosofos {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Semaphore[] palillos = new Semaphore[5]; // Se crea el array de semáforos.
// Mediante un bucle for, se recorre el array de semáforos y se le da a cada uno un permiso único de uso.
for (int c = 0; c < 5; c++) {
palillos[c] = new Semaphore(1,true);
}
// Se instancian los cinco filósofos aportando los datos: posiciones de los dos palillos, nombre, y los dos palillos
// que le pertenecen y actúan como semáforos de uso compartido y excluyente
filosofo f1 = new filosofo(5,1, "Filósofo 1",palillos[4],palillos[0]);
filosofo f2 = new filosofo(1,2, "Filósofo 2",palillos[0],palillos[1]);
filosofo f3 = new filosofo(2,3, "Filósofo 3",palillos[1],palillos[2]);
filosofo f4 = new filosofo(3,4, "Filósofo 4",palillos[2],palillos[3]);
filosofo f5 = new filosofo(4,5, "Filósofo 5",palillos[3],palillos[4]);
// Se inician los cinco hilos.
f1.start();
f2.start();
f3.start();
f4.start();
f5.start();
}
}
CLASE HILO FILÓSOFO
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package cena_filosofos;
// Importo las clases necesarias para trabajar
import java.util.Random;
import java.util.concurrent.Semaphore;
/**
*
* @author glop
*/
public class filosofo extends Thread{
private static final Random aleatorio = new Random(); // Generador de números aleatorios
private Semaphore palilloder; // Semáforo que representa el palillo derecho
private Semaphore palilloizq; // Semñaforo que representa en palillo izquierdo
int posder=-1; // Toma la posición del palillo correspondiente para informar al usuario
int posizq=-1; // Toma la posición del palillo correspondiente para informar al usuario
String nombre; // Nombre del filósofo
// Construye el filósofo con los datos proporcionados. Éstos son; la posición de los dos palillos que le pertencen.
// el nombre del filósofo y los dos palillos que utilizará que son semáforos de uso compartido y excluyente
public filosofo(int posd,int posiz,String nomb,Semaphore palder,Semaphore palizq) {
this.posder = posd;
this.posizq = posiz;
this.nombre = nomb;
this.palilloder = palder;
this.palilloizq = palizq;
}
// Método que representa al filósofo pensando
private void pensar() {
try {
System.out.println(this.nombre + " está pensando");
sleep(aleatorio.nextInt(5000)) ; // El tiempo que transcurre pensando se calcula aleatoriamente hasta 5 segundos
} catch(InterruptedException ex) {
}
}
// Método que representa al filósofo comiendo
private void comer() {
try { // Intenta tomar los palillos
palilloder.acquire(); // Toma el palillo derecho, si este palillo estuviera en uso se entraría en una disputa,
// el hilo se interrumpiría,
// y el proceso iría al finally donde lo suelta
if (!palilloizq.tryAcquire()) { // Si el palillo izquierdo esta siendo usado el filósofo espera.
System.out.println(this.nombre + " está hambriento"); // Se lanza un mensaje por pantalla indicando
// que el filósofo está hambriento
return; // Irá inmediatamente al finally donde soltará el palillo derecho que es quien primero tomó
}
// Si ha llegado hasta aquí es que el palillo izquierdo también ha sido tomado con éxito. ¡Ya puede empezar!
// Se lanza el mensaje por pantalla de que el filósofo ha empezado a comer.
// También se indica, a efectos informativos, los palillos que utiliza
System.out.println(this.nombre + " está comiendo con los palillos : " + this.posder + " y " + this.posizq);
sleep(aleatorio.nextInt(5000)); // Se calcula la demora en comer aleatoriamente hasta 5 segundos
// Se lanza el mensaje por pantalla de que el filósofo ha terminado de comer.
// También se indica, a efectos informativos, los palillos que ha utilizado y ahora libera
System.out.println(this.nombre + " ha terminado de comer y libera los palillos : "+ this.posder + " y " + this.posizq);
palilloizq.release(); // Como ya ha terminado de comer, suelta el palillo izquierdo.
} catch (InterruptedException ex) {
} finally {
// En cualquier caso, soltará el palillo derecho.
palilloder.release();
}
}
@Override
public void run() {
while(true) { // En un bucle infinito, piensa y come, piensa y come ...
pensar();
comer();
}
}
}
Productor consumidor
CLASE PRINCIPAL
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package productor_consumidor;
/**
*
* @author glop
*/
public class Productor_consumidor {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Buffer bu = new Buffer(); //Instalcia del objeto Buffer
productor pro = new productor(bu); // Instancia del objeto productor
consumidor con = new consumidor(bu); // Instancia del objeto consumidor
// Se lanzan los hilos
pro.start();
con.start();
}
}
CLASE BUFFER
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package productor_consumidor;
/**
* Clase del objeto Buffer
* @author glop
*/
public class Buffer {
char conten[] = new char[6]; // Array de char con 6 posiciones
public int capacidad=0; // Variable que almacena la capacidad del Buffer, se inicia con 0 y el máximo es 6
// Se construye el objeto Buffer y se dan valores char vacío al array
public Buffer() {
conten[0] = ' ';
conten[1] = ' ';
conten[2] = ' ';
conten[3] = ' ';
conten[4] = ' ';
conten[5] = ' ';
}
// Método sincronizado que deposita un caracter en el buffer
public synchronized void deposita(char caract) {
// La estructura while indica que el hilo debe esperar si no hay capacidad para más caracteres.
while(capacidad==5) {
try {
wait();
} catch(InterruptedException ex) {
}
}
// Se recorre el array el búsqueda de elementos vacío en los que depositar el caracter
for (int c=0;c<conten.length;c++) {
if (conten[c]==' ') {
conten[c] = caract;
capacidad = capacidad + 1;
break; // En el momento que encuentre un caracter vacío, se puede salir del bucle
}
}
notify(); // Se notifica a los demás hilo que acabó la operación
}
// Método sincronizado que recoge el caracter. Devuelve el caracter obtenido
public synchronized char recoge() {
char letra=' ';
// Si no hay nada que recoger, el hilo espera
while(capacidad==0) {
try {
wait();
} catch(InterruptedException ex) {
}
}
// Se recorre el array en búsqueda de elementos que tengan algún contenido.
for (int c=0;c<conten.length;c++) {
if (conten[c]!=' ') {
letra = conten[c]; // Almacena en la variable letra lo contenido en el elemento.
conten[c] = ' '; // Se borra el elemento ya que se ha extraído el caracter que tenía
capacidad = capacidad - 1;
break; // Cuando se ha extraído el elemento, se puede salir del bucle
}
}
notify(); // Notifica a los demás hilos que acabó la acción
return letra; // Devuelve el caracter obtenido
}
}
CLASE HILO PRODUCTOR
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package productor_consumidor;
/**
* Clase del objeto productor
* @author glop
*/
public class productor extends Thread {
private final String caracteres = "abcdefghijklmnñopqrstuvwxyz"; // String con las letras de abecedario
private Buffer buffer; // Instancia del objeto buffer
// Se construye el objeto productor pasando como parámetro un objeto Buffer
public productor(Buffer buff) {
this.buffer = buff;
}
public void run() {
// Se realiza un bucle 15 veces según lo pedido en la tarea
for (int c=0;c<15;c++) {
char l=caracteres.charAt((int)(Math.random()*caracteres.length()));; // Se genera aleatoriomente un caracter
buffer.deposita(l); // Se deposita en buffer
System.out.println("Depositado el caracter " + l + " en el buffer"); // Salidad por pantalla
try {
sleep(100);
} catch(InterruptedException ex) {
}
}
}
}
CLASE HILO CONSUMIDOR
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package productor_consumidor;
/**
* Clase del objeto consumidor
* @author glop
*/
public class consumidor extends Thread {
private Buffer buffer; // Instancia del objeto Buffer
// Se construye el objeto consumidor pasando por parámetro un objeto Buffer
public consumidor(Buffer buff) {
this.buffer = buff;
}
public void run() {
// Se realiza un bucle 15 veces según lo pedido en la tarea
for (int c=0;c<15;c++) {
char l;
l = buffer.recoge(); // Se almacena en una variable char el caracter obtenido de la recogida del buffer
System.out.println("Recogido el caracter " + l + " en el buffer"); // Salida por pantalla
try {
sleep(100);
} catch(InterruptedException ex) {
}
}
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package productor_consumidor;
/**
*
* @author glop
*/
public class Productor_consumidor {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Buffer bu = new Buffer(); //Instalcia del objeto Buffer
productor pro = new productor(bu); // Instancia del objeto productor
consumidor con = new consumidor(bu); // Instancia del objeto consumidor
// Se lanzan los hilos
pro.start();
con.start();
}
}
CLASE BUFFER
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package productor_consumidor;
/**
* Clase del objeto Buffer
* @author glop
*/
public class Buffer {
char conten[] = new char[6]; // Array de char con 6 posiciones
public int capacidad=0; // Variable que almacena la capacidad del Buffer, se inicia con 0 y el máximo es 6
// Se construye el objeto Buffer y se dan valores char vacío al array
public Buffer() {
conten[0] = ' ';
conten[1] = ' ';
conten[2] = ' ';
conten[3] = ' ';
conten[4] = ' ';
conten[5] = ' ';
}
// Método sincronizado que deposita un caracter en el buffer
public synchronized void deposita(char caract) {
// La estructura while indica que el hilo debe esperar si no hay capacidad para más caracteres.
while(capacidad==5) {
try {
wait();
} catch(InterruptedException ex) {
}
}
// Se recorre el array el búsqueda de elementos vacío en los que depositar el caracter
for (int c=0;c<conten.length;c++) {
if (conten[c]==' ') {
conten[c] = caract;
capacidad = capacidad + 1;
break; // En el momento que encuentre un caracter vacío, se puede salir del bucle
}
}
notify(); // Se notifica a los demás hilo que acabó la operación
}
// Método sincronizado que recoge el caracter. Devuelve el caracter obtenido
public synchronized char recoge() {
char letra=' ';
// Si no hay nada que recoger, el hilo espera
while(capacidad==0) {
try {
wait();
} catch(InterruptedException ex) {
}
}
// Se recorre el array en búsqueda de elementos que tengan algún contenido.
for (int c=0;c<conten.length;c++) {
if (conten[c]!=' ') {
letra = conten[c]; // Almacena en la variable letra lo contenido en el elemento.
conten[c] = ' '; // Se borra el elemento ya que se ha extraído el caracter que tenía
capacidad = capacidad - 1;
break; // Cuando se ha extraído el elemento, se puede salir del bucle
}
}
notify(); // Notifica a los demás hilos que acabó la acción
return letra; // Devuelve el caracter obtenido
}
}
CLASE HILO PRODUCTOR
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package productor_consumidor;
/**
* Clase del objeto productor
* @author glop
*/
public class productor extends Thread {
private final String caracteres = "abcdefghijklmnñopqrstuvwxyz"; // String con las letras de abecedario
private Buffer buffer; // Instancia del objeto buffer
// Se construye el objeto productor pasando como parámetro un objeto Buffer
public productor(Buffer buff) {
this.buffer = buff;
}
public void run() {
// Se realiza un bucle 15 veces según lo pedido en la tarea
for (int c=0;c<15;c++) {
char l=caracteres.charAt((int)(Math.random()*caracteres.length()));; // Se genera aleatoriomente un caracter
buffer.deposita(l); // Se deposita en buffer
System.out.println("Depositado el caracter " + l + " en el buffer"); // Salidad por pantalla
try {
sleep(100);
} catch(InterruptedException ex) {
}
}
}
}
CLASE HILO CONSUMIDOR
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package productor_consumidor;
/**
* Clase del objeto consumidor
* @author glop
*/
public class consumidor extends Thread {
private Buffer buffer; // Instancia del objeto Buffer
// Se construye el objeto consumidor pasando por parámetro un objeto Buffer
public consumidor(Buffer buff) {
this.buffer = buff;
}
public void run() {
// Se realiza un bucle 15 veces según lo pedido en la tarea
for (int c=0;c<15;c++) {
char l;
l = buffer.recoge(); // Se almacena en una variable char el caracter obtenido de la recogida del buffer
System.out.println("Recogido el caracter " + l + " en el buffer"); // Salida por pantalla
try {
sleep(100);
} catch(InterruptedException ex) {
}
}
}
}
Robots 2d
CLASE PRINCIPAL
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package robots2D;
import java.io.File;
import org.lwjgl.LWJGLUtil;
import org.newdawn.slick.*;
import org.newdawn.slick.Input.*;
import org.newdawn.slick.font.effects.ColorEffect;
import org.newdawn.slick.tiled.*;
/**
* JUEGO DE LOS ROBOTS - aplicación base para el desarrollo del examen de la segunda evaluación
*
*
*/
public class Robots2D extends BasicGame {
// Tilemap
private TiledMap mapa;
// Estado del jugador
private float jugadorX, jugadorY;
private SpriteSheet cuadros;
private SpriteSheet cuadrosRobot;
// Posición del corazón
private float corazonX, corazonY;
private Image corazon;
// NUEVO: Para almacenar la explosión
private SpriteSheet explosion;
private Animation jugador;
private Animation jugadorArriba;
private Animation jugadorDerecha;
private Animation jugadorAbajo;
private Animation jugadorIzquierda;
private boolean jugadorVivo;
// Estado de los robots
private Animation[] robot;
private Animation robotArriba;
private Animation robotDerecha;
private Animation robotAbajo;
private Animation robotIzquierda;
private float[] robotX, robotY;
private boolean[] robotVivo;
private boolean[] robotVisible;
private float[] robotVelocidad;
private int numeroRobotsVivos;
private static final int TOTAL_ROBOTS = 30;
// Escritura de cadenas
private UnicodeFont fuente;
// Contador de tiempo
private long tiempo;
// NUEVO: Música y sonidos
private Music musica;
private Sound sonido;
public Robots2D(String name) {
super(name);
}
public static void main(String[] args) {
System.setProperty("org.lwjgl.librarypath", new File(new File(System.getProperty("user.dir"), "native"), LWJGLUtil.getPlatformName()).getAbsolutePath());
System.setProperty("net.java.games.input.librarypath", System.getProperty("org.lwjgl.librarypath"));
try {
AppGameContainer container = new AppGameContainer(new Robots2D("PMDM06 - Tarea"));
container.setDisplayMode(640, 480, false);
container.setTargetFrameRate(60);
container.setVSync(true);
container.setShowFPS(false);
container.setUpdateOnlyWhenVisible(false);
container.start();
} catch (SlickException e) {
}
}
@Override
public void init(GameContainer gc) throws SlickException {
// cargar mapa
mapa = new TiledMap("data/mapa.tmx", "data");
corazon = new Image("data/corazon.png");
// cargar spritesheets
cuadros = new SpriteSheet("data/heroe.png", 24, 32);
cuadrosRobot = new SpriteSheet("data/robot.png", 24, 32);
explosion = new SpriteSheet("data/explosion.png", 32, 32); // NUEVO
// cargar animaciones del jugador
jugadorArriba = new Animation(cuadros, 0, 0, 2, 0, true, 150, false);
jugadorDerecha = new Animation(cuadros, 0, 1, 2, 1, true, 150, false);
jugadorAbajo = new Animation(cuadros, 0, 2, 2, 2, true, 150, false);
jugadorIzquierda = new Animation(cuadros, 0, 3, 2, 3, true, 150, false);
jugador = jugadorAbajo;
// cargar animaciones del robot
robotArriba = new Animation(cuadrosRobot, 0, 0, 2, 0, true, 150, true);
robotDerecha = new Animation(cuadrosRobot, 0, 1, 2, 1, true, 150, true);
robotAbajo = new Animation(cuadrosRobot, 0, 2, 2, 2, true, 150, true);
robotIzquierda = new Animation(cuadrosRobot, 0, 3, 2, 3, true, 150, true);
// estado inicial del jugador
jugadorX = 320;
jugadorY = 240;
jugadorVivo = true;
// estado inicial de los robots
robot = new Animation[TOTAL_ROBOTS];
robotX = new float[TOTAL_ROBOTS];
robotY = new float[TOTAL_ROBOTS];
robotVivo = new boolean[TOTAL_ROBOTS];
robotVelocidad = new float[TOTAL_ROBOTS];
// NUEVO: Un robot puede estar muerto pero visible mientras explota
robotVisible = new boolean[TOTAL_ROBOTS];
numeroRobotsVivos = TOTAL_ROBOTS;
// los colocamos repartidos al azar
for (int i=0;i<TOTAL_ROBOTS;i++) {
// Cogemos una coordenada X alejada del centro
float X = (float)((Math.random()*(gc.getWidth()/2-100)));
// ¿En la izquierda o en la derecha?
if (Math.random()<0.5f) {
robotX[i] = X;
robot[i] = robotDerecha; // mirar a la derecha
}
else {
robotX[i] = gc.getWidth()-X;
robot[i] = robotIzquierda; // mirar a la izquierda
}
// Cogemos una coordenada Y alejada del centro teniendo en cuenta
// que los primeros 64 píxeles no se pueden usar porque está
// el marcador
float Y = 64 + (float)((Math.random()*(gc.getHeight()/2-132)));
// ¿En la parte de arriba o de abajo?
if (Math.random()<0.5f) {
robotY[i] = Y;
}
else {
robotY[i] = gc.getHeight()-Y;
}
}
corazonX = (float)((Math.random()*(gc.getWidth()/2)));
corazonY = 64 + (float)((Math.random()*(gc.getHeight()/2)));
// indicamos que, de momento, los robots están vivos
for (int i = 0; i < TOTAL_ROBOTS; i++) {
robotVivo[i] = true;
robotVisible[i] = true;
// NUEVO: Que algunos empiecen más o menos rápidos
robotVelocidad[i] = 0.25f + 0.5f * (float) Math.random();
}
// cargar tipo de letra de la carpeta data y todos los símboles
// que podamos necesitar
fuente = new UnicodeFont("data/tuffy.ttf", 28, false, false);
// añade las letras ASCII estándar
fuente.addAsciiGlyphs();
// y ahora añadimos los caracteres españoles
fuente.addGlyphs("áéíóúÁÉÍÓÚñÑ¡¿");
// en Slick es obligatorio añadir un efecto para poder dibujar
// texto. Añadimos un efecto vacío.
fuente.getEffects().add(new ColorEffect(java.awt.Color.WHITE));
// cargamos los símbolos del tipo de letra
fuente.loadGlyphs();
// a partir de ahora, llamado a fuente.drawString(x, y, texto) ¡podremos
// escribir en el contenedor!
// NUEVO: Añadimos música de fondo y cargamos los efectos de sonido
musica = new Music("data/tuturne land!.mod");
sonido = new Sound("data/8bit_bomb_explosion.wav");
musica.loop();
// comenzar cuenta de tiempo. Apuntamos el número que contiene el
// reloj del sistema en milisegundos. De esta forma, restando esta
// cantidad a la cuenta actual nos dice el número de milisengudos
// que han transcurrido.
tiempo = System.currentTimeMillis();
}
@Override
public void update(GameContainer gc, int delta) throws SlickException {
Input entrada = gc.getInput();
// si se pulsa Esc, salir
if (entrada.isKeyDown(Input.KEY_ESCAPE)) { // Tecla ESC
gc.exit();
}
// si no quedan robots o ha muerto el jugador, no actualizar nada
if ((jugadorVivo == false) || (numeroRobotsVivos == 0)) {
return;
}
// movimiento del jugador
if (entrada.isKeyDown(Input.KEY_DOWN)) { // Tecla abajo
jugadorY += delta * 0.1f;
// evitar que nos salgamos por la parte inferior del contenedor
if (jugadorY > (gc.getHeight() - jugador.getHeight())) {
jugadorY = (gc.getHeight() - jugador.getHeight());
}
jugador = jugadorAbajo;
jugador.update(delta);
}
if (entrada.isKeyDown(Input.KEY_UP)) { // Tecla arriba
jugadorY -= delta * 0.1f;
// evitar que nos salgamos por la parte superior del contenedor
if (jugadorY < 32) {
jugadorY = 32;
}
jugador = jugadorArriba;
jugador.update(delta);
}
if (entrada.isKeyDown(Input.KEY_RIGHT)) { // Tecla derecha
jugadorX += delta * 0.1f;
// evitar que nos salgamos por la derecha del contenedor
if (jugadorX > (gc.getWidth() - jugador.getWidth())) {
jugadorX = (gc.getWidth() - jugador.getWidth());
}
jugador = jugadorDerecha;
jugador.update(delta);
}
if (entrada.isKeyDown(Input.KEY_LEFT)) { // Tecla izquierda
jugadorX -= delta * 0.1f;
// evitar que nos salgamos por la izquierda del contenedor
if (jugadorX < 0) {
jugadorX = 0;
}
jugador = jugadorIzquierda;
jugador.update(delta);
}
// NUEVO: Movemos los robots hacia el jugador si están vivos
// cada 50 segundos, el robot se moverá un 50% más rápido
// respecto a la velocidad inicial
float prisa = 1.0f + (System.currentTimeMillis() - tiempo) / 50000.0f; // cuanto mayor sea, más rápido irán
for (int i = 0; i < TOTAL_ROBOTS; i++) {
if (robotVivo[i]) {
// calculamos la escala del movimiento, pero la acotaremos
// para que no sean demasiado rápidos o el jugador nunca
// podría escapar
float escalaFinal = prisa * 0.1f * robotVelocidad[i];
escalaFinal = escalaFinal > 1.15 ? 1.15f : escalaFinal;
if (robotY[i] > jugadorY) {
robotY[i] -= delta * escalaFinal;
robot[i] = robotArriba;
}
if (robotY[i] < jugadorY) {
robotY[i] += delta * escalaFinal;
robot[i] = robotAbajo;
}
if (robotX[i] > jugadorX) {
robotX[i] -= delta * escalaFinal;
robot[i] = robotIzquierda;
}
if (robotX[i] < jugadorX) {
robotX[i] += delta * escalaFinal;
robot[i] = robotDerecha;
}
} else {
// si el robot está visible pero su animación se ha parado
// es que acaba de termina la animación de la explosión,
// así que lo ocultamos
if ((robotVisible[i]) && (robot[i].isStopped())) {
robotVisible[i] = false;
}
}
}
// NUEVO: Comprobar si han chocado entre sí o con el jugador
for (int i = 0; i < TOTAL_ROBOTS; i++) {
if (robotVivo[i]) {
// ¿Ha chocado el robot 'i' con el jugador?
// Para nosotros habrán colisionado cuando
// la parte izquierda de sus bases estén a menos de 4
// píxeles en vertical y en horizontal
if ((Math.abs(robotX[i] - jugadorX) < 4.0f)
&& (Math.abs(robotY[i] - jugadorY) < 4.0f)) {
// Sí: robot muerto
robotVivo[i] = false;
// Hacerlo explotar una sola vez
robot[i] = new Animation(explosion, 0, 0, 3, 3, true, 100, true);
robot[i].setLooping(false);
// Aunque no sirve de mucho, ¡un robot menos!
numeroRobotsVivos -= 1;
// Reproducir explosión
sonido.play();
// El jugador ha muerto
jugadorVivo = false;
}
// ¿Ha chocado el robot 'i' con otro robot?
for (int j = 0; j < TOTAL_ROBOTS; j++) {
// Cuidado, hay que evita comprobar si hemos chocado con
// nosotros o nada más empezar explotaremos
if (i != j && robotVivo[j]) {
// Para nosotros habrán colisionado los robots cuando
// la parte izquierda de sus bases estén a menos de 4
// píxeles en vertical y en horizontal
if ((Math.abs(robotX[i] - robotX[j]) < 4.0f)
&& (Math.abs(robotY[i] - robotY[j]) < 4.0f)) {
// Sí: robots muertos
robotVivo[i] = false;
robotVivo[j] = false;
// Crear una nueva explosión y asignársela a los
// dos robots ya que explotan simultáneamente
robot[i] = new Animation(explosion, 0, 0, 3, 3, true, 100, true);
// Que sólo exploten una vez
robot[i].setLooping(false);
robot[j] = robot[i];
// Dos robots menos
numeroRobotsVivos -= 2;
// Reproducir explosión
sonido.play();
// Si ya no quedan robots, ¡hemos ganado!
if (numeroRobotsVivos == 100) {
// Cambiar música
musica = new Music("data/bi-menu.xm");
musica.loop();
}
// Esto es para evitar que un robot ya
// muerto destruya a otro
break;
}
}
}
}
}
if ((Math.abs((jugadorX+jugador.getWidth()) - (corazonX + corazon.getWidth())) < 13.0f)
&& (Math.abs((jugadorY+jugador.getHeight()) - (corazonY+corazon.getHeight())) < 10.0f)) {
numeroRobotsVivos=0;
}
}
@Override
public void render(GameContainer gc, Graphics g) throws SlickException {
// dibujar tilemap
mapa.render(0, 0);
corazon.draw(corazonX,corazonY);
// dibujar jugador. NUEVO: sólo si está vivo
if (jugadorVivo == true) {
jugador.draw(jugadorX, jugadorY);
}
// dibujar robots si están visibles
for (int i = 0; i < TOTAL_ROBOTS; i++) {
if (robotVisible[i]) {
robot[i].draw(robotX[i], robotY[i]);
}
}
// dibujar robots restantes
fuente.drawString(400, 10, "Quedan " + numeroRobotsVivos + " robots");
if (jugadorVivo == false) {
String gameOver = "Fin de juego";
// dibujamos el texto centrado en el contenedor
fuente.drawString((gc.getWidth() - fuente.getWidth(gameOver)) / 2, (gc.getHeight() - fuente.getHeight(gameOver)) / 2, gameOver, Color.red);
return;
} else {
if (numeroRobotsVivos == 0) {
String gameOver = "¡Has ganado!";
// dibujamos el texto centrado en el contenedor
fuente.drawString((gc.getWidth() - fuente.getWidth(gameOver)) / 2, (gc.getHeight() - fuente.getHeight(gameOver)) / 2, gameOver, Color.yellow);
return;
}
}
// dibujar tiempo transcurrido si no ha acabado el juego
fuente.drawString(40, 10, "Tiempo: " + (System.currentTimeMillis() - tiempo) / 1000);
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package robots2D;
import java.io.File;
import org.lwjgl.LWJGLUtil;
import org.newdawn.slick.*;
import org.newdawn.slick.Input.*;
import org.newdawn.slick.font.effects.ColorEffect;
import org.newdawn.slick.tiled.*;
/**
* JUEGO DE LOS ROBOTS - aplicación base para el desarrollo del examen de la segunda evaluación
*
*
*/
public class Robots2D extends BasicGame {
// Tilemap
private TiledMap mapa;
// Estado del jugador
private float jugadorX, jugadorY;
private SpriteSheet cuadros;
private SpriteSheet cuadrosRobot;
// Posición del corazón
private float corazonX, corazonY;
private Image corazon;
// NUEVO: Para almacenar la explosión
private SpriteSheet explosion;
private Animation jugador;
private Animation jugadorArriba;
private Animation jugadorDerecha;
private Animation jugadorAbajo;
private Animation jugadorIzquierda;
private boolean jugadorVivo;
// Estado de los robots
private Animation[] robot;
private Animation robotArriba;
private Animation robotDerecha;
private Animation robotAbajo;
private Animation robotIzquierda;
private float[] robotX, robotY;
private boolean[] robotVivo;
private boolean[] robotVisible;
private float[] robotVelocidad;
private int numeroRobotsVivos;
private static final int TOTAL_ROBOTS = 30;
// Escritura de cadenas
private UnicodeFont fuente;
// Contador de tiempo
private long tiempo;
// NUEVO: Música y sonidos
private Music musica;
private Sound sonido;
public Robots2D(String name) {
super(name);
}
public static void main(String[] args) {
System.setProperty("org.lwjgl.librarypath", new File(new File(System.getProperty("user.dir"), "native"), LWJGLUtil.getPlatformName()).getAbsolutePath());
System.setProperty("net.java.games.input.librarypath", System.getProperty("org.lwjgl.librarypath"));
try {
AppGameContainer container = new AppGameContainer(new Robots2D("PMDM06 - Tarea"));
container.setDisplayMode(640, 480, false);
container.setTargetFrameRate(60);
container.setVSync(true);
container.setShowFPS(false);
container.setUpdateOnlyWhenVisible(false);
container.start();
} catch (SlickException e) {
}
}
@Override
public void init(GameContainer gc) throws SlickException {
// cargar mapa
mapa = new TiledMap("data/mapa.tmx", "data");
corazon = new Image("data/corazon.png");
// cargar spritesheets
cuadros = new SpriteSheet("data/heroe.png", 24, 32);
cuadrosRobot = new SpriteSheet("data/robot.png", 24, 32);
explosion = new SpriteSheet("data/explosion.png", 32, 32); // NUEVO
// cargar animaciones del jugador
jugadorArriba = new Animation(cuadros, 0, 0, 2, 0, true, 150, false);
jugadorDerecha = new Animation(cuadros, 0, 1, 2, 1, true, 150, false);
jugadorAbajo = new Animation(cuadros, 0, 2, 2, 2, true, 150, false);
jugadorIzquierda = new Animation(cuadros, 0, 3, 2, 3, true, 150, false);
jugador = jugadorAbajo;
// cargar animaciones del robot
robotArriba = new Animation(cuadrosRobot, 0, 0, 2, 0, true, 150, true);
robotDerecha = new Animation(cuadrosRobot, 0, 1, 2, 1, true, 150, true);
robotAbajo = new Animation(cuadrosRobot, 0, 2, 2, 2, true, 150, true);
robotIzquierda = new Animation(cuadrosRobot, 0, 3, 2, 3, true, 150, true);
// estado inicial del jugador
jugadorX = 320;
jugadorY = 240;
jugadorVivo = true;
// estado inicial de los robots
robot = new Animation[TOTAL_ROBOTS];
robotX = new float[TOTAL_ROBOTS];
robotY = new float[TOTAL_ROBOTS];
robotVivo = new boolean[TOTAL_ROBOTS];
robotVelocidad = new float[TOTAL_ROBOTS];
// NUEVO: Un robot puede estar muerto pero visible mientras explota
robotVisible = new boolean[TOTAL_ROBOTS];
numeroRobotsVivos = TOTAL_ROBOTS;
// los colocamos repartidos al azar
for (int i=0;i<TOTAL_ROBOTS;i++) {
// Cogemos una coordenada X alejada del centro
float X = (float)((Math.random()*(gc.getWidth()/2-100)));
// ¿En la izquierda o en la derecha?
if (Math.random()<0.5f) {
robotX[i] = X;
robot[i] = robotDerecha; // mirar a la derecha
}
else {
robotX[i] = gc.getWidth()-X;
robot[i] = robotIzquierda; // mirar a la izquierda
}
// Cogemos una coordenada Y alejada del centro teniendo en cuenta
// que los primeros 64 píxeles no se pueden usar porque está
// el marcador
float Y = 64 + (float)((Math.random()*(gc.getHeight()/2-132)));
// ¿En la parte de arriba o de abajo?
if (Math.random()<0.5f) {
robotY[i] = Y;
}
else {
robotY[i] = gc.getHeight()-Y;
}
}
corazonX = (float)((Math.random()*(gc.getWidth()/2)));
corazonY = 64 + (float)((Math.random()*(gc.getHeight()/2)));
// indicamos que, de momento, los robots están vivos
for (int i = 0; i < TOTAL_ROBOTS; i++) {
robotVivo[i] = true;
robotVisible[i] = true;
// NUEVO: Que algunos empiecen más o menos rápidos
robotVelocidad[i] = 0.25f + 0.5f * (float) Math.random();
}
// cargar tipo de letra de la carpeta data y todos los símboles
// que podamos necesitar
fuente = new UnicodeFont("data/tuffy.ttf", 28, false, false);
// añade las letras ASCII estándar
fuente.addAsciiGlyphs();
// y ahora añadimos los caracteres españoles
fuente.addGlyphs("áéíóúÁÉÍÓÚñÑ¡¿");
// en Slick es obligatorio añadir un efecto para poder dibujar
// texto. Añadimos un efecto vacío.
fuente.getEffects().add(new ColorEffect(java.awt.Color.WHITE));
// cargamos los símbolos del tipo de letra
fuente.loadGlyphs();
// a partir de ahora, llamado a fuente.drawString(x, y, texto) ¡podremos
// escribir en el contenedor!
// NUEVO: Añadimos música de fondo y cargamos los efectos de sonido
musica = new Music("data/tuturne land!.mod");
sonido = new Sound("data/8bit_bomb_explosion.wav");
musica.loop();
// comenzar cuenta de tiempo. Apuntamos el número que contiene el
// reloj del sistema en milisegundos. De esta forma, restando esta
// cantidad a la cuenta actual nos dice el número de milisengudos
// que han transcurrido.
tiempo = System.currentTimeMillis();
}
@Override
public void update(GameContainer gc, int delta) throws SlickException {
Input entrada = gc.getInput();
// si se pulsa Esc, salir
if (entrada.isKeyDown(Input.KEY_ESCAPE)) { // Tecla ESC
gc.exit();
}
// si no quedan robots o ha muerto el jugador, no actualizar nada
if ((jugadorVivo == false) || (numeroRobotsVivos == 0)) {
return;
}
// movimiento del jugador
if (entrada.isKeyDown(Input.KEY_DOWN)) { // Tecla abajo
jugadorY += delta * 0.1f;
// evitar que nos salgamos por la parte inferior del contenedor
if (jugadorY > (gc.getHeight() - jugador.getHeight())) {
jugadorY = (gc.getHeight() - jugador.getHeight());
}
jugador = jugadorAbajo;
jugador.update(delta);
}
if (entrada.isKeyDown(Input.KEY_UP)) { // Tecla arriba
jugadorY -= delta * 0.1f;
// evitar que nos salgamos por la parte superior del contenedor
if (jugadorY < 32) {
jugadorY = 32;
}
jugador = jugadorArriba;
jugador.update(delta);
}
if (entrada.isKeyDown(Input.KEY_RIGHT)) { // Tecla derecha
jugadorX += delta * 0.1f;
// evitar que nos salgamos por la derecha del contenedor
if (jugadorX > (gc.getWidth() - jugador.getWidth())) {
jugadorX = (gc.getWidth() - jugador.getWidth());
}
jugador = jugadorDerecha;
jugador.update(delta);
}
if (entrada.isKeyDown(Input.KEY_LEFT)) { // Tecla izquierda
jugadorX -= delta * 0.1f;
// evitar que nos salgamos por la izquierda del contenedor
if (jugadorX < 0) {
jugadorX = 0;
}
jugador = jugadorIzquierda;
jugador.update(delta);
}
// NUEVO: Movemos los robots hacia el jugador si están vivos
// cada 50 segundos, el robot se moverá un 50% más rápido
// respecto a la velocidad inicial
float prisa = 1.0f + (System.currentTimeMillis() - tiempo) / 50000.0f; // cuanto mayor sea, más rápido irán
for (int i = 0; i < TOTAL_ROBOTS; i++) {
if (robotVivo[i]) {
// calculamos la escala del movimiento, pero la acotaremos
// para que no sean demasiado rápidos o el jugador nunca
// podría escapar
float escalaFinal = prisa * 0.1f * robotVelocidad[i];
escalaFinal = escalaFinal > 1.15 ? 1.15f : escalaFinal;
if (robotY[i] > jugadorY) {
robotY[i] -= delta * escalaFinal;
robot[i] = robotArriba;
}
if (robotY[i] < jugadorY) {
robotY[i] += delta * escalaFinal;
robot[i] = robotAbajo;
}
if (robotX[i] > jugadorX) {
robotX[i] -= delta * escalaFinal;
robot[i] = robotIzquierda;
}
if (robotX[i] < jugadorX) {
robotX[i] += delta * escalaFinal;
robot[i] = robotDerecha;
}
} else {
// si el robot está visible pero su animación se ha parado
// es que acaba de termina la animación de la explosión,
// así que lo ocultamos
if ((robotVisible[i]) && (robot[i].isStopped())) {
robotVisible[i] = false;
}
}
}
// NUEVO: Comprobar si han chocado entre sí o con el jugador
for (int i = 0; i < TOTAL_ROBOTS; i++) {
if (robotVivo[i]) {
// ¿Ha chocado el robot 'i' con el jugador?
// Para nosotros habrán colisionado cuando
// la parte izquierda de sus bases estén a menos de 4
// píxeles en vertical y en horizontal
if ((Math.abs(robotX[i] - jugadorX) < 4.0f)
&& (Math.abs(robotY[i] - jugadorY) < 4.0f)) {
// Sí: robot muerto
robotVivo[i] = false;
// Hacerlo explotar una sola vez
robot[i] = new Animation(explosion, 0, 0, 3, 3, true, 100, true);
robot[i].setLooping(false);
// Aunque no sirve de mucho, ¡un robot menos!
numeroRobotsVivos -= 1;
// Reproducir explosión
sonido.play();
// El jugador ha muerto
jugadorVivo = false;
}
// ¿Ha chocado el robot 'i' con otro robot?
for (int j = 0; j < TOTAL_ROBOTS; j++) {
// Cuidado, hay que evita comprobar si hemos chocado con
// nosotros o nada más empezar explotaremos
if (i != j && robotVivo[j]) {
// Para nosotros habrán colisionado los robots cuando
// la parte izquierda de sus bases estén a menos de 4
// píxeles en vertical y en horizontal
if ((Math.abs(robotX[i] - robotX[j]) < 4.0f)
&& (Math.abs(robotY[i] - robotY[j]) < 4.0f)) {
// Sí: robots muertos
robotVivo[i] = false;
robotVivo[j] = false;
// Crear una nueva explosión y asignársela a los
// dos robots ya que explotan simultáneamente
robot[i] = new Animation(explosion, 0, 0, 3, 3, true, 100, true);
// Que sólo exploten una vez
robot[i].setLooping(false);
robot[j] = robot[i];
// Dos robots menos
numeroRobotsVivos -= 2;
// Reproducir explosión
sonido.play();
// Si ya no quedan robots, ¡hemos ganado!
if (numeroRobotsVivos == 100) {
// Cambiar música
musica = new Music("data/bi-menu.xm");
musica.loop();
}
// Esto es para evitar que un robot ya
// muerto destruya a otro
break;
}
}
}
}
}
if ((Math.abs((jugadorX+jugador.getWidth()) - (corazonX + corazon.getWidth())) < 13.0f)
&& (Math.abs((jugadorY+jugador.getHeight()) - (corazonY+corazon.getHeight())) < 10.0f)) {
numeroRobotsVivos=0;
}
}
@Override
public void render(GameContainer gc, Graphics g) throws SlickException {
// dibujar tilemap
mapa.render(0, 0);
corazon.draw(corazonX,corazonY);
// dibujar jugador. NUEVO: sólo si está vivo
if (jugadorVivo == true) {
jugador.draw(jugadorX, jugadorY);
}
// dibujar robots si están visibles
for (int i = 0; i < TOTAL_ROBOTS; i++) {
if (robotVisible[i]) {
robot[i].draw(robotX[i], robotY[i]);
}
}
// dibujar robots restantes
fuente.drawString(400, 10, "Quedan " + numeroRobotsVivos + " robots");
if (jugadorVivo == false) {
String gameOver = "Fin de juego";
// dibujamos el texto centrado en el contenedor
fuente.drawString((gc.getWidth() - fuente.getWidth(gameOver)) / 2, (gc.getHeight() - fuente.getHeight(gameOver)) / 2, gameOver, Color.red);
return;
} else {
if (numeroRobotsVivos == 0) {
String gameOver = "¡Has ganado!";
// dibujamos el texto centrado en el contenedor
fuente.drawString((gc.getWidth() - fuente.getWidth(gameOver)) / 2, (gc.getHeight() - fuente.getHeight(gameOver)) / 2, gameOver, Color.yellow);
return;
}
}
// dibujar tiempo transcurrido si no ha acabado el juego
fuente.drawString(40, 10, "Tiempo: " + (System.currentTimeMillis() - tiempo) / 1000);
}
}
Midlet mensajero
CLASE PRINCIPAL
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package midletMensajero;
// Importo las clases necesarias para trabajar.
import java.io.IOException;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.ImageItem;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.*;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
/**
* Midlet que permite la gestión de una agenda y el envío de sms's a la misma.
* @author glop
*/
public class MidletMensajero extends MIDlet implements CommandListener {
Display pantalla; // Pantalla del midlet.
private Command seleccionar; // Comando con la opción seleccionar del menú principal.
private Command Mver; // Comando con que lanza el formulario de ver cliente.
private Command Mnuevo; // Comando con que lanza el formulario de guardar cliente.
private Command Mmodificar; // Comando con que lanza el formulario de modificar cliente.
private Command Meliminar; // Comando elimina el cliente seleccionado.
private Command Mvolver; // Comando que regresa al menú principal.
private Command cGuardar; // Comando que guarda el cliente.
private Command cModificar; // Comando que modifica el cliente.
private Command MmodificarPublicidad; // Modifica la plantilla del mensaje publicitario.
private Command cVolver; // Comando que regresa al lista de clientes.
private Command siguiente; // Comando utilizado en la pantalla de presentación que da paso a la pantalla de instrucciones.
private Command probar; // Comando utilizado en la pantalla de instrucciones que da paso a la pantalla del menú principal.
private Command adios; // Comando utilizado en la pantalla de créditos que cierra la aplicación.
private RecordStore almacen; // Almacen de registros de clientes.
listaClientes listado; // Instancia del objeto listaClientes que hereda de List.
private List menu; // Lista que forma el menú principal.
TextField tnombre; // TextField nombre. Utiliza tanto en la adición de clientes como en la modificación.
TextField ttelefono; // TextField teléfono. Utiliza tanto en la adición de clientes como en la modificación.
TextBox sms; // TextBox sms. Utilizado en la modificación del mensaje publicitario.
private RecordEnumeration enumerador; // Enumerador que recorre los registros del RecordStore.
private Form contenedor; // Formulario con el que se forman las pantallas según la necesidad.
mensaje smsObj; // Instancia del objeto mensaje que representa un hilo de ejecución.
String nombreCliente,telefonoCliente,smsTexto; // Variables que almacenan los datos necesarios para envío de mensajes
public MidletMensajero() throws IOException {
pantalla = Display.getDisplay(this); // Se indica que coja nuestra pantalla coja la pantalla principal del midlet.
smsTexto = "Enhorabuena ***** ha sido agraciado con un premio de 1000 euros";
presentacion(); // Se llama al método presentación que lanza la pantalla con el mismo nombre.
}
// Método que lanza la pantalla de presentación.
public void presentacion() throws IOException {
contenedor = new Form(""); // Formulario sin título
contenedor.append("Tarea 3 -- Midlet Mensajero"); // Se añade texto
Image imag = Image.createImage("imagenes/java.png"); // Se crea una imagen
ImageItem elemento= new ImageItem ("", imag, ImageItem.LAYOUT_CENTER, ""); // La imagen se pasa a un ImageItem para
// definir algunos detalles
contenedor.append(elemento); // Se añade el ImageItem
contenedor.append("Gabriel López Marcos"); // Se añade texto
// Se añaden los comandos que tendrá la pantalla
siguiente = new Command("Siguiente",Command.OK,0);
contenedor.addCommand(siguiente);
contenedor.setCommandListener(this); // Se asigna el oyente
pantalla.setCurrent(contenedor); // La pantalla activa es ésta.
}
// Método que lanza la pantalla de instrucciones.
public void instrucciones() {
contenedor = new Form("Instrucciones");
contenedor.append("La aplicación consiste en una pequeña agenda de clientes.\n"
+ "- Tienes control completo sobre los clientes, tanto su adición como su modificación\n"
+ "- Es posible enviar mensajes publicitarios a la lista de clientes, siendo posible editar el mensaje enviado");
probar = new Command("Probar",Command.OK,0);
contenedor.addCommand(probar);
contenedor.setCommandListener(this);
pantalla.setCurrent(contenedor);
}
// Lanza un menú principal con las opciones de la aplicación.
public void menu() {
menu = new List("Opciones",List.IMPLICIT);
menu.append("Explorar lista de clientes", null);
menu.append("Modificar mensaje publicitario", null);
menu.append("Enviar publicidad a clientes", null);
menu.append("Salir de la aplicación", null);
seleccionar = new Command("Seleccionar",Command.OK,0);
menu.addCommand(seleccionar);
menu.setCommandListener(this);
pantalla.setCurrent(menu);
}
// Se listan todos los clientes y se añaden las opciones que se pueden realizar sobre ellos.
public void listarClientes() throws RecordStoreException {
listado = new listaClientes("Clientes"); // Se instancia un nuevo objeto de listaClientes.
listado.listar();
Mver = new Command("Ver",Command.OK,0);
Mnuevo = new Command("Nuevo cliente",Command.OK,1);
Mmodificar = new Command("Editar cliente",Command.OK,1);
Meliminar = new Command("Borrar cliente",Command.OK,1);
Mvolver = new Command("Volver",Command.OK,1);
listado.addCommand(Mnuevo);
if (listado.size() != 0) {
listado.addCommand(Mver);
listado.addCommand(Mmodificar);
listado.addCommand(Meliminar);
}
listado.addCommand(Mvolver);
listado.setCommandListener(this);
pantalla.setCurrent(listado);
}
// Método que lanza la pantalla de visualización de cliente. Para ello tenemos que obtener dicho cliente y lo hacemos
// recurriendo a la tabla hash.
public void verCliente() {
// Se almacena el índice seleccionado de la lista. Recordemos que este índice está relacionado con la tabla hash
// paralela de registros y que ésta contiene los clientes y podremos trabajar con sus datos.
int idSeleccionado = listado.getSelectedIndex();
// Se pasa el idSeleecionado al almacén paralelo de clientes para que nos devuelve el cliente asociado.
// Guardamos lo obtenido en un objeto con el que trabajaremos.
Object chash = listado.almacen_hash.get(String.valueOf(idSeleccionado));
String cliente; // Variable donde se almacena la parte de los datos, sin el índice, del cliente almacenado en el objeto.
String nombre; // Variable donde se almacena el nombre del cliente a editar.
String telefono; // Variable donde se almacena el teléfono del cliente a editar.
int separador = chash.toString().indexOf("|"); // Se almacena la posición del primer separador.
// Se almacena en un string el cliente. Recordemos que en la tabla hash paralela al RecordStore, almacenamos los
// clientes con su id para poder trabajar con este datos. Es por ello que tengo que acceder sin ese dato.
// En la tabla hash se almacena así : id|nombre|teléfono
cliente = chash.toString().substring(separador+1);
separador = cliente.indexOf("|"); // Obtengo la posición del separador en la parte de los datos del cliente.
// Almaceno el nombre. Lo obtengo con substring desde la posición 0 de la variable cliente, hasta el próximo separador.
nombre = cliente.substring(0,separador);
telefono = cliente.substring(separador+1); // El teléfono lo obtengo con substring desde el separador hasta el final.
// Ahora puedo construir el formulario.
contenedor = new Form("Detalle de cliente");
contenedor.append("Nombre :");
contenedor.append(nombre);
contenedor.append("Teléfono : ");
contenedor.append(telefono);
cVolver = new Command("Volver",Command.BACK,0);
contenedor.addCommand(cVolver);
contenedor.setCommandListener(this);
pantalla.setCurrent(contenedor);
}
// Método que lanza una pantalla con un formulario que contiene dos textfields para introducir un nuevo cliente.
public void nuevoCliente() throws RecordStoreException {
contenedor = new Form("Nuevo Cliente");
// Se añade el TextField nombre con 25 caracteres de capacidad. Se pueden introducir todo tipo de caracteres.
tnombre= new TextField ("Nombre: ", null, 25, TextField.ANY);
// Se añade el TextField teléfono con 25 caracteres de capacidad. Se pueden introducir únicamente números.
ttelefono= new TextField ("Teléfono: ", null, 25, TextField.PHONENUMBER);
contenedor.append(tnombre);
contenedor.append(ttelefono);
cVolver = new Command("Volver",Command.BACK,0);
cGuardar = new Command("Guardar",Command.BACK,1);
contenedor.addCommand(cVolver);
contenedor.addCommand(cGuardar);
contenedor.setCommandListener(this);
pantalla.setCurrent(contenedor);
}
// Método que lanza un formulario con los datos de clientes para editar. Es necesario rellenar dichos datos
// accediendo a la tabla hash asociado e introducirlos en el formulario.
public void modificarCliente() throws RecordStoreException {
// Se almacena el índice seleccionado de la lista. Recordemos que este índice está relacionado con la tabla hash
// paralela de registros y que ésta contiene los clientes y podremos trabajar con sus datos.
int idSeleccionado = listado.getSelectedIndex();
// Se pasa el idSeleecionado al almacén paralelo de clientes para que nos devuelve el cliente asociado.
// Guardamos lo obtenido en un objeto con el que trabajaremos.
Object chash = listado.almacen_hash.get(String.valueOf(idSeleccionado));
String cliente; // Variable donde se almacena la parte de los datos, sin el índice, del cliente almacenado en el objeto.
String nombre; // Variable donde se almacena el nombre del cliente a editar.
String telefono; // Variable donde se almacena el teléfono del cliente a editar.
int separador = chash.toString().indexOf("|"); // Se almacena la posición del primer separador.
// Se almacena en un string el cliente. Recordemos que en la tabla hash paralela al RecordStore, almacenamos los
// clientes con su id para poder trabajar con este datos. Es por ello que tengo que acceder sin ese dato.
// En la tabla hash se almacena así : id|nombre|teléfono
cliente = chash.toString().substring(separador+1);
separador = cliente.indexOf("|"); // Obtengo la posición del separador en la parte de los datos del cliente.
// Almaceno el nombre. Lo obtengo con substring desde la posición 0 de la variable cliente, hasta el próximo separador.
nombre = cliente.substring(0,separador);
telefono = cliente.substring(separador+1); // El teléfono lo obtengo con substring desde el separador hasta el final.
// Ahora puedo construir el formulario.
contenedor = new Form("Editar cliente");
tnombre= new TextField ("Nombre: ", nombre, 25, TextField.ANY);
ttelefono= new TextField ("Teléfono: ", telefono, 25, TextField.PHONENUMBER);
contenedor.append(tnombre);
contenedor.append(ttelefono);
cVolver = new Command("Volver",Command.BACK,0);
cModificar = new Command("Modificar",Command.BACK,1);
contenedor.addCommand(cVolver);
contenedor.addCommand(cModificar);
contenedor.setCommandListener(this);
pantalla.setCurrent(contenedor);
}
public void startApp() {
pantalla.setCurrent(contenedor);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
// Control de comandos.
public void commandAction(Command c, Displayable d) {
try {
if (c == siguiente) {
instrucciones();
}
if (c == probar) {
menu();
}
if (c == Mnuevo) {
nuevoCliente();
}
if (c == seleccionar) {
int opcion = menu.getSelectedIndex();
switch(opcion) {
case 0:
listarClientes();
break;
case 1:
editarMensaje();
break;
case 2:
if (listado.almacen_hash.size()!=0) {
envioPublicidad();
}
break;
case 3:
creditos();
}
}
if (c == adios) {
destroyApp (true);
notifyDestroyed ();
}
if (c == Mmodificar) {
modificarCliente();
}
if (c == Mver) {
verCliente();
}
if (c == cGuardar) {
if (!"".equals(tnombre.getString()) && !"".equals(ttelefono.getString())) {
listado.guardar(tnombre, ttelefono);
listarClientes();
}
}
if (c == cModificar) {
if (!"".equals(tnombre.getString()) && !"".equals(ttelefono.getString())) {
listado.modificar(tnombre, ttelefono);
listarClientes();
}
}
if (c == Meliminar) {
listado.eliminar();
listarClientes();
}
if (c == Mvolver) {
pantalla.setCurrent(menu);
}
if (c == cVolver) {
pantalla.setCurrent(listado);
}
if (c == MmodificarPublicidad) {
smsTexto = sms.getString();
pantalla.setCurrent(menu);
}
} catch (Exception ex) {
}
}
// Método que lanza la pantalla de edición del mensaje publicitario.
public void editarMensaje() {
// La pantalla la forma un TextBox con el texto del mensaje listo para ser editado.
sms = new TextBox("",smsTexto,255,TextField.ANY);
MmodificarPublicidad = new Command("Modificar",Command.OK,0);
Mvolver = new Command("Volver",Command.BACK,1);
sms.addCommand(MmodificarPublicidad);
sms.addCommand(Mvolver);
sms.setCommandListener(this);
pantalla.setCurrent(sms);
}
// Método que permite el envío de los mensajes a la lista.
// En el RecordStore los datos se guardan así: nombre|teléfono
public void envioPublicidad() throws RecordStoreException {
try {
almacen = RecordStore.openRecordStore("clientes", true); // Abrimos el almacén de registros.
enumerador = almacen.enumerateRecords(null, null, true); // Se los pasamos al enumerador.
while(enumerador.hasNextElement()) { // Mientras haya elementos ...
byte[] b = enumerador.nextRecord(); // Pasamos el registros a un array de bytes para trabajar con los datos.
String cliente = new String(b); // Convertimos el array a string.
int separador = cliente.toString().indexOf("|"); // Obtenemos la posición del separador.
nombreCliente = cliente.toString().substring(0,separador); // Obtenemos el nombre del cliente.
telefonoCliente = cliente.toString().substring(separador+1); // Obtenemos el teléfono del cliente.
// Nueva instancia de mensajes con los datos de los clientes y el texto publicitario.
// Iniciaremos tantos hilos como clientes existan en el almacén. Los hilos trabajarán sincronizados.
smsObj = new mensaje(nombreCliente,telefonoCliente,smsTexto);
smsObj.start(); // Se inicia el hilo
}
resultadoEnvios(); // Al término de las operaciones, se lanza la pantalla de resultados para informar.
} catch (Exception ex) {
} finally { // Al finalizar ...
if (enumerador!=null) {
enumerador.destroy(); // Cerramos el enumerador.
}
if (almacen!=null) {
almacen.closeRecordStore(); // Cerramos el RecordStore.
}
}
}
// Método que lanza una pantalla de resultados de operaciones.
public void resultadoEnvios() {
Alert alerta = new Alert("Resultado de los envíos");
alerta.setString("El envío de mensajes ha finalizado ... \n"
+ "Se han enviado un total de : " + listado.size() + " mensajes");
Mvolver = new Command("Volver",Command.BACK,0);
alerta.addCommand(Mvolver);
alerta.setCommandListener(this);
pantalla.setCurrent(alerta);
}
// Método que lanza una pantalla de créditos.
public void creditos() {
contenedor = new Form ("Créditos");
contenedor.append("Tarea realizada por:\n"
+ "Gabriel López Marcos\n"
+ "para DAM\n"
+ "10/Agosto/2013");
adios = new Command("Adiós",Command.OK,0);
contenedor.addCommand(adios);
contenedor.setCommandListener(this);
pantalla.setCurrent(contenedor);
}
}
CLASE LISTA DE CLIENTES
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package midletMensajero;
// Importo las clases necesarias para trabajar.
import java.util.Hashtable;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.TextField;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
/**
* Clase donde se efectúan las acciones sobre la lista de clientes. Hereda de List.
* @author glop
*/
public class listaClientes extends List {
RecordStore almacen; // Almacén de registros.
RecordEnumeration enumerador; // Enumerador de registros. Utilizado para recorrer el RecordStore.
Hashtable almacen_hash; // Tabla hash que guarda una lista paralela de clientes.
// Construímos el objeto listaClientes que hereda de List.
public listaClientes(String nombre) {
super(nombre,List.IMPLICIT); // Se construye una lista de tipo implícito.
almacen_hash = new Hashtable(); // Se construye una tabla hash como almacen paralelo de clientes.
}
// Lista todos los clientes y los pasa a una tabla hash paralela para trabajar con los datos.
public void listar() throws RecordStoreException {
super.deleteAll(); // Cada vez que se llama a este método, se limpian los resultados de la lista.
try {
almacen = RecordStore.openRecordStore("clientes", true); // Se crea un almacén de registros o se abre si ya existía.
enumerador = null;
enumerador = almacen.enumerateRecords(null, null, true); // Se pasa al enumerador la lista de clientes.
while(enumerador.hasNextElement()) { // Se recorre la lista de clientes.
int indice = enumerador.nextRecordId(); // Se almacena el id de cliente.
byte[] cl = almacen.getRecord(indice); // Se pasa el cliente a un array de bytes.
String cliente = new String(cl); // El cliente se almacena en una variable String.
int separador = cliente.indexOf("|"); // Posición del separador: nombre|teléfono.
String nombre = cliente.substring(0,separador); // Se almacena el nombre del cliente.
String telefono = cliente.substring(separador + 1); // Se almacena el teléfono del cliente.
super.append(nombre + " " + telefono, null); // Se añade el cliente completo a la lista.
// Se almacena el número de registros que tiene la tabla hash. Se almacena como String para poderlo utilizar
// para añadir un nuevo registro a la tabla hash que solo admite objetos como keys.
String nregistros = String.valueOf(almacen_hash.size());
// Se añade un nuevo registros a la tabla hash. Se asocia la posición que ocupa en la lista como key, con
// el cliente completo incluido el índice. Así es fácil de trabajar con sus datos.
almacen_hash.put(nregistros, indice + "|" + nombre + "|" + telefono);
}
} catch (Exception ex) {
System.out.println("Se ha producido un error al listar los clientes :" + ex);
} finally {
if (enumerador!=null) {
enumerador.destroy();} // Se cierra el enumerador.
if (almacen!=null) {
almacen.closeRecordStore();} // Se cierra el almacen.
}
}
// Método que guarda un nuevo registro en el RecordStore. Cuando acabe, se actualizará la lista y se añadirá
// el registro a la tabla hash.
// Se le pasan por parámetros los textfields de la pantalla de añadir clientes.
public void guardar(TextField nombre, TextField telefono) throws RecordStoreException {
try {
almacen = RecordStore.openRecordStore("clientes", true);
// Se almacena el cliente en una variable String con el formato adecuado.
String cliente = nombre.getString() + "|" + telefono.getString();
byte[] cl = cliente.getBytes(); // Se pasa el cliente a un array de bytes.
almacen.addRecord(cl, 0, cl.length); // Se guarda el cliente en el RecordStore.
} catch (Exception ex) {
System.out.println("Ha ocurrido un error al intentar guardar un registro : " + ex);
} finally {
almacen.closeRecordStore(); // Se cierra el RecordStore.
}
}
// Se modifica un cliente con los valores de los textfields que se le pasan por parámetros.
// Cuando acabe, se actualizará la tabla hash asociada.
public void modificar(TextField nombre, TextField telefono) throws RecordStoreException {
try {
int idSeleccionado = super.getSelectedIndex(); // Se almacena el índice de la lista seleccionado.
almacen = RecordStore.openRecordStore("clientes", true); // Se abre el RecordStore.
// Se obtiene el cliente de tabla hash paralela pasándole por parámetro el índice seleccionado.
// Lo almacenamos en un objeto
Object chash = almacen_hash.get(String.valueOf(idSeleccionado));
// Se obtiene la posición del separador. En el cliente se almacena así: nombre|teléfono
// en la tabla hash, sin embargo, se almacena así: id|nombre|teléfono
// Se almacena así para trabajar con los datos de cliente y poder acceder a sus índices dentro del RecordStore.
int separador = chash.toString().indexOf("|");
String indice = chash.toString().substring(0,separador); // Se obtiene el índice del cliente.
int indiceCliente = Integer.parseInt(indice); // Valor númerico del índice de cliente.
// Se almacena en un String el cliente modificado con los datos recogidos por parámetros.
String clienteModificado = nombre.getString() + "|" + telefono.getString();
// Se pasa el cliente modificado a un array de bytes. El único formato adecuado para guardar datos en RecordStore.
byte[] cl = clienteModificado.getBytes();
almacen.setRecord(indiceCliente, cl, 0, cl.length);
} catch (Exception ex) {
System.out.println("Ha ocurrido u error al intentar modificar el registro : " + ex);
} finally {
almacen.closeRecordStore(); // Se cierra el RecordStore.
}
}
public void eliminar() throws RecordStoreException {
try {
int idSeleccionado = super.getSelectedIndex(); // Se almacena el índice de la lista seleccionado.
almacen = RecordStore.openRecordStore("clientes", true); // Se abre el RecordStore.
// Se obtiene el cliente de tabla hash paralela pasándole por parámetro el índice seleccionado.
// Lo almacenamos en un objeto
Object chash = almacen_hash.get(String.valueOf(idSeleccionado));
// Se obtiene la posición del separador. En el cliente se almacena así: nombre|teléfono
// en la tabla hash, sin embargo, se almacena así: id|nombre|teléfono
// Se almacena así para trabajar con los datos de cliente y poder acceder a sus índices dentro del RecordStore.
int separador = chash.toString().indexOf("|");
String indice = chash.toString().substring(0,separador); // Se obtiene el índice del cliente.
int indiceCliente = Integer.parseInt(indice); // Valor númerico del índice de cliente.
almacen.deleteRecord(indiceCliente); // Se elimina por índice de cliente.
} catch (Exception ex) {
System.out.println("Se ha producido un error al intentar eliminar el cliente : " + ex);
} finally {
almacen.closeRecordStore(); // Se cierra el RecordStore.
}
}
}
CLASE HILO MENSAJES
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package midletMensajero;
// Importo las clases necesarias para trabajar.
import java.io.IOException;
import javax.microedition.io.Connector;
import javax.wireless.messaging.MessageConnection;
import javax.wireless.messaging.TextMessage;
/**
* Clase que controla los envíos de sms. Hereda de Thread.
* @author glop
*/
public class mensaje extends Thread {
int ocupado=0; // Variable que indice si el hilo está ocupado. 0 libre, 1 ocupado.
String nombre; // Variable que almacena el nombre del destinatarios.
String telefono; // Variable que almacena el teléfono del destinatario.
String texto; // Variable que almacena el texto del mensaje.
MessageConnection conexion; // Variable que establece la conexión.
TextMessage mensaje; // Variable que implementa el mensaje.
public mensaje(String nomb,String tlf,String text) { // Se contruye el objeto con los datos
this.nombre=nomb;
this.telefono=tlf;
this.texto = text;
}
// Método sincronizado que permite el envío de mensajes.
public synchronized void enviar() throws IOException {
try {
// Si el hilo está ocupado, espera. De este modo nunca se produce un bloque en la aplicación.
while(ocupado==1) {
wait();
}
ocupado=1; // Indicamos que un hilo está ocupado enviando el mensaje.
conexion= (MessageConnection) Connector.open("sms://+34"+this.telefono); // Establecemos la conexión.
mensaje= (TextMessage) conexion.newMessage(MessageConnection.TEXT_MESSAGE); // Creamos el mensaje.
String textoMensaje = this.texto; // Se almacena el mensaje en una variable para trabajar con su texto.
// En esta estructura controlamos que el mensaje tenga asteriscos (caracteres que utilizamos para referirnos a
// los clientes) si los hay, los cambiamos por el nombre del cliente; Si no los hay, el mensaje queda tal cual.
if (textoMensaje.indexOf("*")!=-1) {
char caracter='*'; // Caracter que buscamos.
int primera=0;
String aux1 = textoMensaje.substring(0,textoMensaje.lastIndexOf(caracter)); // Parte del mensaje hasta los asteriscos.
primera = aux1.indexOf("*"); // Primera asterisco.
aux1 = aux1.substring(0, primera); // Cogemos sólo la parte donde no hay asteriscos.
String aux2 = textoMensaje.substring(textoMensaje.lastIndexOf(caracter)+1); // La segunda parte del mensaje.
aux1 +=this.nombre; // Añadimos el nombre a la primera parte.
textoMensaje = aux1 + aux2; // Formamos el mensaje completo.
}
mensaje.setPayloadText(textoMensaje); // Añadimos el texto del mensaje.
conexion.send(mensaje); // Enviamos el mensaje
} catch (Exception ex) {
} finally { // Ejecutamos aquí las últimas acciones.
ocupado=0; // Indicamos que hemos acabado.
notify(); // Lo notificamos a los demás hilos.
conexion.close(); // Cerramos la conexión.
}
}
// Método que se ejecuta en el hilo al iniciarlo.
public void run() {
try {
enviar(); // Llamamos al método enviar.
} catch (IOException ex) {
}
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package midletMensajero;
// Importo las clases necesarias para trabajar.
import java.io.IOException;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.ImageItem;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.*;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
/**
* Midlet que permite la gestión de una agenda y el envío de sms's a la misma.
* @author glop
*/
public class MidletMensajero extends MIDlet implements CommandListener {
Display pantalla; // Pantalla del midlet.
private Command seleccionar; // Comando con la opción seleccionar del menú principal.
private Command Mver; // Comando con que lanza el formulario de ver cliente.
private Command Mnuevo; // Comando con que lanza el formulario de guardar cliente.
private Command Mmodificar; // Comando con que lanza el formulario de modificar cliente.
private Command Meliminar; // Comando elimina el cliente seleccionado.
private Command Mvolver; // Comando que regresa al menú principal.
private Command cGuardar; // Comando que guarda el cliente.
private Command cModificar; // Comando que modifica el cliente.
private Command MmodificarPublicidad; // Modifica la plantilla del mensaje publicitario.
private Command cVolver; // Comando que regresa al lista de clientes.
private Command siguiente; // Comando utilizado en la pantalla de presentación que da paso a la pantalla de instrucciones.
private Command probar; // Comando utilizado en la pantalla de instrucciones que da paso a la pantalla del menú principal.
private Command adios; // Comando utilizado en la pantalla de créditos que cierra la aplicación.
private RecordStore almacen; // Almacen de registros de clientes.
listaClientes listado; // Instancia del objeto listaClientes que hereda de List.
private List menu; // Lista que forma el menú principal.
TextField tnombre; // TextField nombre. Utiliza tanto en la adición de clientes como en la modificación.
TextField ttelefono; // TextField teléfono. Utiliza tanto en la adición de clientes como en la modificación.
TextBox sms; // TextBox sms. Utilizado en la modificación del mensaje publicitario.
private RecordEnumeration enumerador; // Enumerador que recorre los registros del RecordStore.
private Form contenedor; // Formulario con el que se forman las pantallas según la necesidad.
mensaje smsObj; // Instancia del objeto mensaje que representa un hilo de ejecución.
String nombreCliente,telefonoCliente,smsTexto; // Variables que almacenan los datos necesarios para envío de mensajes
public MidletMensajero() throws IOException {
pantalla = Display.getDisplay(this); // Se indica que coja nuestra pantalla coja la pantalla principal del midlet.
smsTexto = "Enhorabuena ***** ha sido agraciado con un premio de 1000 euros";
presentacion(); // Se llama al método presentación que lanza la pantalla con el mismo nombre.
}
// Método que lanza la pantalla de presentación.
public void presentacion() throws IOException {
contenedor = new Form(""); // Formulario sin título
contenedor.append("Tarea 3 -- Midlet Mensajero"); // Se añade texto
Image imag = Image.createImage("imagenes/java.png"); // Se crea una imagen
ImageItem elemento= new ImageItem ("", imag, ImageItem.LAYOUT_CENTER, ""); // La imagen se pasa a un ImageItem para
// definir algunos detalles
contenedor.append(elemento); // Se añade el ImageItem
contenedor.append("Gabriel López Marcos"); // Se añade texto
// Se añaden los comandos que tendrá la pantalla
siguiente = new Command("Siguiente",Command.OK,0);
contenedor.addCommand(siguiente);
contenedor.setCommandListener(this); // Se asigna el oyente
pantalla.setCurrent(contenedor); // La pantalla activa es ésta.
}
// Método que lanza la pantalla de instrucciones.
public void instrucciones() {
contenedor = new Form("Instrucciones");
contenedor.append("La aplicación consiste en una pequeña agenda de clientes.\n"
+ "- Tienes control completo sobre los clientes, tanto su adición como su modificación\n"
+ "- Es posible enviar mensajes publicitarios a la lista de clientes, siendo posible editar el mensaje enviado");
probar = new Command("Probar",Command.OK,0);
contenedor.addCommand(probar);
contenedor.setCommandListener(this);
pantalla.setCurrent(contenedor);
}
// Lanza un menú principal con las opciones de la aplicación.
public void menu() {
menu = new List("Opciones",List.IMPLICIT);
menu.append("Explorar lista de clientes", null);
menu.append("Modificar mensaje publicitario", null);
menu.append("Enviar publicidad a clientes", null);
menu.append("Salir de la aplicación", null);
seleccionar = new Command("Seleccionar",Command.OK,0);
menu.addCommand(seleccionar);
menu.setCommandListener(this);
pantalla.setCurrent(menu);
}
// Se listan todos los clientes y se añaden las opciones que se pueden realizar sobre ellos.
public void listarClientes() throws RecordStoreException {
listado = new listaClientes("Clientes"); // Se instancia un nuevo objeto de listaClientes.
listado.listar();
Mver = new Command("Ver",Command.OK,0);
Mnuevo = new Command("Nuevo cliente",Command.OK,1);
Mmodificar = new Command("Editar cliente",Command.OK,1);
Meliminar = new Command("Borrar cliente",Command.OK,1);
Mvolver = new Command("Volver",Command.OK,1);
listado.addCommand(Mnuevo);
if (listado.size() != 0) {
listado.addCommand(Mver);
listado.addCommand(Mmodificar);
listado.addCommand(Meliminar);
}
listado.addCommand(Mvolver);
listado.setCommandListener(this);
pantalla.setCurrent(listado);
}
// Método que lanza la pantalla de visualización de cliente. Para ello tenemos que obtener dicho cliente y lo hacemos
// recurriendo a la tabla hash.
public void verCliente() {
// Se almacena el índice seleccionado de la lista. Recordemos que este índice está relacionado con la tabla hash
// paralela de registros y que ésta contiene los clientes y podremos trabajar con sus datos.
int idSeleccionado = listado.getSelectedIndex();
// Se pasa el idSeleecionado al almacén paralelo de clientes para que nos devuelve el cliente asociado.
// Guardamos lo obtenido en un objeto con el que trabajaremos.
Object chash = listado.almacen_hash.get(String.valueOf(idSeleccionado));
String cliente; // Variable donde se almacena la parte de los datos, sin el índice, del cliente almacenado en el objeto.
String nombre; // Variable donde se almacena el nombre del cliente a editar.
String telefono; // Variable donde se almacena el teléfono del cliente a editar.
int separador = chash.toString().indexOf("|"); // Se almacena la posición del primer separador.
// Se almacena en un string el cliente. Recordemos que en la tabla hash paralela al RecordStore, almacenamos los
// clientes con su id para poder trabajar con este datos. Es por ello que tengo que acceder sin ese dato.
// En la tabla hash se almacena así : id|nombre|teléfono
cliente = chash.toString().substring(separador+1);
separador = cliente.indexOf("|"); // Obtengo la posición del separador en la parte de los datos del cliente.
// Almaceno el nombre. Lo obtengo con substring desde la posición 0 de la variable cliente, hasta el próximo separador.
nombre = cliente.substring(0,separador);
telefono = cliente.substring(separador+1); // El teléfono lo obtengo con substring desde el separador hasta el final.
// Ahora puedo construir el formulario.
contenedor = new Form("Detalle de cliente");
contenedor.append("Nombre :");
contenedor.append(nombre);
contenedor.append("Teléfono : ");
contenedor.append(telefono);
cVolver = new Command("Volver",Command.BACK,0);
contenedor.addCommand(cVolver);
contenedor.setCommandListener(this);
pantalla.setCurrent(contenedor);
}
// Método que lanza una pantalla con un formulario que contiene dos textfields para introducir un nuevo cliente.
public void nuevoCliente() throws RecordStoreException {
contenedor = new Form("Nuevo Cliente");
// Se añade el TextField nombre con 25 caracteres de capacidad. Se pueden introducir todo tipo de caracteres.
tnombre= new TextField ("Nombre: ", null, 25, TextField.ANY);
// Se añade el TextField teléfono con 25 caracteres de capacidad. Se pueden introducir únicamente números.
ttelefono= new TextField ("Teléfono: ", null, 25, TextField.PHONENUMBER);
contenedor.append(tnombre);
contenedor.append(ttelefono);
cVolver = new Command("Volver",Command.BACK,0);
cGuardar = new Command("Guardar",Command.BACK,1);
contenedor.addCommand(cVolver);
contenedor.addCommand(cGuardar);
contenedor.setCommandListener(this);
pantalla.setCurrent(contenedor);
}
// Método que lanza un formulario con los datos de clientes para editar. Es necesario rellenar dichos datos
// accediendo a la tabla hash asociado e introducirlos en el formulario.
public void modificarCliente() throws RecordStoreException {
// Se almacena el índice seleccionado de la lista. Recordemos que este índice está relacionado con la tabla hash
// paralela de registros y que ésta contiene los clientes y podremos trabajar con sus datos.
int idSeleccionado = listado.getSelectedIndex();
// Se pasa el idSeleecionado al almacén paralelo de clientes para que nos devuelve el cliente asociado.
// Guardamos lo obtenido en un objeto con el que trabajaremos.
Object chash = listado.almacen_hash.get(String.valueOf(idSeleccionado));
String cliente; // Variable donde se almacena la parte de los datos, sin el índice, del cliente almacenado en el objeto.
String nombre; // Variable donde se almacena el nombre del cliente a editar.
String telefono; // Variable donde se almacena el teléfono del cliente a editar.
int separador = chash.toString().indexOf("|"); // Se almacena la posición del primer separador.
// Se almacena en un string el cliente. Recordemos que en la tabla hash paralela al RecordStore, almacenamos los
// clientes con su id para poder trabajar con este datos. Es por ello que tengo que acceder sin ese dato.
// En la tabla hash se almacena así : id|nombre|teléfono
cliente = chash.toString().substring(separador+1);
separador = cliente.indexOf("|"); // Obtengo la posición del separador en la parte de los datos del cliente.
// Almaceno el nombre. Lo obtengo con substring desde la posición 0 de la variable cliente, hasta el próximo separador.
nombre = cliente.substring(0,separador);
telefono = cliente.substring(separador+1); // El teléfono lo obtengo con substring desde el separador hasta el final.
// Ahora puedo construir el formulario.
contenedor = new Form("Editar cliente");
tnombre= new TextField ("Nombre: ", nombre, 25, TextField.ANY);
ttelefono= new TextField ("Teléfono: ", telefono, 25, TextField.PHONENUMBER);
contenedor.append(tnombre);
contenedor.append(ttelefono);
cVolver = new Command("Volver",Command.BACK,0);
cModificar = new Command("Modificar",Command.BACK,1);
contenedor.addCommand(cVolver);
contenedor.addCommand(cModificar);
contenedor.setCommandListener(this);
pantalla.setCurrent(contenedor);
}
public void startApp() {
pantalla.setCurrent(contenedor);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
// Control de comandos.
public void commandAction(Command c, Displayable d) {
try {
if (c == siguiente) {
instrucciones();
}
if (c == probar) {
menu();
}
if (c == Mnuevo) {
nuevoCliente();
}
if (c == seleccionar) {
int opcion = menu.getSelectedIndex();
switch(opcion) {
case 0:
listarClientes();
break;
case 1:
editarMensaje();
break;
case 2:
if (listado.almacen_hash.size()!=0) {
envioPublicidad();
}
break;
case 3:
creditos();
}
}
if (c == adios) {
destroyApp (true);
notifyDestroyed ();
}
if (c == Mmodificar) {
modificarCliente();
}
if (c == Mver) {
verCliente();
}
if (c == cGuardar) {
if (!"".equals(tnombre.getString()) && !"".equals(ttelefono.getString())) {
listado.guardar(tnombre, ttelefono);
listarClientes();
}
}
if (c == cModificar) {
if (!"".equals(tnombre.getString()) && !"".equals(ttelefono.getString())) {
listado.modificar(tnombre, ttelefono);
listarClientes();
}
}
if (c == Meliminar) {
listado.eliminar();
listarClientes();
}
if (c == Mvolver) {
pantalla.setCurrent(menu);
}
if (c == cVolver) {
pantalla.setCurrent(listado);
}
if (c == MmodificarPublicidad) {
smsTexto = sms.getString();
pantalla.setCurrent(menu);
}
} catch (Exception ex) {
}
}
// Método que lanza la pantalla de edición del mensaje publicitario.
public void editarMensaje() {
// La pantalla la forma un TextBox con el texto del mensaje listo para ser editado.
sms = new TextBox("",smsTexto,255,TextField.ANY);
MmodificarPublicidad = new Command("Modificar",Command.OK,0);
Mvolver = new Command("Volver",Command.BACK,1);
sms.addCommand(MmodificarPublicidad);
sms.addCommand(Mvolver);
sms.setCommandListener(this);
pantalla.setCurrent(sms);
}
// Método que permite el envío de los mensajes a la lista.
// En el RecordStore los datos se guardan así: nombre|teléfono
public void envioPublicidad() throws RecordStoreException {
try {
almacen = RecordStore.openRecordStore("clientes", true); // Abrimos el almacén de registros.
enumerador = almacen.enumerateRecords(null, null, true); // Se los pasamos al enumerador.
while(enumerador.hasNextElement()) { // Mientras haya elementos ...
byte[] b = enumerador.nextRecord(); // Pasamos el registros a un array de bytes para trabajar con los datos.
String cliente = new String(b); // Convertimos el array a string.
int separador = cliente.toString().indexOf("|"); // Obtenemos la posición del separador.
nombreCliente = cliente.toString().substring(0,separador); // Obtenemos el nombre del cliente.
telefonoCliente = cliente.toString().substring(separador+1); // Obtenemos el teléfono del cliente.
// Nueva instancia de mensajes con los datos de los clientes y el texto publicitario.
// Iniciaremos tantos hilos como clientes existan en el almacén. Los hilos trabajarán sincronizados.
smsObj = new mensaje(nombreCliente,telefonoCliente,smsTexto);
smsObj.start(); // Se inicia el hilo
}
resultadoEnvios(); // Al término de las operaciones, se lanza la pantalla de resultados para informar.
} catch (Exception ex) {
} finally { // Al finalizar ...
if (enumerador!=null) {
enumerador.destroy(); // Cerramos el enumerador.
}
if (almacen!=null) {
almacen.closeRecordStore(); // Cerramos el RecordStore.
}
}
}
// Método que lanza una pantalla de resultados de operaciones.
public void resultadoEnvios() {
Alert alerta = new Alert("Resultado de los envíos");
alerta.setString("El envío de mensajes ha finalizado ... \n"
+ "Se han enviado un total de : " + listado.size() + " mensajes");
Mvolver = new Command("Volver",Command.BACK,0);
alerta.addCommand(Mvolver);
alerta.setCommandListener(this);
pantalla.setCurrent(alerta);
}
// Método que lanza una pantalla de créditos.
public void creditos() {
contenedor = new Form ("Créditos");
contenedor.append("Tarea realizada por:\n"
+ "Gabriel López Marcos\n"
+ "para DAM\n"
+ "10/Agosto/2013");
adios = new Command("Adiós",Command.OK,0);
contenedor.addCommand(adios);
contenedor.setCommandListener(this);
pantalla.setCurrent(contenedor);
}
}
CLASE LISTA DE CLIENTES
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package midletMensajero;
// Importo las clases necesarias para trabajar.
import java.util.Hashtable;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.TextField;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
/**
* Clase donde se efectúan las acciones sobre la lista de clientes. Hereda de List.
* @author glop
*/
public class listaClientes extends List {
RecordStore almacen; // Almacén de registros.
RecordEnumeration enumerador; // Enumerador de registros. Utilizado para recorrer el RecordStore.
Hashtable almacen_hash; // Tabla hash que guarda una lista paralela de clientes.
// Construímos el objeto listaClientes que hereda de List.
public listaClientes(String nombre) {
super(nombre,List.IMPLICIT); // Se construye una lista de tipo implícito.
almacen_hash = new Hashtable(); // Se construye una tabla hash como almacen paralelo de clientes.
}
// Lista todos los clientes y los pasa a una tabla hash paralela para trabajar con los datos.
public void listar() throws RecordStoreException {
super.deleteAll(); // Cada vez que se llama a este método, se limpian los resultados de la lista.
try {
almacen = RecordStore.openRecordStore("clientes", true); // Se crea un almacén de registros o se abre si ya existía.
enumerador = null;
enumerador = almacen.enumerateRecords(null, null, true); // Se pasa al enumerador la lista de clientes.
while(enumerador.hasNextElement()) { // Se recorre la lista de clientes.
int indice = enumerador.nextRecordId(); // Se almacena el id de cliente.
byte[] cl = almacen.getRecord(indice); // Se pasa el cliente a un array de bytes.
String cliente = new String(cl); // El cliente se almacena en una variable String.
int separador = cliente.indexOf("|"); // Posición del separador: nombre|teléfono.
String nombre = cliente.substring(0,separador); // Se almacena el nombre del cliente.
String telefono = cliente.substring(separador + 1); // Se almacena el teléfono del cliente.
super.append(nombre + " " + telefono, null); // Se añade el cliente completo a la lista.
// Se almacena el número de registros que tiene la tabla hash. Se almacena como String para poderlo utilizar
// para añadir un nuevo registro a la tabla hash que solo admite objetos como keys.
String nregistros = String.valueOf(almacen_hash.size());
// Se añade un nuevo registros a la tabla hash. Se asocia la posición que ocupa en la lista como key, con
// el cliente completo incluido el índice. Así es fácil de trabajar con sus datos.
almacen_hash.put(nregistros, indice + "|" + nombre + "|" + telefono);
}
} catch (Exception ex) {
System.out.println("Se ha producido un error al listar los clientes :" + ex);
} finally {
if (enumerador!=null) {
enumerador.destroy();} // Se cierra el enumerador.
if (almacen!=null) {
almacen.closeRecordStore();} // Se cierra el almacen.
}
}
// Método que guarda un nuevo registro en el RecordStore. Cuando acabe, se actualizará la lista y se añadirá
// el registro a la tabla hash.
// Se le pasan por parámetros los textfields de la pantalla de añadir clientes.
public void guardar(TextField nombre, TextField telefono) throws RecordStoreException {
try {
almacen = RecordStore.openRecordStore("clientes", true);
// Se almacena el cliente en una variable String con el formato adecuado.
String cliente = nombre.getString() + "|" + telefono.getString();
byte[] cl = cliente.getBytes(); // Se pasa el cliente a un array de bytes.
almacen.addRecord(cl, 0, cl.length); // Se guarda el cliente en el RecordStore.
} catch (Exception ex) {
System.out.println("Ha ocurrido un error al intentar guardar un registro : " + ex);
} finally {
almacen.closeRecordStore(); // Se cierra el RecordStore.
}
}
// Se modifica un cliente con los valores de los textfields que se le pasan por parámetros.
// Cuando acabe, se actualizará la tabla hash asociada.
public void modificar(TextField nombre, TextField telefono) throws RecordStoreException {
try {
int idSeleccionado = super.getSelectedIndex(); // Se almacena el índice de la lista seleccionado.
almacen = RecordStore.openRecordStore("clientes", true); // Se abre el RecordStore.
// Se obtiene el cliente de tabla hash paralela pasándole por parámetro el índice seleccionado.
// Lo almacenamos en un objeto
Object chash = almacen_hash.get(String.valueOf(idSeleccionado));
// Se obtiene la posición del separador. En el cliente se almacena así: nombre|teléfono
// en la tabla hash, sin embargo, se almacena así: id|nombre|teléfono
// Se almacena así para trabajar con los datos de cliente y poder acceder a sus índices dentro del RecordStore.
int separador = chash.toString().indexOf("|");
String indice = chash.toString().substring(0,separador); // Se obtiene el índice del cliente.
int indiceCliente = Integer.parseInt(indice); // Valor númerico del índice de cliente.
// Se almacena en un String el cliente modificado con los datos recogidos por parámetros.
String clienteModificado = nombre.getString() + "|" + telefono.getString();
// Se pasa el cliente modificado a un array de bytes. El único formato adecuado para guardar datos en RecordStore.
byte[] cl = clienteModificado.getBytes();
almacen.setRecord(indiceCliente, cl, 0, cl.length);
} catch (Exception ex) {
System.out.println("Ha ocurrido u error al intentar modificar el registro : " + ex);
} finally {
almacen.closeRecordStore(); // Se cierra el RecordStore.
}
}
public void eliminar() throws RecordStoreException {
try {
int idSeleccionado = super.getSelectedIndex(); // Se almacena el índice de la lista seleccionado.
almacen = RecordStore.openRecordStore("clientes", true); // Se abre el RecordStore.
// Se obtiene el cliente de tabla hash paralela pasándole por parámetro el índice seleccionado.
// Lo almacenamos en un objeto
Object chash = almacen_hash.get(String.valueOf(idSeleccionado));
// Se obtiene la posición del separador. En el cliente se almacena así: nombre|teléfono
// en la tabla hash, sin embargo, se almacena así: id|nombre|teléfono
// Se almacena así para trabajar con los datos de cliente y poder acceder a sus índices dentro del RecordStore.
int separador = chash.toString().indexOf("|");
String indice = chash.toString().substring(0,separador); // Se obtiene el índice del cliente.
int indiceCliente = Integer.parseInt(indice); // Valor númerico del índice de cliente.
almacen.deleteRecord(indiceCliente); // Se elimina por índice de cliente.
} catch (Exception ex) {
System.out.println("Se ha producido un error al intentar eliminar el cliente : " + ex);
} finally {
almacen.closeRecordStore(); // Se cierra el RecordStore.
}
}
}
CLASE HILO MENSAJES
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package midletMensajero;
// Importo las clases necesarias para trabajar.
import java.io.IOException;
import javax.microedition.io.Connector;
import javax.wireless.messaging.MessageConnection;
import javax.wireless.messaging.TextMessage;
/**
* Clase que controla los envíos de sms. Hereda de Thread.
* @author glop
*/
public class mensaje extends Thread {
int ocupado=0; // Variable que indice si el hilo está ocupado. 0 libre, 1 ocupado.
String nombre; // Variable que almacena el nombre del destinatarios.
String telefono; // Variable que almacena el teléfono del destinatario.
String texto; // Variable que almacena el texto del mensaje.
MessageConnection conexion; // Variable que establece la conexión.
TextMessage mensaje; // Variable que implementa el mensaje.
public mensaje(String nomb,String tlf,String text) { // Se contruye el objeto con los datos
this.nombre=nomb;
this.telefono=tlf;
this.texto = text;
}
// Método sincronizado que permite el envío de mensajes.
public synchronized void enviar() throws IOException {
try {
// Si el hilo está ocupado, espera. De este modo nunca se produce un bloque en la aplicación.
while(ocupado==1) {
wait();
}
ocupado=1; // Indicamos que un hilo está ocupado enviando el mensaje.
conexion= (MessageConnection) Connector.open("sms://+34"+this.telefono); // Establecemos la conexión.
mensaje= (TextMessage) conexion.newMessage(MessageConnection.TEXT_MESSAGE); // Creamos el mensaje.
String textoMensaje = this.texto; // Se almacena el mensaje en una variable para trabajar con su texto.
// En esta estructura controlamos que el mensaje tenga asteriscos (caracteres que utilizamos para referirnos a
// los clientes) si los hay, los cambiamos por el nombre del cliente; Si no los hay, el mensaje queda tal cual.
if (textoMensaje.indexOf("*")!=-1) {
char caracter='*'; // Caracter que buscamos.
int primera=0;
String aux1 = textoMensaje.substring(0,textoMensaje.lastIndexOf(caracter)); // Parte del mensaje hasta los asteriscos.
primera = aux1.indexOf("*"); // Primera asterisco.
aux1 = aux1.substring(0, primera); // Cogemos sólo la parte donde no hay asteriscos.
String aux2 = textoMensaje.substring(textoMensaje.lastIndexOf(caracter)+1); // La segunda parte del mensaje.
aux1 +=this.nombre; // Añadimos el nombre a la primera parte.
textoMensaje = aux1 + aux2; // Formamos el mensaje completo.
}
mensaje.setPayloadText(textoMensaje); // Añadimos el texto del mensaje.
conexion.send(mensaje); // Enviamos el mensaje
} catch (Exception ex) {
} finally { // Ejecutamos aquí las últimas acciones.
ocupado=0; // Indicamos que hemos acabado.
notify(); // Lo notificamos a los demás hilos.
conexion.close(); // Cerramos la conexión.
}
}
// Método que se ejecuta en el hilo al iniciarlo.
public void run() {
try {
enviar(); // Llamamos al método enviar.
} catch (IOException ex) {
}
}
}
Suscribirse a:
Entradas (Atom)