I'm attempting to create a method called "runExperiments()
the first step in the loop is to decrement a variable called "powerLevel" by a random number between 1 and 3 which is I have created a second method for which works.
the next step which is where I am having problem is if the "powerLevel" can be reduced then I need a message containing the experiment number (starting at 1) should displayed, if not then a different message should be displayed and the remaining experiments should not be attempted.
Then finally when all expierements have finished I need to display "Experiment run stopped" But I know how to do this section.
I have posted all the code below. The method is at the bottom. I have made a first attempt but I cannot seem to figure out the part in the bold. Any help or guidance would be fantastic. I'm not sure if I have used the correct type of loop either so that may be wrong as well.
public class SpaceRocket
{
private String name;
private int maxPowerLevel;
private int numberOfExperiments;
private int powerLevel;
private int decreasePowerLevel;
/**
* returns maxPowerLevel
*/
public int getMaxPowerLevel()
{
return this.maxPowerLevel;
}
/**
* returns numberOfExperiments
*/
public int getNumberofExperiments()
{
return this.numberOfExperiments;
}
/**
* returns powerLevel
*/
public int getPowerLevel()
{
return this.powerLevel;
}
/**
*
* Causes execution to pause by time number of milliseconds
*
*/
public void delay(int time)
{
try
{
Thread.sleep(time);
}
catch (Exception e)
{
System.out.println(e);
}
}
/**
*
* return a random integer between 1 and 3 inclusive
*/
public int randomInteger()
{
java.util.Random r = new java.util.Random();
return r.nextInt(3) + 1;
}
public SpaceRocket(String aName, int aNumberOfExperiments)
{
this.name = aName;
this.numberOfExperiments = aNumberOfExperiments;
this.powerLevel = 0;
this.maxPowerLevel = 15;
}
public boolean decrementPower(int adecreasePowerLevel)
{
this.decreasePowerLevel = adecreasePowerLevel;
if(decreasePowerLevel > this.powerLevel)
{
this.powerLevel = 0;
return true;
}
else
{
this.powerLevel =(this.powerLevel - this.decreasePowerLevel);
return false;
}
}
public runExperiments()
{
for(this.powerLevel =(this.powerLevel - randomIntegar())
{
if(this.powerLevel
}
}
If I understand your question correctly, every time the loop runs, you want to decrease "powerlevel" by a random value, then display a message depending on whether powerlevel can be reduced.
Here are two approaches.
1) use an if statement in your for loop
for (conditions){
if(powerlevel cannot be decremented){
//display a messsage
break;
}
// display a message
}
conditions could be iterating through all the experiments
2) use a while loop which checks whether powerlevel can be reduced in every loop
while(powerlevel can be decreased){
//display a message containing the experiment number (starting at 1)
}
//display a different message
Related
I have two classes called Ticket and Register. Register is a class that takes in a ticket array. A ticket contains a time and a string with its Ticket ID. One of the methods in my Register Class is called contains() and it returns a Boolean. It checks whether the register contains a ticket with that ID. My problem is that it only shows true for the first ticket element and false for all the others even if it contains the ticket, therefore I believe the problem is with my contains() function. I am very knew to Java so if someone could help me it would be greatly appreciated. Here is my code for Register and my driver code.
/
// This is class called Register that has the methods:"add()","contains()","retrieve()" and the constructor "Register()"
public class Register{
public Ticket[] tickets;
public int numTickets;
public Register(){
tickets = new Ticket[100];
numTickets = 0;
}
public void add(Ticket ticket){ //add ticket method. Takes a ticket as a parameter and adds it to the array
tickets[numTickets] = ticket;
numTickets = numTickets+1; // incramenting array
}
public boolean contains(String ticketID){ //contains method. Takes a string from the ticket using the ID() method and uses as a parameter.
boolean b = false;
for (int i = 0;i<100;i++){
if (ticketID.equals(tickets[i].ID())){ // checks to see if ticket ID is in the array
b = true; // return value is true if found
break;
}
break;
}
return b; // returns true of false
}
public Ticket retrieve(String ticketID){ // returns the ticket with the specified ID
int j = 0; // initializing return value
for (int i = 0;i<100;i++){
if (ticketID.equals(tickets[i].ID())){
j = i;
break;
}
}
return tickets[j]; // returns ticket
}
}
Here is my driver code
public static void main(String[] args){
Register r = new Register();
Ticket t;
t = new Ticket(new Time("13:00"), "00001");
String ID_One = t.ID();
r.add(t);
t = new Ticket(new Time("13:18"), "00002");
String ID_Two = t.ID();
r.add(t);
System.out.println(r.contains(ID_One));
System.out.println(r.contains("00002"));
System.out.println(r.retrieve(ID_Two).toString());
Output is:
true
false // this should be true
Ticket[id=00002, time=13:18:00]
Delete the second break, which always exits the for loop on the first iteration, so only the first element of the array is ever compared.
You could simplify your code to 1 line:
public boolean contains(String ticketID) {
return Arrays.stream(tickets).map(Ticket::ID).anyMatch(ticketID::equals);
}
You're using a break statement outside your if condition, so it will only check the first element then break the loop. You can see this immediately with better formatting.
for (int i = 0; i<100; i++){
if (ticketID.equals(tickets[i].ID())){ // checks to see if ticket ID is in the array
b = true; // return value is true if found
break;
}
break;
}
Remove the second break to fix this so you only break when your if condition is true.
For personal advise, you might want to consider using a Map structure if you have a unique ID for each ticket. This can reduce your search time considerably.
int numTickets = 0;
Map<String, Ticket> ticketMap = new HashMap<>();
public void add(Ticket ticket) {
numTickets++;
ticketMap.put(ticket.ID(), ticket);
}
public boolean contains(String ticketId) {
return ticketMap.containsKey(ticketId);
}
public Ticket retrieve(String ticketId) {
return ticketMap.get(ticketId);
}
I'm just new to Java OOP, and I hardly understand about the class and stuff. I tried to write some code to understand but I didn't succeed. Here is my code, I expected it to return the number of eggs but I don't know why it returns nothing.
class EggCounter {
private int egg;
{
egg = 0;
}
public void eggAdd()
{
egg = egg + 1;
}
public void eggBreak()
{
egg = egg - 1;
}
public void eggAddDozen()
{
egg = egg + 12;
}
public int getEgg()
{
return egg;
}
}
public class EggTest
{
public static void main(String[]args)
{
EggCounter egg = new EggCounter();
egg.eggAdd();
egg.eggAddDozen();
egg.eggBreak();
egg.getEgg();
}
}
It does return 12. Replace the egg.getEgg(); line in your main method with System.out.println(egg.getEgg()); and you will notice it prints 12.
It is returning, it's just that you do nothing with the return value of getEgg. What you need to do is store it into the variable or do something with it. return <value> only returns the given value to the callee, you must store it to use it. Example:
int eggCount = egg.getEgg();
System.out.println(eggCount);
Here, the assignment of eggCount calls egg.getEgg(). The call resolves when the number of eggs is returned, which assigns the return value to eggCount. Finally, it will print out eggCount. If you need the result of egg.getEgg() later, you can simply just output the following:
System.out.println(egg.getEgg());
How this works is the method egg.getEgg() is called. The return value is then resolved, which is passed into the print statement. This gets rid of storing it into a variable you can use later.
i'm having a bit of a problem. Here's the situation. I have an amount field in my main class that gets incremented when certain buttons are clicked on. There is a method provided through which you can delete any order (I'm basically programming for a restaurant terminal) and the amount gets decremented. The delete method is placed in another class.
public void posdel(int pos, JTextField amountFieldGot, int amountGot)
{
if(slist==null)
{
JOptionPane.showMessageDialog(null, "No order has been placed yet.",null,JOptionPane.WARNING_MESSAGE);
}
else
{
if(pos==1)
{
reductionAmount = (slist.quantity*slist.price);
amountGot = amountGot - reductionAmount;
slist=slist.next;
}
else
{
int i=1;
Node temp=slist;
Node prev=null;
while(temp.next!=null && i<pos)
{
prev=temp;
temp=temp.next;
i++;
}
if(pos==i)
{
prev.next=temp.next;
}
else
{
JOptionPane.showMessageDialog(null, "Invalid order", null, JOptionPane.ERROR_MESSAGE);
}
}
}
amountFieldGot.setText(Integer.toString(amountGot));
}
So basically, I have an amountField in my GUI that i pass as a parameter to the posdel method. I also pass the amount value as a parameter. The new amount that i get is amountGot after the deletion of the first order. ( I haven't written the code for other positions.)
Suppose the amount value i pass into the method is 30 (14+16) 14 = order 1, 16 = order2.
And my first order has a value of 14.
So amountGot = 30 - 14 which is 16.
And the amountField in the GUI gets updated to 16.
Now my order 2 becomes my order 1. And if i try to delete this,
my amountField gets update to 14. (30-16 = 14).
So i'm guessing the amount value stays the same itself as 30 and does not get updated to the new amountGot value. Can someone please help me solve this problem ?
below is the code for my delete button.
deleteButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
dishDelPos = JOptionPane.showInputDialog("Enter the position of the order to be deleted");
try
{
dishDeletePosition = Integer.parseInt(dishDelPos);
order1.posdel(dishDeletePosition, amountField, amount);
repaint();
}
catch(NumberFormatException ex1)
{
JOptionPane.showMessageDialog(null,"This is not a valid position");
}
}
});
A few things.
You can make the delete method in the class static. The you would reference it
value = MyClass.deleteMethod();
You can create a new class to perform the method
MyClass myClass = new MyClass();
value = myClass.deleteMethod();
You can do it using a pointer of sorts, by passing in a reference to an already existing instance of the class holding the delete method, to where you want to call it.
myFunction(MyClass myClass)
{
value = myClass.deleteMethod();
}
basically set up your function to return a value
public static int deleteMethod()
{
}
this function returns an int.
or if you need to return more than that then set the class up with global variables of information
class MyClass
{
public int value1;
public int value2;
public String value3;
public void deleteMethod()
{
//does something with global variables
}
}
now fetch the info after calling delete like so
Myclass myClass = new MyClass();
myClass.deleteMethod();
value1 = myClass.value1
value2 = myClass.Value2
value3 = myClass.Value3
Sorry if this is answered somewhere due to me missing something obvious, but I've been googling this for days now and it just doesn't seem to make any sense. I've got 3 years of experience in Javascript and am getting into Java now, so I'm not behind on the basic concepts of anything and such.
I'm using IntelliJ for this, but it fails to point out the problem. The communication (access rights and instantiations) between my classes is fine, the code syntax and variable types are as well, etc, so I really can't tell what it is.
I have a Data class, which just holds "read-only" data for the other classes to use.
public class Data {
// snip
public static int[][] specs = {
{6,1,6,40},
{5,2,5,30},
{5,3,4,40},
{4,4,3,60}
};
}
There's another class that has to read this data when it's initialized.
public class Soldier {
// snip
public int range;
public Soldier() {
int x = ...; // user input
range = Data.specs[x][1];
}
}
The specs array itself contains its data as defined (ie the array is not empty), x is valid as an index of the specs array (ie 0 <= x <= 3), its type is int and Test has read access to the specs array (all confirmed with debug output statements). And yet, when it tries to set the value of range (then and only then, at that exact point), I get the "Index out of bounds" error.
Can someone please tell me what's going wrong when trying to read the array? Or am I right in saying that this is really weird and I need to post the entire code?
Note: a small new test also shows that, if I change the code to first output a manually chosen value from the array and then set the value of range, the console prints the error statement (and exits the program) and follows it up by printing the manually picked value, but assigning the value and then asking to output range only throws the error... That makes absolutely no sense at all!
Edit: I've edited the code above. The class called Test is called Soldier in my code (I'm making a text-based game...). Below's the stack trace, if it's any good without the full code (which is way long). The basic structure of my program is this:
1) Boot contains the main method and instantiates a new Game
2) Game instantiates x Teams
3) each Team instantiates an Army
4) each Army instantiates x Soldiers
Each instance of the classes is set as an attribute of the instantiating class (public Army army; and an Army instantiation in the Team constructor, for example). It's essentially a cascade of constructors instantiating subsequent classes and assigning them as their attributes.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Army.<init>(Army.java:13)
at Team.<init>(Team.java:19)
at Game.<init>(Game.java:22)
at Boot.main(Boot.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)5
Edit edit: here's the semi-full code (I'm leaving out the stuff that has absolutely nothing to do with it, including the imports). It's in no particular order and the classes are in separate .java files within the IntelliJ project. The game continues up to the point where a new Soldier asks for its type to be designated (the function performing the user input is working fine and validating the input as proven by a technically identical other part of the game).
public class Boot {
public static void main(String[] args) {
Object[] games = new Object[] {};
if (Lib.userConfirmPrompt("Start the game?") == true) {
do {
games[games.length] = new Game();
}
while (Lib.userConfirmPrompt("Do you want to play again?") == true);
}
System.exit(0);
}
}
public class Game {
public Object[] teams = new Object[] {};
public Game() {
for (int i = 0;i < settings.xbots + 1;i++) {
teams[teams.length] = new Team(this);
}
}
}
public class Team {
public Game game;
public Army army;
public Team(Game p) {
game = p;
army = new Army(this);
}
}
public class Army {
public Team team;
public static Object[] soldiers = new Object[] {};
public Army(Team p) {
team = p;
for (int i = 0;i < team.game.settings.xsoldiers;i++) {
soldiers[soldiers.length] = new Soldier(this);
}
}
}
public class Soldier {
private Army army;
public int sight;
public int range;
public int distance;
public int damage;
public Soldier(Army p) {
army = p;
int type = Lib.userTxtIntOptionsPrompt(Data.isoldiertypes);
// HERE is where it crashes, type is assigned and valid but the array access fails
sight = Data.isoldierspecs[type][0];
range = Data.isoldierspecs[type][1];
distance = Data.isoldierspecs[type][2];
damage = Data.isoldierspecs[type][3];
}
}
public class Data {
public static List isoldiertypes = Arrays.asList("Scout","Private","Machinegunner","Grenadier");
public static int[][] isoldierspecs = {
{6,1,6,40},
{5,2,5,30},
{5,3,4,40},
{4,4,3,60}
};
}
public class Lib {
private static Scanner input = new Scanner(System.in);
// output
// default: 1 query string to print
public static void outBase(String query) {
System.out.print(query);
}
public static void outStd(String query) {
outBase(query + "\n");
}
// end of output
// input
// default: 1 query string to print,
// query and input are in-line (exception: userConfirmPrompt prints query block-wise and default instruction in-line before input),
// keeps user hostage until valid input is given (exception: userPrompt returns blindly)
public static String userPrompt(String query) {
outBase(query);
return input.nextLine();
}
public static String userTxtPrompt(String query) {
String menuinput = null;
do {
if (menuinput != null) {
userHostage();
}
menuinput = userPrompt(query);
} while (menuinput.length() == 0);
return menuinput;
}
public static int userIntPrompt(String query) {
String menuinput = null;
do {
if (menuinput != null) {
userHostage();
}
menuinput = userTxtPrompt(query);
} while(menuinput.matches("^-?\\d+$") == false);
return new Integer(menuinput);
}
// end of input
// options input
// default: takes a List of options as argument,
// prints an enumerated list of these options string-wise,
// prompts for a numeral selection of the desired option and returns the number if valid
public static int userTxtIntOptionsPrompt(List options) {
int choice = 0;
Boolean chosen = false;
do {
if (chosen == true) {
userHostage();
} else {
chosen = true;
}
chosen = true;
for (int i = 0;i < options.size() - 2;i++) {
outStd((i + 1) + ") " + options.get(i) + ",");
}
outStd((options.size() - 1) + ") " + options.get(options.size() - 2) + "\nand " + options.size() + ") " + options.get(options.size() - 1) + ".");
choice = userIntPrompt("Enter the number of the option you'd like to select: ") - 1;
} while(choice < 0 || choice >= options.size());
return choice;
}
// end of options input
// miscellaneous
public static void userHostage() {
outStd("Invalid operation. Please try again.");
}
}
The problem is in your Army class:
public static Object[] soldiers = new Object[] {};
You initialize an empty (length == 0) array named soldiers, but later you access:
soldiers[soldiers.length] = new Soldier(this);
This causes the failure.
By definition, soldiers.length is out of the bound of the array (since the bound is from 0 to soldiers.length-1)
To overcome it - make sure you allocate enough space in the array soldiers or use a dynamic array (ArrayList) instead. You can append elements to an ArrayList using ArrayList.add(), and you don't need to know the expected size before filling it up.
The x should be greater than -1 and less than 4.
The stacktrace does not mention the Solder class, its in the conctructor of the Army class.
Any how, only knowing that the index should be within a range is not enough. As a programmer its your duty to validate the index before trying to access an element at that index.
if(index > 0 && index < array.length) {
//then only acess the element at index
Problem is the array soldiers is of size 0.
This line int x = ...; // user input implies that you are taking input in some fashion from the user and accessing the array with it. Are you checking this value to see that is in range (i.e., between 0 and 3)? If not, this may be why your testing works.
Edit: something like this might solve it for you:
public class Army {
public Team team;
public Vector<Soldier> soldiers;
public Army(Team p) {
soldiers = new Vector<Soldier>()
team = p;
for (int i = 0;i < team.game.settings.xsoldiers;i++) {
soldiers.add(new Soldier(this));
}
}
}
Judging by your other code, this sort of pattern will be useful in your Game object as well.
This is a chunk of code I'm using for Google's antai challenge whenever I run it it seems to go into some endless loop then I get the stack trace at the bottom. I'm burnt out looking at this code I can't for the life of me figure this out.
public class Node
{
private final int xCoord, yCoord;
private int F, G, H;
private Tile location;
Node previousNode;
private Tile [] neighbors;
/*
G
the exact cost to reach this node from the starting node.
H
the estimated(heuristic) cost to reach the destination from here.
F = G + H
As the algorithm runs the F value of a node tells us how expensive we think it will be to reach our goal by way of that node.
*/
public Node(Tile loc)
{
location = loc;
xCoord = location.getCol();
yCoord = location.getRow();
F=G=H=0;
setNeighbors();
}
private void setNeighbors()
{
if(neighbors == null)
{
neighbors = new Tile[4];
}
neighbors[0] = new Tile(xCoord+1,yCoord);
neighbors[1] = new Tile(xCoord-1,yCoord);
neighbors[2] = new Tile(xCoord,yCoord+1);
neighbors[3] = new Tile(xCoord,yCoord-1);//error occurs here!!!!!!
}
}
/**
* Represents a tile of the game map.
*/
public class Tile implements Comparable<Tile> {
private final int row;
private final int col;
/**
* Creates new {#link Tile} object.
*
* #param row row index
* #param col column index
*/
public Tile(int row, int col) {
this.row = row;
this.col = col;
}
/**
* Returns row index.
*
* #return row index
*/
public int getRow() {
return row;
}
/**
* Returns column index.
*
* #return column index
*/
public int getCol() {
return col;
}
/**
* {#inheritDoc}
*/
#Override
public int compareTo(Tile o) {
return hashCode() - o.hashCode();
}
/**
* {#inheritDoc}
*/
#Override
public int hashCode() {
return row * Ants.MAX_MAP_SIZE + col;
}
/**
* {#inheritDoc}
*/
#Override
public boolean equals(Object o) {
boolean result = false;
if (o instanceof Tile) {
Tile tile = (Tile)o;
result = row == tile.row && col == tile.col;
}
return result;
}
/**
* {#inheritDoc}
*/
#Override
public String toString() {
return row + " " + col;
}
}
the actual error I'm receiving is:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at Node.setNeighbors(Node.java:37)
at Node.<init>(Node.java:25)
at AstarSearch.assessRoute(AstarSearch.java:73)
at MyBot.gatherFood(MyBot.java:153)
at MyBot.doTurn(MyBot.java:124)
at AbstractSystemInputParser.processLine(AbstractSystemInputParser.java:54)
at AbstractSystemInputReader.readSystemInput(AbstractSystemInputReader.java:18)
at MyBot.main(MyBot.java:25)
any help is appreciated
You need to do some debugging / clean up. From quick view I see, that in assesRoute() you
are never manipulating interesetedNode tile - this loop is not going to end normally.
It is also better to keep visited nodes in hash set - you only need to assure presence or absence, not a number of nodes. Alternative would be boolean flag in a node itself, this way you can work it with one list.
It seems like your creating more objects than your memory allows, guess your code is including an unfifite loop, you can make a static integer to count how many times the setNeighbors is called, its the routine where you create new objects, and show this integer on the catch statement of a try/catch around the main call of your class.
I don't know what this Google challenge is, so this may not be of much use (ie I don't know if you have access to the JVM), though it is a generic method to help diagnose this kind of problem.
I suggest turning on the JVM flag -XX:+HeapDumpOnOutOfMemoryError, and running your code again. An OutOfMemoryError will cause the heap to be dumped. You can then analyse this offline using something like Eclipse MAT.
The MyBot.doTurn() in the stack trace suggests your program is running over or discovering some kind of path... Are you sure this is a finite algorithm?
in assesRoute is a while loop. how many iterations do you expect? print out how many are actually done. if the difference is big, you know that there is a problem. take the start state of this iteration and try to understand why this state doesn't end the loop in proper time.