Java Array !Not! Out Of Bounds - java

public class GameEntry {
private String name;
private int score;
public GameEntry(String n, int s){
name = n;
score = s;
}
public String getName(){
return name;
}
public int getScore(){
return score;
}
public String toString(){
return "(" + name + ", "+ score + ")";
}
}
public class Scoreboard {
private int numEntries = 0;
public GameEntry[] board;
public Scoreboard(int capacity){
board = new GameEntry[capacity];
}
**public void add(GameEntry e){**
//System.out.println(board[numEntries - 1].getScore());
int newScore = e.getScore();
//Is the new entry really a high score
//*****This is the line i refer to as******
if (numEntries < board.length || newScore > board[numEntries - 1].getScore()) {
if (numEntries<board.length) {
numEntries++;
}
//shift any lower scores rightward to make room for the new entry
int j = numEntries - 1;
while(j>0 && board[j-1].getScore()<newScore){
board[j] = board[j-1]; //shift entry from j-1 to j
j--; // and decrement j
}
board[j] = e; // when done add a new entry
}
}
}
I would like to draw your attention inside the Scoreboard class, to its add method.
My question is why this code does not fail.
The first time the add method runs, the numEntries is equal to 0. So inside the if statement the board[numEntries - 1].getScore should get an IndexOutOfBounds.
When i put it before the if i get the proper exception. Does the if catch the exception?
I have printed the value of (numEntries - 1) and i get -1. But yet inside the if ot does not seem to bother it.
The line i refer to is inside the add method the first if.
if (numEntries < board.length || newScore > board[numEntries - 1].getScore())

Simple Answer: Short-circuit evaluation of logical or.
When the first part of the condition, i.e. numEntries < board.length evaluates to true, the second part after || is not evaluated at all.

You are checking the following expression first:
numEntries < board.length
Then you have an OR (||) followed by the expression you are asking about.
The compiler checks the expression from left to right. So if the above expression is true, it just enters the if and starts executing it's contents without checking other expressions.

Related

System.out.println doesn't show text in console (IntelliJ)

I am writing a program which part is presented below:
public class Portal {
private String name;
private int[] positions; // positions of "ship"
private static int moves = 0; // moves made by player to sink a ship
public static int shot; // the value of position given by player
private int hits = 0; // number of hits
private int maxSize = 4; // max size of ship (the size will be randomized)
int first; // position of 1st ship block
int size; // real size of ship (randomized in setPortal method)
public void checkIfHit(){
for (int i : positions){
if (i == shot){
System.out.println("Hit confirmed");
hits++;
} else if (hits == positions.length){
System.out.println("Sunk");
} else {
System.out.println("Missed it");
}
}
moves++;
}
public void setPortal(){
size = 1 + (int)Math.random()*maxSize;
for (int i = 0; i < size - 1; i++){
if (i == 0){
positions[i]= 1 + (int)Math.random()*positions.length;
first = positions[i];
System.out.println(positions[i]);
continue;
}
positions[i]= first + 1;
System.out.println(positions[i]);
}
}
}
public class Main{
public static void main(String[] args){
// write your code here
Portal p1 = new Portal();
p1.setPortal();
}
}
code is split in two Java .class files.
The problem I'm dealing with is that using p1.setPortal(); doesn't show up text in IntelliJ console. The program works though and returns 0.
I don't have such problem in another program when I've put System.out.println in method other than main (also in separate class file).
What may be the cause of such issue?
It should properly throw an exception, because you forgot to initialize the integer array.
Have a look at this thread: Do we need to initialize an array in Java?
The Java's default value is null for an integer array. So your for wont even loop trough. The only thing that wonders me is why there is no exception..

Java method returns int that can't be compared to another int (Android Studio)

First off, these are ints, not Integers.
I want to get a variable from another class and compare it to a value, like so:
Log.v("xx", "" + boardAdap.getPieceNumber());
int pieceNumberInt = boardAdap.pieceNumber;
if (pieceNumberInt == 32) {
Log.v("xx", "int comparison worked");
}
int pieceNumberMethod = boardAdap.getPieceNumber();
if (pieceNumberMethod == 32) {
Log.v("xx", "method comparison worked");
}
So, I want to get the pieceNumber variable from the boardAdap class, and check if it is equal to 32. If it is, it prints the stuff in Log in the console.
The boardAdap method:
int pieceNumber;
int pieceNumberIncrement;
public int getPieceNumber() {
for (int i = 0; i < 64; i++) {
if (board.getPiece(Square.squareAt(i)).name() != "NONE") {
this.pieceNumberIncrement++;
}
}
this.pieceNumber = pieceNumberIncrement;
return pieceNumber;
}
This iterates through an enum called Square, and increments pieceNumberIncrement if the value is not "NONE".
However, when I run this, the output is:
32
int comparison worked
So, why does the second if condition fail, if getPieceNumber() returns an int? It also fails when I use an Integer wrapper, or convert pieceNumberMethod to a string and then to an Integer, and other methods.
Also, should I change getPieceNumber() to just update the pieceNumber instead, and reference only that?
Additionally, if pieceNumberMethod is used in a for loop like:
for (int i = 0; i < pieceNumberMethod; i++) {
}
The for loop will never stop.
Thanks!
You are basically calling getPieceNumber twice so in the second call the number changes.
int pieceNumberMethod = boardAdap.getPieceNumber();
Log.v("xx", "" + pieceNumberMethod);
int pieceNumberInt = boardAdap.pieceNumber;
if (pieceNumberInt == 32) {
Log.v("xx", "int comparison worked");
}
if (pieceNumberMethod == 32) {
Log.v("xx", "method comparison worked");
}
Try calling method once.Hope that works!
The problem is comparing the strings. You need equals("NONE")
String none = new String("NONE");
int count = 32;
System.out.println(count);
for (int i = 0; i < 64; i++) {
if (none != "NONE") {
count++;
}
}
System.out.println(count);
If you run this code it will print different values for "count" despite value of "none"

return int from within if statement in a loop in java

i have a loop which iterates equal to the length of an array, inside this loop i have a method which do some processing and have if-else structure inside. i want that if certain condition is true, then re-iterate the whole loop else continue.
the Minimum working code is provided.
for(int xx=0;xx<temp.length;xx++)
{
rule=temp[xx][1];
cons=temp[xx][2];
fp.factprocess(fact, rule, vars, cons);
}
contents of fp.factprocess are like
if(condition==true)
make xx = 0 in the parent loop
else
continue
i dont know how do i do it, i used return statement but it has to be in the end and can not be in the if-block.
Return a boolean from the condition test. If boolean true, set xx to -1 (to be incremented to 0) in the loop.
for(int xx=0;xx<temp.length;xx++)
{
rule=temp[xx][1];
cons=temp[xx][2];
boolean setXXtoZero = fp.factprocess(fact, rule, vars, cons);
if(setXXtoZero) xx=-1;
}
fp.factprocess:
return condition;
Yes, there can be a return statement in the if block.
public int getValue(int val){
if ( value == 5 ){
return value;
}
else{
return 6;
}
}
for instance, is valid Java code.
public int getValue(int input){
if ( input == 5 ){
return input;
}
}
on the other hand, is not, since you don't return anything if input does not equal 5, yet the method has to either return an int, or throw an Exception.
That's probably what your problem is: you need to provide a return statement for all possible scenario's.
If you want to modify the xx variable of the loop, I suggest to return a boolean in your factprocess method.
for (int xx = 0; xx < temp.length; xx++) {
rule = temp[xx][1];
cons = temp[xx][2];
boolean shouldRestart = fp.factprocess(fact, rule, vars, cons);
if (shouldRestart) {
xx = 0;
}
}
Pass xx to factprocess() and assign the return to xx
for(int xx=0;xx<temp.length;xx++)
{
rule=temp[xx][1];
cons=temp[xx][2];
xx = fp.factprocess(fact, rule, vars, cons, xx);
}
Inside factprocces()
if (condition == true) {
return 0
} else {
return xx
}

how to get calculator to accept new numbers after equal sign is pressed? java

i am doing an exercise to create a simple calculator in java.
i want the calculator to keep taking numbers after the equal sign is pressed. so if i press "10+10 =" the result will be 20, and if I want to press "+1 = " and the result will be 21. or if I want to subtract as well.
my code is below. im sure the change has to be made to the "equals" portion of the code but i am unsure where/how to begin.
public int getDisplayValue()
{
return displayValue;
}
public void numberPressed(int number)
{
currentValue = (currentValue * 10) + number;
displayValue = currentValue;
}
private void applyPreviousOperation()
{
if (previousOp == '+')
{
heldValue = heldValue + currentValue;
displayValue = heldValue;
}
else if (previousOp == '-')
{
heldValue = heldValue - currentValue;
displayValue = heldValue;
}
else {
heldValue = currentValue;
}
}
public void plus()
{
applyPreviousOperation();
previousOp = '+';
currentValue = 0;
}
public void minus()
{
applyPreviousOperation();
previousOp = '-';
currentValue = 0;
}
public void equals()
{
applyPreviousOperation();
previousOp = ' ';
currentValue = 0;
heldValue = 0;
}
public void clear()
{
displayValue = 0;
previousOp = ' ';
}
}
You need to define your question more clearly.
what's the calculator flow should be. You describe an operation that contradicts a simple a+b.
It really matters how you input the numbers, If for example the very first operation is texted "a+b" ,"a-b" .... than you can keep it as currentValue.
than next opperations will be calculated against currentValue.
Have a variable called defaultOperand. When the equals button is pressed, update the defaultOperand variable with the output of the operation. It becomes the default left side operand. If an operation is inputted without a left side operand, then use the value in the defaultOperand as the default left hand operand.

Randomize String Array and display all of the values

I'm making a card game, and I've arrived at the shufflin' time.
I've to shuffle a few cards (that are chosen before from the user, so they're not always the same amount) and then display them to the user one by one.
As I'm still developing the game's logic I'm displaying cards' name by changing a button text.
But I get stuck when I try to get the cards' name and set them as the button's text.
What happens is me gettin' a blank button or just with "Masons" or "Villager" String. Infact if I check the log I see that all the others cards(characters) get displayed as "null".
This is how I tried to achieve the goal (Yes I'm a newbie):
This is the head:
int demoniac;
int guard;
int masons;
int medium;
int mythomaniac;
int owl;
int villager;
int werehamster;
int all;
int i;
int t;
String[] characters = new String[24];
Button randomButton;
My method to addAll the cards(characters):
public void addAll(){
for(i = 0; i < all; i++){
add(demoniac, "Demoniac");
add(guard, "Guard");
add(medium, "Medium");
add(mythomaniac, "Mythomaniac");
add(owl, "Owl");
add(werehamster, "Werehamster");
add(villager, "Villager");
add(masons, "Masons");
}
}
My method to add and manage the various types of cards(characters):
public int add(int character, String name){
if(character != 0 && name == "Villager"){
for(t = 0; t < character; t++){
i+=t;
characters[i] = name;}
}
else if(character == 2 && name == "Masons"){
characters[i] = name;
i++;
characters[i] = name;
Toast.makeText(randomSelection.this, "works", Toast.LENGTH_SHORT).show();
}else if(character != 0){
characters[i] = name;
}
return i;
}
To randomize:
public void randomize(){
Collections.shuffle(Arrays.asList(characters));
for (int s = 1; s < characters.length; s++)
{
System.out.println(characters[s]);
}
}
The method to display a different card(character) each time the user clicks the button:
public void show(View view){
for (int s = 1; s < characters.length; s++)
{
randomButton.setText(characters[s]);
}
}
EDIT:
I've noticed the no sense for loop I've done, by the way you should know although most of the characters are only 1 of their kind (demoniac, guard, etc..) there are 2 Masons and from 5 to 12 Villagers, so We need to retrieve these ints and add as much Strings to the Array as much we're told from those ints.
Example: If I get 6 Villagers, I've to add the String "Villager" 6 times into the String Array.
Then I've set that s value to 1 'cause I've to display the first
String ([0]) as soon as the Activity gets started, so on the OnCreate() method.
Maybe I'm wrong, if so I please you to correct me!
Getting a blank button or just with "Masons" or "Villager" String
That is because you only set the Button's text with the last element of the list. Which is either null or "Masons" (not seeing how it could be "Villager").
for (int s = 1; s < characters.length; s++)
{
randomButton.setText(characters[s]);
}
If I check the log I see that all the others cards(characters) get displayed as "null"
You only set position 0 of your array. For example, you don't initialize the positions, so these int values default to 0.
int demoniac;
int guard;
int all;
Then
for(i = 0; i < all; i++){
add(demoniac, "Demoniac");
add(guard, "Guard");
Really, that loop shouldn't be entered because all equals 0.
Additionally
Collections are zero-indexed, so this doesn't print element 0. You need to set int s = 0;.
for (int s = 1; s < characters.length; s++)
It isn't clear to me what the add(int character, String name) method is returning, but if you explain it, I will update this answer.
I believe this code fulfills most of what you are trying to achieve
// Where the characters are stored
private ArrayList<String> characters;
public void initDeck() {
if (characters == null)
characters = new ArrayList<String>();
// Extract the numbers if you actually need them, otherwise, they just are constants
addCharacter("Demoniac", 1, characters);
addCharacter("Guard", 1, characters);
addCharacter("Medium", 1, characters);
addCharacter("Mythomaniac", 1, characters);
addCharacter("Owl", 1, characters);
addCharacter("Werehamster", 1, characters);
addCharacter("Villager", 5, characters);
addCharacter("Masons", 1, characters);
}
public void addCharacter(String name, int amount, ArrayList<String> cards) {
if (amount < 0) {
throw new IllegalArgumentException("Must add a non-negative number of characters for " + name);
}
// Don't use '==' for Strings
if (name.equals("Villager")) {
if (amount != 5 || amount != 12) {
throw new IllegalArgumentException("There can only be 5 or 12 " + name);
}
}
for (int i = 0; i < amount; i++) {
cards.add(name);
}
}
public int searchCharacters(String character, ArrayList<String> cards) {
return cards.indexOf(character);
}
public Map<String, Integer> getAllCharacterPositions() {
Map<String, Integer> allPositions = new LinkedHashMap<String, Integer>();
for (int i = 0; i < characters.size(); i++) {
allPositions.put(characters.get(i), i);
}
return allPositions;
}
void run() {
// initialize the characters
initDeck();
// shuffle them
Collections.shuffle(characters);
// print them all out
for (int i = 0; i < characters.size(); i++) {
System.out.printf("%d: %s\n", i, characters.get(i));
}
// Find the position of a character
System.out.println();
String findCharacter = "Owl";
// Option 1 -- always linear search lookup
System.out.printf("%d: %s\n", searchCharacters(findCharacter, characters), findCharacter);
// Option 2 -- one-time linear scan, constant lookup
Map<String, Integer> positions = getAllCharacterPositions();
System.out.printf("%d: %s\n", positions.get(findCharacter), findCharacter);
// Get a random character
System.out.println();
Random rand = new Random(System.currentTimeMillis());
int randPos = rand.nextInt(characters.size());
System.out.printf("%d: %s\n", randPos, characters.get(randPos));
// randomButton.setText(characters.get(randPos));
}
Given the array is already shuffled, just look at the first card:
public void show(View view){
randomButton.setText(characters[0]);
}
If you want to navigate that deck I suggest you put the shuffled list in to a Queue, where you can look at the next card (peek) or take the next card (poll):
private static Queue<string> buildNewShuffledDeck(String[] characters){
List<String> shuffledCharacterList = new ArrayList<String>(characters);
Collections.shuffle(shuffledCharacterList);
Queue<string> deck = new ArrayDeque(shuffledCharacterList);
return deck;
}
public void show(View view){
String nextCard = deck.peek();
if (nextCard != null)
randomButton.setText(nextCard);
else
//deck is empty...
}
Then to take from the deck, say on the random button click:
String nextCard = deck.poll();
General advice on arrays: Stop using them in favor of other data types that are far more useful and interchangeable.
Then next step advice, make a class that represents a Card and stop using Strings, the string you currently have is just one property of a card.
You are just displaying the last character name that you add
Replace with this
public void show(View view){
Random r = new Random(System.currentTimeMillis());
randomButton.setText(characters[r.nexInt(characters.length)])
}

Categories

Resources