Introdução aos Objectos/Exercício 02: Energia

From Wiki**3

< Introdução aos Objectos
Revision as of 19:46, 20 September 2009 by Root (talk | contribs) (Programa Principal)

Problema

Numa casa de campo existem vários animais.

Alguns animais são domésticos: cães, gatos e pássaros (canários, etc.). Os donos acreditam em dar liberdade completa aos animais, o que causa alguns problemas de interacção nem sempre do agrado geral.

Outros animais, embora vivam na casa ou perto dela, não são oficialmente considerados animais domésticos: ratos, cobras, insectos, aranhas, etc. Estes animais também se deslocam pela propriedade, livre mas nem sempre impunemente.

Todos os animais podem correr (e os pássaros voar), consumindo energia para o efeito. Quando a energia termina, não podem correr mais e têm de dormir para recuperar forças.

Além do repouso, os cães e os gatos podem recuperar energia comendo ratos. Um rato devorado perde, claro está, toda a energia (é transferida para o predador). Os gatos, por serem ágeis, também conseguem comer pássaros (com efeitos muito semelhantes aos da relação gato-rato).

Por vezes, os cães perdem a paciência e atacam os gatos. Ambos perdem energia no processo.

Modele os conceitos "cão", "gato", "pássaro" e "rato". Além da energia, os cães e os gatos têm nome (uma cadeia de caracteres).

Considere que a energia disponível inicialmente para os cães, gatos, pássaros e ratos é, respectivamente, de 1000, 500, 20 e 50 unidades. Quando os animais correm, gastam, respectivamente, 50, 25, 5 e 2 unidades. Um pássaro, quando voa, gasta apenas 2 unidades. Um cão que ataque um gato gasta 100 unidades e faz com que o gato perca 25.

Para um predador comer uma presa tem de a perseguir para a capturar (podendo a perseguição ser ou não bem sucedida). Um cão consegue capturar um rato em cada 25 tentativas. Para os gatos, o rácio é 1 em 5 (ratos) e 1 em 10 (pássaros). A perseguição consome a mesma energia que correr (para cada interveniente), mas a presa recebe um bónus de 5 unidades se escapar. Se a presa estiver a dormir, é apanhada 1 em cada 2 tentativas.

Construa uma aplicação onde existem 2 cães ("Piloto" e "Átila"), 3 gatos ("Tareco", "Pantufa" e "Kitty"), 20 pássaros e 50 ratos (os pássaros e ratos podem ser organizados em arrays).

Neste cenário, os gatos correm, perseguem pássaros e ratos e são atacados pelos cães, que também podem correr e perseguir e comer ratos. Os animais dormem automaticamente se ficam sem energia (excepto quando são devorados: nesse caso devem ser considerados mortos).

Apresente o estado inicial dos animais (métodos toString) e o estado final (depois de algumas interacções).

(Pode utilizar parte do resultado do Exercício 01 na resolução deste exercicio.)

Solução

A solução apresentada procura manter-se simples e a um nível que ainda não implica utilizar abstracção de propriedade comuns, como por exemplo, a energia, ou de conceitos mais básicos (o de Animal, por exemplo). Estes aspectos, necessários numa boa definição de solução são objecto de estudo em fases mais adiantadas da exposição da matéria.

UML: Diagrama de Classes

Neste caso, como se escolheu (dada a fase introdutória) não representar os conceitos hierarquizados, apenas existem relações de dependência entre as classes (representadas pelas setas a tracejado).

File:PO-dog-cat-mouse-bird-energy.png

Conceito de Cão: Dog

<java5> public class Dog {

/** * We define the base energy as a constant, but it does not have to be this * way. It could be defined differently for each dog (but this requirement * does not exist in this case). */ private static final int BASE_ENERGY = 1000;

/** * The dog's name. */ private String _name;

/** * The dog's current energy value. */ private int _energy = BASE_ENERGY;

/** * @return dog's current energy level. */ private int getEnergy() { return _energy; }

/** * @return dog's name */ public String getName() { return _name; }

/** * Set the dog's name * * @param name * the dog's name */ public void setName(String name) { _name = name; }

/** * When a dog runs, the energy decreases by 50 units. This value could be * defined as an attribute or as a constant. * * @return whether the dog was able to run. */ public boolean run() { if (_energy < 50) return false; _energy -= 50; return true; }

/** * Call "run" to account for spent energy. * * @param mouse * the mouse to be chased. * @return whether the dog was able to catch the mouse. If the mouse * escapes, its energy increases. */ public boolean caughtMouse(Mouse mouse) { run(); mouse.run(); if (0 == (int) (25 * Math.random())) { return true; } mouse.escaped(); return false; }

/** * Eating is more or less like a vampire feeding... * * @param mouse * the mouse to eat. */ public void eatMouse(Mouse mouse) { if (caughtMouse(mouse)) _energy += mouse.drain(); }

/** * We assume that the dog is always able to attack the cat. The parameter to * attacked is used to specify the amount of energy lost by the cat. * Note that we are assuming that the degree of loss depends on the attacker * (hence the value being defined in the dog class). * * The energy values could be defined as attributes or as constants. * * @param cat * the cat the dog attacks */ public void attackCat(Cat cat) { _energy -= 100; cat.attacked(25); }

/** * Energy is recovered when sleeping. */ public void sleep() { _energy = BASE_ENERGY; }

/** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object o) { if (o instanceof Dog) { Dog dog = (Dog) o; return _name.equals(dog.getName()) && _energy == dog.getEnergy(); } return false; }

/** * @see java.lang.Object#toString() */ @Override public String toString() { return _name + " (dog) (" + _energy + ")"; } } </java5>

Conceito de Gato: Cat

<java5> public class Cat {

/** * We define the base energy as a constant, but it does not have to be this * way. It could be defined differently for each dog (but this requirement * does not exist in this case). */ private static final int BASE_ENERGY = 500;

/** * The cat's name. */ private String _name;

/** * The cat's current energy value. */ private int _energy = BASE_ENERGY;

/** * @return cat's current energy level. */ private int getEnergy() { return _energy; }

/** * @return cat's name */ public String getName() { return _name; }

/** * Set the cat's name * * @param name * the cat's name */ public void setName(String name) { _name = name; }

/** * When a cat runs, the energy decreases by 25 units. This value could be * defined as an attribute or as a constant. * * @return whether the cat was able to run. */ public boolean run() { if (_energy < 25) return false; _energy -= 25; return true; }

/** * Call "run" to account for spent energy. * * @param mouse * the mouse to be caught. * @return whether the cat was able to catch the mouse. If the mouse * escapes, its energy increases. */ public boolean caughtMouse(Mouse mouse) { run(); mouse.run(); if (0 == (int) (5 * Math.random())) { return true; } mouse.escaped(); return false; }

/** * Call "run" ("fly"??) to account for spent energy. * * @param bird * the bird to be caught. * @return whether the cat was able to catch the bird. If the bird escapes, * its energy increases. */ public boolean caughtBird(Bird bird) { run(); bird.fly(); // run?? if (0 == (int) (10 * Math.random())) { return true; } bird.escaped(); return false; }

/** * Eating is more or less like a vampire feeding... * * @param mouse * the mouse to eat. */ public void eatMouse(Mouse mouse) { if (caughtMouse(mouse)) _energy += mouse.drain(); }

/** * Eating is more or less like a vampire feeding... * * @param bird * the mouse to eat. */ public void eatBird(Bird bird) { if (caughtBird(bird)) _energy += bird.drain(); }

/** * We should probably check for large decrease values. Nevertheless, in this * case, for simplicity, we will let the energy go negative and, later on, * the cat can recover after a nap. * * @param energyDecrease */ public void attacked(int energyDecrease) { _energy -= energyDecrease; }

/** * Energy is recovered when sleeping. */ public void sleep() { _energy = BASE_ENERGY; }

/** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object o) { if (o instanceof Cat) { Cat cat = (Cat) o; return _name.equals(cat.getName()) && _energy == cat.getEnergy(); } return false; }

/** * @see java.lang.Object#toString() */ @Override public String toString() { return _name + " (cat) (" + _energy + ")"; } } </java5>

Conceito de Rato: Mouse

<java5> public class Mouse {

/** * We define the base energy as a constant, but it does not have to be this * way. It could be defined differently for each dog (but this requirement * does not exist in this case). */ private static final int BASE_ENERGY = 50;

/** * Tje mouse's current energy value. */ private int _energy = BASE_ENERGY;

/** * @return mouse's current energy level. */ private int getEnergy() { return _energy; }

/** * When a mouse runs, the energy decreases by 2 units. This value could be * defined as an attribute or as a constant. * * @return whether the mouse was able to run. */ public boolean run() { if (_energy < 2) return false; _energy -= 2; return true; }

/** * Energy goes up 5 points in a narrow escape. */ public void escaped() { _energy += 5; }

/** * @return the energy level in this mouse */ public int drain() { int energy = _energy; _energy = 0; return energy; }

/** * Energy is recovered when sleeping. */ public void sleep() { _energy = BASE_ENERGY; }

/** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object o) { if (o instanceof Mouse) { Mouse mouse = (Mouse) o; return _energy == mouse.getEnergy(); } return false; }

/** * @see java.lang.Object#toString() */ @Override public String toString() { return "mouse (" + _energy + ")"; } } </java5>

Conceito de Pássaro: Bird

<java5> public class Bird {

/** * We define the base energy as a constant, but it does not have to be this * way. It could be defined differently for each dog (but this requirement * does not exist in this case). */ private static final int BASE_ENERGY = 20;

/** * Bird's current energy value. */ private int _energy = BASE_ENERGY;

/** * @return mouse's current energy level. */ private int getEnergy() { return _energy; }

/** * When a bird runs, the energy decreases by 5 units. This value could be * defined as an attribute or as a constant. * * @return whether the bird was able to run. */ public boolean run() { if (_energy < 5) return false; _energy -= 5; return true; }

/** * When a bird flies, the energy decreases by 2 units. This value could be * defined as an attribute or as a constant. * * @return whether the bird was able to fly. */ public boolean fly() { if (_energy < 2) return false; _energy -= 2; return true; }

/** * Energy goes up 5 points in a narrow escape. */ public void escaped() { _energy += 5; }

/** * @return the energy level in this mouse */ public int drain() { int energy = _energy; _energy = 0; return energy; }

/** * Energy is recovered when sleeping. */ public void sleep() { _energy = BASE_ENERGY; }

/** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object o) { if (o instanceof Bird) { Bird bird = (Bird) o; return _energy == bird.getEnergy(); } return false; }

/** * @see java.lang.Object#toString() */ @Override public String toString() { return "bird (" + _energy + ")"; } } </java5>

Programa Principal

<java5> public class Application {

/** * The application scenario. * * @param args */ public static void main(String[] args) { Dog d1 = new Dog(); d1.setName("Piloto"); // could be passed to the constructor Dog d2 = new Dog(); d2.setName("Átila"); // could be passed to the constructor

Cat c1 = new Cat(); c1.setName("Tareco"); // could be passed to the constructor Cat c2 = new Cat(); c2.setName("Pantufa"); // could be passed to the constructor Cat c3 = new Cat(); c3.setName("Kitty"); // could be passed to the constructor

Bird[] birds = new Bird[20]; for (int ix = 0; ix < birds.length; ix++) birds[ix] = new Bird();

Mouse[] mice = new Mouse[50]; for (int ix = 0; ix < mice.length; ix++) mice[ix] = new Mouse();

// snapshot: present everything System.out.println("BEFORE"); System.out.println(d1.toString()); System.out.println(d2.toString()); System.out.println(c1.toString()); System.out.println(c2.toString()); System.out.println(c3.toString());

for (int ix = 0; ix < birds.length; ix++) System.out.println(birds[ix]);

for (int ix = 0; ix < mice.length; ix++) System.out.println(mice[ix]);

// run, chase, eat, sleep, etc.

for (int ix = 0; ix < birds.length; ix++) birds[ix].fly();

d1.run(); d2.attackCat(c1); c2.eatBird(birds[2]); c3.eatBird(birds[9]); c3.eatMouse(mice[0]); d2.eatMouse(mice[1]); mice[3].run();

// snapshot: present everything System.out.println("AFTER"); System.out.println(d1.toString()); System.out.println(d2.toString()); System.out.println(c1.toString()); System.out.println(c2.toString()); System.out.println(c3.toString());

for (int ix = 0; ix < birds.length; ix++) System.out.println(birds[ix]);

for (int ix = 0; ix < mice.length; ix++) System.out.println(mice[ix]);

}

} </java5>