How to compare two objects with random constructors - java

I made these 2 objects:
Fighter Lucas = new Fighter(Statistics.punchStrength,
Statistics.movementSpeed, Statistics.reflex);
Opponent Simon = new Opponent(Statistics.punchStrength2,
Statistics.movementSpeed2, Statistics.reflex2);
I want to make them "fight" by comparing their random variables, but I have no idea how to do this.

Make one class fighter and then 2 instances Fighter and Opponent ... I don't understand why you make 2 classes which are doing same job.

You Fighter class should have a method attack(Opponent)
class Figher{
// ..
public void attack(Opponent opponent){
int opponentMaxDamage = calculateHitpointsBy(opponent);
int damageByOpponent = opponent.defend(this, opponentMaxDamage);
this.lifePoints-=damageByOpponent;
}
public boolean isAlive(){
return 0< this.lifePoints;
}
// ..
}
and your Opponent class should have a method defend(Fighter)
class Opponent{
// ..
public void defend(Figher fighter, int maxAttackDamage){
int myDamage = reduceDamage(fighter,int maxAttackDamage);
int attackerDamage = calculateAttackerDamage(fighter);
this.lifePoints-=myDamage ;
}
public boolean isAlive(){
return 0< this.lifePoints;
}
// ..
}
This gives you the possibility to add more complex calculations for the life points later. Eg.: the actual damage an attacker can do to the opponent may depend on the equipment she wears. The same may be true for the damage the opponent receives.
The method isAlive() could be extracted to a common base class...
You use it this way:
Fighter Lucas = new Fighter(Statistics.punchStrength, Statistics.movementSpeed, Statistics.reflex);
Opponent Simon = new Opponent(Statistics.punchStrength2, Statistics.movementSpeed2, Statistics.reflex2);
// fight
while(Lucas.isAlive()&&Simon.isAlive())
Lucas.attack(Simon);
// report winner
if(Lucas.isAlive())
System.out.println("winner is Lucas");
if(Simon.isAlive())
System.out.println("winner is Simon");

Use getter and setter methods in both of the classes i.e Fighter and Opponent
Then
Your Fighter class looks like this
class Fighter{
private int punchStrength, movementSpeed, reflex;
public int getPunchStrength() {
return punchStrength;
}
public void setPunchStrength(int punchStrength) {
this.punchStrength = punchStrength;
}
public int getMovementSpeed() {
return movementSpeed;
}
public void setMovementSpeed(int movementSpeed) {
this.movementSpeed = movementSpeed;
}
public int getReflex() {
return reflex;
}
public void setReflex(int reflex) {
this.reflex = reflex;
}
public Fighter(int punchStrength, int movementSpeed, int reflex) {
this.punchStrength = punchStrength;
this.movementSpeed = movementSpeed;
this.reflex = reflex;
}
}
Your Opponent class look like this
class Opponent{
private int punchStrength, movementSpeed, reflex;
public int getPunchStrength() {
return punchStrength;
}
public void setPunchStrength(int punchStrength) {
this.punchStrength = punchStrength;
}
public int getMovementSpeed() {
return movementSpeed;
}
public void setMovementSpeed(int movementSpeed) {
this.movementSpeed = movementSpeed;
}
public int getReflex() {
return reflex;
}
public void setReflex(int reflex) {
this.reflex = reflex;
}
public Opponent(int punchStrength, int movementSpeed, int reflex) {
this.punchStrength = punchStrength;
this.movementSpeed = movementSpeed;
this.reflex = reflex;
}
}
Now in your main class :
Fighter Lucas = new Fighter (Statistics.punchStrength,
Statistics.movementSpeed, Statistics.reflex);
Opponent Simon = new Opponent (Statistics.punchStrength2,
Statistics.movementSpeed2, Statistics.reflex2);
int avgFighter = ((Lucas.getpunchStrength())+(Lucas.getmovementSpeed())+(Lucas.getreflex()))/3;
int avgOpponent = ((Opponent .getpunchStrength())+(Opponent .getmovementSpeed())+(Opponent .getreflex()))/3;
if(avgFighter > avgOpponent )
System.out.println("Fighter wins");
else if(avgFighter == avgOpponent)
System.out.println("Draw");
else
System.out.println("Fighter looses");

Short version
Make one class - Fighter - which has fight(Fighter otherFighter) method. In that method, resolve the fight, so that the fight() logic and Fighter implementation does not leak outside the class. For an example, see below.
Long version
What I would do is abandon idea of having Opponent and Fighter classes if they're doing the same thing and have the same fields. Instead, why not have one Fighter class? The way I understand, the only difference between your objects is that they have different values - and that does not necessarily mean that you need to belong to different classes. Hence, unless Fighter can fight some other entities that have vastly different properties, one class should be enough. Besides, you can always extend the class if you need more fields or/and methods that behave slightly differently.
Now, determining who would win the fight is a rather interesting problem because you can do it in many ways, some more maintainable than others. On the one hand, you could calculate the outcome outside the classes. However, I do not think that this is the best approach. First of all, this means you need to know quite a lot about the Fighter, and how the fights work. Imagine if someone else worked with your code and wanted to resolve a fight. Would he/she be able to do it easily, or would he/she have to consult with you?
In my opinion, the logic should not leak to the outside, as this will make your code harder to maintain in the long run. E.g., what if attributes change? What if you want to resolve fights in multiple places of your code? Are you going to create a class whose sole purpose is to resolve a fight? Seems a bit strange. Or, worse yet, are you going to copy-paste the code? If so, what will you do if you need to change the logic of an outcome? Are you sure you can adjust all code you've copy-pasted? These are the questions you should be actively thinking about.
What I immediately think when I see a class named Fighter is that the entity represented, well, fights. Wouldn't it be nice if it could resolve the fights itself? Wouldn't it be logical place to put the code? Hence, my solution would be something like this:
public class Fighter {
private int speed;
private int reflex;
private int strength;
public Fighter(int speed, int reflex, int strength) {
this.speed = speed;
this.reflex = reflex;
this.strength = strength;
}
public String fight(Fighter otherFighter) {
int thisSum = speed + reflex + strength;
int thatSum = otherFighter.speed + otherFighter.reflex + otherFighter.strength;
int outcome = thisSum - thatSum;
if (outcome == 0) {
return "Draw";
} else if (outcome > 0) {
return "First fighter won";
} else {
return "Second fighter won";
}
}
}
Notice the fight() method. You pass another Fighter instance into it and without any effort the fight is resolved. The only caveat is that you need a way to figure out to determine which attributes are 'higher' and calculate the overall outcome. There are many ways to do it, of course. I used ints for clarity and ease of use. But you could use anything you like, or implement any logic you want. In any case, now you can resolve the fight with one method call. Hence, the whole code outside the class looks something like this:
public class Main {
public static void main(String[] args) {
Fighter fighter = new Fighter(1, 2, 3);
Fighter opponent = new Fighter(4, 2, 1);
System.out.println(fighter.fight(opponent));
}
}
Naturally, fight() could be extended to contain much more complex logic. Or it could be changed to accept some common base class of opponents, monsters, or fighters, which would allow you not only to fight Fighter's, but also other entities, too. Nevertheless, one thing I would try to achieve is to have as little logic about the fight as possible outside the Fighter class, so as to not have to change code in multiple places if I change my mind about how the fights work.
By the way, I have not used getters and setters, but it would probably be a good idea if getting an attribute involves some kind of logic.

Related

Can we use Setter Method in java to perform operations?

Is setter method only use to assigning values? or can we perform operations in it. Here in this code the commented part is giving me correct output but while using set and get I am getting output as 0.
I want to avoid calling totalMarksOfStudent() method again and again because it have 5 parameters which I dont want to give again and again. So what is the way to return totalMarksStudent in another class without calling totalMarksOfStudent().
int totalMarksStudent = 0;
public void setMarks(int englishMarks, int mathsMarks, int physicsMarks, int chemistryMarks, int csMarks) {
totalMarksStudent = englishMarks + mathsMarks + physicsMarks + chemistryMarks + csMarks;
}
public int getMarks(){
return totalMarksStudent;
}
// public int totalMarksOfStudent(int englishMarks, int mathsMarks, int physicsMarks, int chemistryMarks, int csMarks) {
// totalMarksStudent = englishMarks + mathsMarks + physicsMarks + chemistryMarks + csMarks;
// return totalMarksStudent;
}
public String displayTotalMarks() {
String totalMarks1 = "Name " + name + "\tRoll No " + rollNo + "\tTotal Marks " + getMarks();//totalMarksOfStudent(englishMarks, mathsMarks, physicsMarks, chemistryMarks, csMarks);
return totalMarks1;
}
Better to avoid that...
I think it's better to have some fields like your parameters in setMarks (englishMarks , mathsMarks , ...) , and give value to them in constructor or setter methods. Also it's better to have a method named something like calculateTotalMarks , and call it without any parameters whenever you need it. Remember that there will be no problem to have operations in setter methods but usually and for better designed program we avoid that. Methods should do the thing their name says : for example , setter just for assigning , getter just for accessing values , calculateTotalMarks for calculating the total marks and so on ...
setter method is usually used to assigning values. It is promise.
You can reduce parameters by using Object
I recommend to make object of MarksStudent. because common attribute can bind to one class. It make understand easily code
for example
// Java is object-oriented language
class marksStudents {
private int english;
private int math;
private int physics;
private int chemistry;
private int cs;
//getMethods is Abbreviation
public int getTotal() {
return english+math+physics+chemistry+cs;
}
//setMethods
public void setEnglish(int english) {
this.english = english;
}
public void setMath(int math) {
this.math = math;
}
public void setPhysics(int physics) {
this.physics = physics;
}
public void setChemistry(int chemistry) {
this.chemistry = chemistry;
}
public void setCs(int cs) {
this.cs = cs;
}
}
To execute
public class Main{
public static void main(String[] args) {
// You can make object marksStudents of studentsA
marksStudents studentsA = new marksStudents();
studentsA.setChemistry(20);
studentsA.setEnglish(30);
studentsA.setMath(40);
studentsA.setCs(50);
studentsA.setPhysics(60);
//200
System.out.println(studentsA.getTotal());
// You can make object marksStudents of studentsB too
marksStudents studentsB = new marksStudents();
studentsB.setChemistry(10);
studentsB.setEnglish(10);
studentsB.setMath(10);
studentsB.setCs(10);
studentsB.setPhysics(10);
//50
System.out.println(studentsB.getTotal());
}
}
The getter/setter method is only a practice. Not bad practice - it just defines a class, whose instances for the external world are handled by a list of independent values. Using them makes your code better comprehensible and easy to understand, what is it doing.
So it is no problem to make other operations with it, in general.
Some frameworks like to use reflection to use getters/setters and also reach the variables directly in them. In these cases, doing any different in the getters/setters than reading/writing the private members is no wise idea. Sometimes you can use a little bit of api/impl interface trickery to handle this problem.

Trying to use a variable from another class

public class Boss{
public void Attack1(){
int randomspace = (int )(Math.random() * 3 + 1);
System.out.println("Attacking space " + randomspace);
if(space == randomspace){
//Something right here to kill the player
}
}
}
But space is in a different class called Player
public class Player {
int space = 1;
}
I thought about making a separate space variable and change them at the same time, but how would the Boss class know when to increment/decrement at the same time as the Player class. it would be easier to just keep it in the one class for simplicity.
EDIT: I figured it out. public class Boss extends Player{ and that fixed my problem
Use parameters. (and lowercase your methods)
A boss will attack a space.
public void attack(int space){
if(space == randomspace){
//Something right here to kill the player
}
If you need the Player, then you should really be using some abstract class, say Unit, then use Hero to be the main piece.
Then you can have
public void attack(Unit unit){
if(unit.getSpace() == randomspace){
//Something right here to kill the player
}
And ideally unit.getSpace() could also come from some Board class that holds all information about the Unit types
Then, your logic elsewhere says boss.attack(player) or boss.attack(player.getSpace())

Basics of manipulating variables in different classes

I've done quite a bit of digging and can't seem to find the answer I'm looking for, I may be asking the question wrong because I'm pretty nooby.
Anyway I'm trying to build a simple Pokemon style game for practice and I can't seem to get the opponent or player hit points to change during the combat event..
I have it so you select 1. to attack with the following code:
if(select == 1){
System.out.println("You strike at the raccoon!");
System.out.println("You deal " + play1.atk + " damage!");
Math.subtract(raccoon1.hp, play1.atk);
the Math.subtract class is just
public static int subtract(int x, int y){
return (x-y);
}
Where it pulls raccoon1.hp from an object I built from an 'Opponent' class that just has:
public class Opponent {
public int hp = 5;
public int def = 0;
public int atk = 1;
}
The player is set up the same way.
I'm sure I'm just missing and/or doing something dumb but any help to a new programmer would be greatly appreciated.
Thanks!
Racoon1.hp = Math.subtract(raccoon1.hp, play1.atk)
You have to set the returned value equal to raccoon.hp, or else there's no point in returning a value.
This is a question of proper object-oriented programming. Instead of thinking about it in terms of variables, think about it in terms of methods. Don't try to manipulate the variable directly, try to manipulate it through operations done by the class.
In your case...
if(select == 1){
System.out.println("You strike at the raccoon!");
System.out.println("You deal " + play1.atk + " damage!");
//reduce the health by the current attack value of the player
racoon.reduceHealth(play1.getAttackValue());
In your Pokemon class, or whatever you named the class that you instantiate an instance of when creating a new Pokemon, create a method like this...
public void reduceHealth(int attackValue){
this.hp = this.hp - attackValue;
}
In your Player class, or whatever you named that class that you instantiate an instance of when creating a new Player, create a method like this...
public int getAttackValue(){
return this.atk;
}
This way, operations done on your objects are done so by its own class, not other classes. When getting information, create methods that return the information you want. When manipulating a variable of an object, use methods of the object to do the manipulation.
I suggestions you todo somethings like that
public class Opponent {
public int hp = 5;
public int def = 0;
public int atk = 1;
public void attack(Opponent target){
target.hp -= atk;
}
}
After you can simply do
Opponent player = new Opponent ();
Opponent badGuy = new Opponent ();
player.attack(badGuy);

How can I use the parent class to get a parameter from child class?

I have this child class AggressiveAlien and here is one method inside it
public boolean attack()
{
boolean attack;
if (currentLocation == this.AggresiveAlien.getCurrentLocation)
{
energyCanister = (int) ( (1/2) * alien2.energyCanister + energyCanister);
lifePoints = (int) (lifePoints - (1/2)*alien2.energyCanister);
attack = true;
}
return attack;
}
I would like the returned value to be used in the parent class Alien
public void gotAttacked()
{
if (AggresiveAlien.attack())
energyCanister = energyCanister/2;
}
But it seems to be giving errors on the AggresiveAlien.attack() part. Is there any way for me to use this returned value from AggresiveAlien to be used in Alien?
Help would be very much appreciated. Thanks!
Here is another part of the child class
public class AggressiveAlien extends Alien
{
public AggressiveAlien(XYCoordination currentLocation, int energyCanister)
{
super(currentLocation, energyCanister);
}
public int collectCanister(NormalPlanet canister)
{
super.collectCanister();
n=1;
}
I think you might be having two problems... First you need to cast the base type to the child type, such as
((AggressiveAlien)this).attack()
Also, 1/2 may actually be 0! 1 and 2 are interpreted as integers which means the value of any division is floored! so 1/2 = (int) 0.5 = 0
check your types! You better use 0.5 or use /2.0 to force the value to compute as a float or double (depending on the platform).
Hope this helped!
It looks as though you're trying to use AggresiveAlien statically. Instead you probably want to do:
if ((AggresiveAlien)this.attack()) energyCanister = energyCanister/2;
But I can't be sure given the limited amount of information.
you say, you have a parent and child class, which means you are using inheritance here. you can easily accomplish your task by using virtual function and then overriding in the child class.
in your Alien class create a function called attack() and override in the child class AggresiveAlien.
like following:
Alien class:
public boolean attack()
{
return false;
}
AggresiveAlien class:
public boolean attack()
{
return true;
}
and your gotAttacked function
public void gotAttacked()
{
if (this.attack())
energyCanister = energyCanister/2;
}

Need help extrapolating Java code

If anyone familiar with Rebecca Wirfs-Brock, she has a piece of Java code found in her book titled, Object Design: Roles, Responsibilities, and Collaborations.
Here is the quote >Applying Double Dispatch to a Specific Problem
To implement the game Rock, Paper, Scissors we need to write code that determines whether
one object “beats” another. The game has nine possible outcomes based on the three kinds of
objects. The number of interactions is the cross product of the kinds of objects. Case or switch statements are often governed by the type of data that is being operated on. The
object-oriented language equivalent is to base its actions on the class of some other object. In Java,
it looks like this
Here is the piece of Java code on page 16 '
import java.util.*;
import java.lang.*;
public class Rock
{
public static void main(String args[])
{
}
public static boolean beats(GameObject object)
{
if (object.getClass.getName().equals("Rock"))
{
result = false;
}
else if (object.getClass.getName().equals("Paper"))
{
result = false;
}
else if(object.getClass.getName().equals("Scissors"))
{
result = true;
}
return result;
}
}'
===>This is not a very good solution. First, the receiver needs to know too much about the argument.
Second, there is one of these nested conditional statements in each of the three classes. If new
kinds of objects could be added to the game, each of the three classes would have to be modified.
Can anyone share with me how to get this "less than optimal" piece of code to work in order to see it 'working'. She proceeds to demonstrate a better way, but I will spare you.
Thanks
I would start by defining classes RPSSystem and RPSObject. The code to construct the classic RPS-game would look like this:
RPSObject rock = new RPSObject("Rock");
RPSObject paper = new RPSObject("Paper");
RPSObject scissors = new RPSObject("Scissors");
RPSSystem classicRPS = new RPSSystem(rock, paper, scissors);
// new RPSSystem(Collection<RPSObject> objects) possible too
classicRPS.defineBeatsRule(rock, scissors);
classicRPS.defineBeatsRule(paper, rock);
classicRPS.defineBeatsRule(scissors, paper);
RPSSystem would have a method
int fight(RPSObject a, RPSObject b)
which would return -1 when a wins, 1 when b wins and 0 when the result is not defined. Internally RPSObjects could be stored in a list and beating rules could be stored in a matrix (columns and rows would match the indices of the objects in the list). If multiple instances of similar RPSObject should be allowed, the equals-method of RPSObject should be written accordingly.
Having a separate class for each object in the system seems a bit too complicated.
EDIT:
Complete classes:
package rpsgame;
public final class RPSObject {
private final String name;
public RPSObject(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String toString() {
return getName();
}
}
package rpsgame;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public final class RPSSystem {
private final List<RPSObject> objects;
private final int[][] beatsRules;
public static final int WINS = 1;
public static final int TIE = 0;
public static final int LOSES = -1;
public RPSSystem(RPSObject... objects) {
this.objects = Arrays.asList(objects.clone());
this.beatsRules = new int[objects.length][objects.length];
}
void defineBeatsRule(RPSObject winner, RPSObject loser) {
if (winner.equals(loser)) throw new IllegalArgumentException();
int winnerIndex = getObjectIndex(winner);
int loserIndex = getObjectIndex(loser);
beatsRules[winnerIndex][loserIndex] = WINS;
beatsRules[loserIndex][winnerIndex] = LOSES;
}
public int fight(RPSObject a, RPSObject b) {
int aIndex = getObjectIndex(a);
int bIndex = getObjectIndex(b);
return beatsRules[aIndex][bIndex];
}
public List<RPSObject> getObjects() {
return Collections.unmodifiableList(objects);
}
private int getObjectIndex(RPSObject o) {
int index = objects.indexOf(o);
if (index < 0) throw new IllegalArgumentException();
return index;
}
// test
public static void main(String[] args) {
RPSSystem classicRPS = buildClassicRPS();
List<RPSObject> objects = classicRPS.getObjects();
for (RPSObject a: objects) {
for (RPSObject b: objects) {
int result = classicRPS.fight(a, b);
switch (result) {
case RPSSystem.WINS:
System.out.println(a + " beats " + b);
break;
case RPSSystem.TIE:
System.out.println(a + " vs " + b + " is tied");
break;
case RPSSystem.LOSES:
System.out.println(a + " loses against " + b);
break;
}
}
}
}
private static RPSSystem buildClassicRPS() {
RPSObject rock = new RPSObject("Rock");
RPSObject paper = new RPSObject("Paper");
RPSObject scissors = new RPSObject("Scissors");
RPSSystem classicRPS = new RPSSystem(rock, paper, scissors);
classicRPS.defineBeatsRule(rock, scissors);
classicRPS.defineBeatsRule(paper, rock);
classicRPS.defineBeatsRule(scissors, paper);
return classicRPS;
}
}
Just add RPSSystem.EVERYONE_DIES and defineEveryoneDiesRule(...) and you're ready for
rps.add(atombomb);
rps.defineBeatsRule(atombomb, scissors);
rps.defineBeatsRule(atombomb, rock);
rps.defineBeatsRule(atombomb, paper);
rps.defineEveryoneDiesRule(atombomb, atombomb);
Use an enum for dealing with it (RPSObj) that has a beats(RPSObj o) method, with each enum element having a Set passed in, stored as beatset. Then, the beats(RPSObj o) method can do return beatset.contains(o);. Simples :)
Edit: You can actually use an EnumSet as the Set implementation, which should be even more efficient than other set implementations :)
You might want to take a look at this thread:
Using inheritance and polymorphism to solve a common game problem
It seems to be around the same subject.
I think personally I would simply have a utility-like class that would contain the 'beats' method. The 'beats' method would take two GameObject objects as parameters.
That way I could just pass in the two objects (rock, paper or scissors) and perform the necessary logic. Now if you add a new object, you don't change anything other than the 'beats' method within the utility class keeping things encapsulated from your main.
ryan's link is nice, it contains several other ideas for handling this situation as well.
So here's how I fixed it. I first made a new interface called GameObject since they refer to it!
public interface GameObject
{
public boolean beats(GameObject g);
}
The type didn't exist so referring to it wasn't going to work so great.
Here's my new code for Rock with comments on changes:
import java.util.*;
import java.lang.*;
public class Rock implements GameObject //Need to be an instance of GameObject somehow!
{
public static void main(String args[])
{
}
public boolean beats(GameObject object) //This isn't static anymore
{
boolean result = false; //Need to declare and initialize result
if (((Object)object).getClass().getName().equals("Rock")) //getClass should have ()
{
result = false;
}
else if (object.getClass().getName().equals("Paper")) //getClass should have ()
{
result = false;
}
else if(object.getClass().getName().equals("Scissors")) //getClass should have ()
{
result = true;
}
return result;
}
}
EDIT: You seemed to be asking for how to fix the code and not the better way to do it. I believe this should be good to go for you now.

Categories

Resources