(Java) Calling methods in constructor? - java

***I tried searching but I just can't understand what comes up. Sorry.
I am working on a server/client project for school. I am at my wit's end and I am about to give up. I do not have notes from class so I need some help. First I will post the directions I was given, then my current code, then my problem.
SERVER DIRECTIONS:
The Triangle class must have the following instance variables: side_a, side_b, side_c. Create a static variable to keep track of the number of Triangle objects created. Also create a static variable to hold the total of the perimeters of all Triangle objects created.
A three parameter constructor of the Triangle class should assign a trio of input values to the instance variables of the object. If not a valid triangle set all of the sides to 1. Create a separate private method called isValid(). The sum of any two sides of a triangle must be greater than the third in order to represent a valid triangle. No side may be 0 or negative. The constructor should also add 1 to the count and also call a method to calculate and then add the perimeter for that object to an accumulator.
The Triangle class must have the following methods as stated above:
public boolean is_right() public boolean is_isoc()
public boolean is_equil() public boolean is_scal()
public String toString() – returns the values for the 3 sides of the Triangle
You should also add a method to the Triangle class called calc_perim. This method will use the sides of the Triangle object to calculate the perimeter for that object.
addTotalPerim. This method will call calc_perim and add the perimeter for that object to an accumulator.
reduceTotalPerim. This method should subtract the perimeter for that object from the accumulator.
SERVER CODE:
public class Triangle {
private int side_a, side_b, side_c;
private static int count;
**//PROBLEM 1: Java tells me 'perim' is not used.**
private static int perim;
private boolean valid;
public Triangle(int s1, int s2, int s3)
{
side_a = s1; side_b = s2; side_c = s3;
**//PROBLEM 2: Java tells me 'v' is not used.**
boolean v = isValid();
if (v = false)
{side_a = 1; side_b = 1; side_c = 1;}
Triangle.count++;
calc_perim(s1,s2,s3);
addTotalPerim();
reduceTotalPerim();
}
private int calc_perim()
{
int perimeterCalc = side_a + side_b + side_c;
return perimeterCalc;
}
private void addTotalPerim()
{
Triangle.perim += calc_perim();
}
private void reduceTotalPerim()
{
Triangle.perim -= calc_perim();
}
private boolean isValid()
{
boolean valid1;
if (side_a < 1)
{ valid1 = false;}
else if (side_b < 1)
{ valid1 = false;}
else if (side_c < 1)
{ valid1 = false;}
else if ((side_a + side_b) < side_c || (side_a + side_b) == side_c)
{ valid1 = false;}
else
{ valid1 = true;}
return valid1;
}
public boolean is_right()
{
boolean right;
if (((side_a * side_a) + (side_b * side_b)) == (side_c * side_c))
right = true;
else
right = false;
return right;
}
public boolean is_isoc()
{
boolean isoc;
if (side_a == side_b)
isoc = true;
else if (side_a == side_c)
isoc = true;
else if (side_b == side_c)
isoc = true;
else
isoc = false;
return isoc;
}
public boolean is_equil()
{
boolean equil;
if (side_a == side_b && side_a == side_c)
equil = true;
else
equil = false;
return equil;
}
public boolean is_scal()
{
boolean scal;
if (side_a == side_b || side_a == side_c || side_b == side_c)
scal = false;
else
scal = true;
return scal;
}
public String toString()
{
return "Side 1: " + side_a + " Side 2: " + side_b + " Side 3: " + side_c;
}
}
Sorry about formatting but this site has a terrible way of formatting code, unless I'm misunderstanding something...
SERVER PROBLEMS:
What is the correct way to add/subtract the perimeter obtained via method calc_perim to varible perim? The directions say to call the calc_perim method in the constructor but I can't figure out how, so I just made it do its calculations on its own.
In the constructor, after calling method isValid(), why am I told by Java that variable 'v' is not used? Did I call isValid() incorrectly? >>>>> How do I call a method in the constructor? <<<<<
Other than that major issue, the server class works fine.

Suggestions:
Within Triangle class, initialize the static variables.
private static int count = 0;
private static int perim = 0;
Within Triangle constructor, change,
if (v = false)
to
if (v == false)
Change calc_perim as:
private void addTotalPerim()
{
perim += calc_perim();
}
private void reduceTotalPerim()
{
perim -= calc_perim();
}
Why you call reduceTotalPerim() after addTotalPerim(), didn't get this clear.
isValid function should check all combinations like a+b>c, b+c>a, c+a>b, if any one fails should be invalid

The "is not used" message from the Java compiler is technically a warning, not an error, so you could run your program even with the message still in effect if you really wanted to. But your instincts are correct- it's a bad idea to ignore those messages.
In this case, your code has a serious problem. You're calling v = false, which means that you're assigning a value of false to v. Change it to v == false. By using ==, you're doing a comparison, which is what you really want.

Related

How to write constructor that will accept 1 of 3 String values that I choose in the case (morning, evening, night)?

this is a subclass and am trying to shifts variable to accept only 1 of 3 values, that's morning evening night am a newbie so please forgive me for such a simple question
public class PartTimeStaffHire extends StaffHire
{
// instance variables - replace the example below with your own
private int workingHour
private double wagesPerHour
private String shifts;
private boolean terminated
This is subclass of StaffHire and accept all this variables and the last one am trying to accept only 1 of this 3 values
/**
* Constructor for objects of class PartTimeStaffHire
*/
public PartTimeStaffHire(int vacancy, String designation1, String typeofjob,
String staffName1, String joinDate, String qualification1, String appointed,
boolean joined, int hoursPerDay, double wagePerHour, String shift)
{
super(vacancy, designation1, typeofjob, staffName1, joinDate,
qualification1, appointed, joined);
workingHour = hoursPerDay;
wagesPerHour = wagePerHour;
shifts = shift;
if( shifts == "morning") {
shifts = "morning";
}
else if(shifts == "evening") {
shifts = "evening";
}
else if(shifts == "night") {
shifts = "night";
}
else {
System.out.println("Choose (morning, evening, night)" );
}
//(morning, evening, night)
}
public String shift()
{
if( shifts == "morning") {
shifts = "morning";
}
else if(shifts == "evening") {
shifts = "evening";
}
else if(shifts == "night") {
shifts = "night";
}
else {
System.out.println("Choose (morning, evening, night)" );
}
return shifts;
}
/**
* An example of a method - replace this comment with your own
*
* #param y a sample parameter for a method
* #return the sum of x and y
*/
public void print()
{
super.print();
System.out.println("The yearly salary is " + wagesPerHour);
System.out.println("Weekly working hours are " + workingHour;
System.out.println("##################" + shifts);
}
}
thanks in advance
If you know the possible values of a type, an enum is what you want to use.
So in this case you can create an enum Shift with the three possible constants:
public enum Shift {
MORNING,
EVENING,
NIGHT;
//this lets you convert a String such as `morning` to an enum constant
//if the enum not not one of the 3 constants (ignoring the case), this returns null. So you can use it to also validate the input.
public static Shift getShiftByName(String name) {
for(Shift s:values()) {
if(s.name().equalsIgnoreCase(name)) {
return s;
}
}
return null;
}
//if you want to convert it back to a String (for output), overwrite toString:
#Override
public String toString() {
//name() returns the constant's name as a String, such as "MORNING".
// since you use it as lowercase, overriding toString here makes sense
return name().toLowerCase();
}
}
You can then use it as
String strShiftInput = "morning";
Shift chosenChift = getShiftByName(strShiftInput);
if(chosenShift == null) {
//invalid input, handle accordingly
}
new PartTimeStaffHire(theOtherParameters, chosenShift);

Java Rock Paper Scissors - Everything Is a Tie

I am working on a project for an introductory CompSci course in java and I am stuck. We have to fill out the methods for a rock, paper, scissor game called stick, fire, water. I thought I filled it out correctly, but every time I run it, my program says it is a tie. It displays both my choice and the computer choice, but it says it is a tie and it doesn't increment the rounds played (or either my score or the computer's score, but since it is a tie that would not happen anyways, although I am sure it is still messed up).
/* This class ecapsulates the state and logic required to play the
Stick, Water, Fire game. The game is played between a user and the computer.
A user enters their choice, either S for stick, F for fire, W for water, and
the computer generates one of these choices at random- all equally likely.
The two choices are evaluated according to the rules of the game and the winner
is declared.
Rules of the game:
S beats W
W beats F
F beats S
no winner on a tie.
Each round is executed by the playRound method. In addition to generating the computer
choice and evaluating the two choices, this class also keeps track of the user and computer
scores, the number of wins, and the total number of rounds that have been played. In the case
of a tie, neither score is updated, but the number of rounds is incremented.
NOTE: Do not modify any of the code that is provided in the starter project. Additional instance variables and methods
are not required to make the program work correctly, but you may add them if you wish as long as
you fulfill the project requirements.
*/
public class StickWaterFireGame {
// TODO 1: Declare private instance variables here:
Random rand = new Random();
int numRounds = 0;
int playerScore = 0;
int computerScore = 0;
boolean playerWins = false;
boolean isTie = false;
/* This constructor assigns the member Random variable, rand, to
* a new, unseeded Random object.
* It also initializes the instance variables to their default values:
* rounds, player and computer scores will be 0, the playerWins and isTie
* variables should be set to false.
*/
public StickWaterFireGame() {
// TODO 2: Implement this method.
Random rand = new Random();
numRounds = 0;
playerScore = 0;
computerScore = 0;
playerWins = false;
isTie = false;
}
/* This constructor assigns the member Random variable, rand, to
* a new Random object using the seed passed in.
* It also initializes the instance variables to their default values:
* rounds, player and computer scores will be 0, the playerWins and isTie
* variables should be set to false.
*/
public StickWaterFireGame(int seed) {
// TODO 3: Implement this method.
Random rand = new Random(seed);
numRounds = 0;
playerScore = 0;
computerScore = 0;
playerWins = false;
isTie = false;
}
/* This method returns true if the inputStr passed in is
* either "S", "W", or "F", false otherwise.
* Note that the input can be upper or lower case.
*/
public boolean isValidInput(String inputStr) {
// TODO 4: Implement this method.
if (inputStr.equalsIgnoreCase("S") || inputStr.equalsIgnoreCase("W") || inputStr.equalsIgnoreCase("F")) {
return true;
}
else {
return false;
}
}
// Returns the choice of the computer for the most recent round of play
public String getComputerChoice(){
// TODO 5: Implement this method.
return getRandomChoice();
}
// Returns true if the player has won the last round, false otherwise.
public boolean playerWins(){
// TODO 6: Implement this method.
if (playerWins) {
return true;
}
else {
return false;
}
}
// Returns the player's cumulative score.
public int getPlayerScore(){
// TODO 7: Implement this method.
return playerScore;
}
// Returns the computer's cumulative score.
public int getComputerScore(){
// TODO 8: Implement this method.
return computerScore;
}
// Returns the total nuber of rounds played.
public int getNumRounds(){
// TODO 9: Implement this method.
return numRounds;
}
// Returns true if the player and computer have the same score on the last round, false otherwise.
public boolean isTie(){
// TODO 10: Implement this method.
if (computerScore == playerScore) {
return true;
}
else {
return false;
}
}
/* This "helper" method uses the instance variable of Random to generate an integer
* which it then maps to a String: "S", "W", "F", which is returned.
* This method is called by the playRound method.
*/
private String getRandomChoice() {
// TODO 11: Implement this method.
String randomChoice = "";
Random rand = new Random();
int randomInput = rand.nextInt(3) + 1;
if (randomInput == 1) {
randomChoice = "S";
}
if (randomInput == 2) {
randomChoice = "W";
}
if (randomInput == 3) {
randomChoice = "F";
}
return randomChoice;
}
/* This method carries out a single round of play of the SWF game.
* It calls the isValidInput method and the getRandomChoice method.
* It implements the rules of the game and updates the instance variables
* according to those rules.
*/
public void playRound(String playerChoice) {
// TODO 12: Implement this method.
int numRounds = 0;
int playerScore = 0;
int computerScore = 0;
boolean playerWins = false;
boolean isTie = false;
String computerChoice = getRandomChoice();
if (!isValidInput(playerChoice)) {
++computerScore;
++numRounds;
}
else {
if (computerChoice.equalsIgnoreCase(playerChoice)) {
++numRounds;
}
if (computerChoice.equals("S") && playerChoice.equalsIgnoreCase("W")) {
++computerScore;
++numRounds;
}
if (computerChoice.equals("S") && playerChoice.equalsIgnoreCase("F")) {
playerWins = true;
++playerScore;
++numRounds;
}
if (computerChoice.equals("W") && playerChoice.equalsIgnoreCase("S")) {
playerWins = true;
++playerScore;
++numRounds;
}
if (computerChoice.equals("W") && playerChoice.equalsIgnoreCase("F")) {
++computerScore;
++numRounds;
}
if (computerChoice.equals("F") && playerChoice.equalsIgnoreCase("S")) {
++computerScore;
++numRounds;
}
if (computerChoice.equals("F") && playerChoice.equalsIgnoreCase("W")) {
playerWins = true;
++playerScore;
++numRounds;
}
}
}
} ```
Look at this method. You are redelaring three variables when you set them to 0. I think you just want to assign them.
public void playRound(String playerChoice) {
// TODO 12: Implement this method.
int numRounds = 0;
int playerScore = 0;
int computerScore = 0;
boolean playerWins = false;
boolean isTie = false;
String computerChoice = getRandomChoice();
There are numerous suspicious things about your code, but the specific issues you describe are likely related to the fact that your playRound() method declares local variables shadowing most of the class's instance variables:
int numRounds = 0;
int playerScore = 0;
int computerScore = 0;
boolean playerWins = false;
boolean isTie = false;
That method manipulates those local variables rather than the like-named instance variables, and the effects can be seen only inside that method, for the duration of one execution of it. Just removing those local-variable declarations should move you forward.

Changing classic code to functional

I have the following portion of ugly (but working) code for checking if fields on a chessboard are vacant:
if (abs(xDst - xSrc) == abs(yDst - ySrc)) {
boolean backslashMove = xSrc < xDst && ySrc > yDst || xSrc > xDst && ySrc < yDst;
if (backslashMove) {
int y = max(ySrc, yDst) - 1;
for (int x = min(xSrc, xDst) + 1; x < max(xSrc, xDst); x++) {
if (board.getActiveChessmanAt(x, y).isAlive()) {
return false;
}
y--;
}
} else { //slash move
Obviously, it examines fields between coordinates (xScr, ySrc) and (xDst, yDst) in Bishop-like line of move.
I'm trying to transform this with using IntStream:
if (backslashMove) {
final int y = max(ySrc, yDst) - 1;
if (IntStream.range(min(xSrc, xDst) + 1, max(xSrc, xDst))
.anyMatch(x -> board.getActiveChessmanAt(x, y).isAlive()))
return false;
How can I perform y-- in this case? It has to be final if it's about to be used within 'anyMatch' command
If you really need to rewrite it using streams, then you can use the fact that both x and y are incremented simultaneously. So you can build a range of increments instead of the range of x-values:
final int xSrc = min(xSrc, xDst) + 1;
final int xDst = max(xSrc, xDst);
final int ySrc = max(ySrc, yDst) - 1;
if (IntStream.range(0, xDst - xSrc)
.anyMatch(distance -> board.getActiveChessmanAt(xSrc + distance, ySrc + distance).isAlive())) {
return false;
}
In general, it's not possible to use a non-final local variable from the "parent" method directly. Java doesn't support real closures. You would need a wrapper object for this (AtomicInteger is an often suggested candidate), or you could make the non-final variable a class field (note the potential thread safety problems). To me personally, these both "tricks" are bad.
What you need is not functional programming in terms of streams/folds.
Instead of, you should refactor your actual code to make it clearer/shorter/better.
You could for example :
extract the parts of logic scattered in the actual method in specific methods with meaningful names
use structured objects rather than too fine unitary variable
remove undesirable nesting : use early exit and not required conditional statements may help
It could give :
// -> extract method + structured objects
if (!isPointsMatch(pointSrc, pointDst)) {
return false; // -> early exit
}
// -> extract method + structured objects
if (isBackslashMove(pointSrc, pointDst)) {
if (board.hasAnyActiveChessmanAlive(pointSrc, pointDst)) {
return false;
}
}
// else slash move -> The else is useless
// ...
Your original code snipped is procedural. Your functional approach does not work well. So how about an object oriented approach?
class Position{
private final int x, y;
public Position(int x, int y){
this.x=x;
this.y=y;
}
public getX(){
return x;
}
public getY(){
return y;
}
}
interface Move {
Position moveFrom(Position start);
}
interface Figure {
Collection<Move> getPossibleMoves(Position start, Board board);
}
class Bishop implements Figure {
private final Collection<Move> moves = new HashSet<>();
public Bishop(){
moves.add(start->new Position(start.getX()-2,start.getY()-1));
moves.add(start->new Position(start.getX()-2,start.getY()+1));
moves.add(start->new Position(start.getX()+2,start.getY()-1));
moves.add(start->new Position(start.getX()+2,start.getY()+1));
moves.add(start->new Position(start.getX()-1,start.getY()-2));
moves.add(start->new Position(start.getX()-1,start.getY()+2));
moves.add(start->new Position(start.getX()+1,start.getY()-2));
moves.add(start->new Position(start.getX()+1,start.getY()+2));
}
#Override
public Collection<Move> getPossibleMoves(Position start, Board board){
return moves.stream()
.filter({ Position end = m.moveFrom(start);
return board.isOnBorad(end.getX(),end.getY())
&& board.getActiveChessmanAt(end.getX(), end.getY()).isAlive()})
.collect(Collectors.toSet());
}
}
Another implementation of Figure might return a separate Move instance for each step until it reaches a limit:
class Tower implements Figure {
enum Direction {
NORTH(1,0),EAST(0,1),SOUTH(-1,0),WEST(0,-1);
private final Position change;
private Direction(int x, int y){
change = new Position(x, y);
}
public Position getNextFrom(Position start){
return new Position(start.getX()+change.getX(),start.getX()+change.getY());
}
#Override
public Collection<Move> getPossibleMoves(Position start, Board board){
Collection<Move> moves = new HashSet<>();
for(Direction direction : Direction.values()){
Position current = direction.getNextFrom(start);
while( board.isOnBorad(current.getX(),current.getY())
&& board.getActiveChessmanAt(current.getX(), current.getY()).isAlive()){
moves.add(p-> new Position(current.getX(),current.getY());
}
}
return moves;
}
}

Helper Method won't work when called from other method, but will from main

I have a helper method that I am calling from another method in the same class. When I test it from main, it works fine. But as soon as I use it in the other class, it doesn't work at all. I cannot figure out what is wrong.
This is the helper method:
private boolean checkStack(Stack<String> stack,String check) {
System.out.println(stack);
System.out.println(check);
Stack<String> jump = new Stack<String>();
int count = 0;
String temp = "";
while (!stack.empty()) {
temp = stack.pop();
if (check == temp) {
count++;
}
jump.push(temp);
}
while (!jump.empty()) {
temp = jump.pop();
stack.push(temp);
}
System.out.println(count);
if (count != 0) {
return true;
} else {
return false;
}
}
I will test it from main like so:
pathSoFar.push("00");
pathSoFar.push("01");
pathSoFar.push("20");
pathSoFar.push("23");
System.out.println(pathSoFar);
String checkfor = "20";
System.out.println(test01.checkStack(pathSoFar,checkfor));
But it wont work when I call it from another method:
for (String n : possibleSpots) {
System.out.println();
String check = n;
if (!checkStack(pathSoFar, n)) {
pathSoFar.push(n);
String x = ""+n.charAt(0);
String y = ""+n.charAt(1);
int nextRow = Integer.parseInt(x);
int nextCol = Integer.parseInt(y);
System.out.println(nextRow + "" + nextCol + " = next move.");
if (findPath(wordToFind, pathSoFar, nextRow, nextCol)) {
return true;
}
} else{}
}
This is the method header if that helps:
private boolean findPath(String wordToFind, Stack<String> pathSoFar, int row, int col) {
possibleSpots can contain either String literals or String objects.
The problem lies in the following line
if (check == temp)
Change it to
if (check.equals(temp))
String matching is done with == which will work only for String literals.
That is the reason why it worked for you in one case and it does not work in another case.
To know the difference check the below link:
What is the difference between == vs equals() in Java?

trying to break out of for loop but keeps going back into it and performing recursive call

I just discovered the project euler website, I have done challenges 1 and 2 and have just started number 3 in java... here is my code so far:
import java.util.ArrayList;
public class IntegerFactorise {
private static int value = 13195;
private static ArrayList<Integer> primeFactors = new ArrayList<Integer>();
private static int maxPrime = 0;
/**
* Check whether a give number is prime or not
* return boolean
*/
public static boolean isPrimeNumber(double num) {
for(int i = 2; i < num; i++) {
if(num % i == 0) {
return false;
}
}
return true;
}
/*Multiply all of the prime factors in the list of prime factors*/
public static int multiplyPrimeFactors() {
int ans = 1;
for(Integer i : primeFactors) {
ans *= i;
}
return ans;
}
/*Find the maximum prime number in the list of prime numbers*/
public static void findMaxPrime() {
int max = 0;
for(Integer i : primeFactors) {
if(i > max) {
max = i;
}
}
maxPrime = max;;
}
/**
* Find all of the prime factors for a number given the first
* prime factor
*/
public static boolean findPrimeFactors(int num) {
for(int i = 2; i <= num; i++) {
if(isPrimeNumber(i) && num % i == 0 && i == num) {
//could not possibly go further
primeFactors.add(num);
break;
}
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
findPrimeFactors(num / i);
}
}
int sumOfPrimes = multiplyPrimeFactors();
if(sumOfPrimes == value) {
return true;
}
else {
return false;
}
}
/*start here*/
public static void main(String[] args) {
boolean found = false;
for(int i = 2; i < value; i++) {
if(isPrimeNumber(i) && value % i == 0) {
primeFactors.add(i);
found = findPrimeFactors(value / i);
if(found == true) {
findMaxPrime();
System.out.println(maxPrime);
break;
}
}
}
}
}
I am not using the large number they ask me to use yet, I am testing my code with some smaller numbers, with 13195 (their example) i get down to 29 in this bit of my code:
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
findPrimeFactors(num / i);
}
}
int sumOfPrimes = multiplyPrimeFactors();
if(sumOfPrimes == value) {
return true;
}
It gets to the break statement then finally the check and then the return statement.
I am expecting the program to go back to the main method after my return statement, but it jumps up to:
findPrimeFactors(num / i);
and tries to finish the iteration...I guess my understanding is a flawed here, could someone explain to me why it is behaving like this? I can't wait to finish it of :) I'll find a more efficient way of doing it after I know I can get this inefficient one working.
You are using recursion, which means that a function will call itself.
So, if we trace what your function calls are when you call return, we will have something like that:
IntegerFactorise.main()
|-> IntegerFactorise.findPrimeFactors(2639)
|-> IntegerFactorise.findPrimeFactors(377)
|-> IntegerFactorise.findPrimeFactors(29) -> return true;
So, when you return in the last findPrimeFactors(), you will only return from this call, not from all the stack of calls, and the execution of the previous findPrimeFactors() will continue just after the point where you called findPrimeFactors().
If you want to return from all the stack of calls, you have to modify your code to do something like that:
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
return findPrimeFactors(num / i);
}
So that when the last findPrimeFactors() returns, all the previous findPrimeFactors() which called it will return too.
I think the problem is that you are ignoring the return value from your recursive call to findPrimeFactors().
Let's walk through this. We start with the initial call to findPrimeFactors that happens in main. We then enter the for loop as it's the first thing in that method. Now let's say at some point we get into the else statement and thus recursively call frindPrimeFactors(num / i). This will suspend the looping, but as this recursive call starts to run you enter the for loop again (remember, the previous loop is merely paused and not finished looping yet). This time around you encounter the break, which allows this recursive call to finish out, returning true of false. When that happens you are now back to the original loop. At this point the original loop continues even if the recursive call returned true. So, you might try something like this:
if (findPrimeFactors(num / i))
return true;
I'm assuming that you need to continue looping if the recursive call returned false. If you should always finish looping upon return (whether true or false) then try this:
return findPrimeFactors(num / i);

Categories