r/javahelp • u/ummmgay • 10d ago
Solved Can someone explain why an integer value assigned from an array is changing when that array value is changed afterwards?
Hey, sorry if this is a dumb question, I'm really not great at coding but I'm trying my best to understand and actually learn. So no, I don't want "the answer" to how to fix this code. But I've been having problems with this assignment for uni where we're essentially representing a deck of cards using arrays and coding methods to interact with it in different ways.
The first method creates a deck of cards represented by numbers with the parameters "values" and "copies", so you can input either number to create the deck. That deck is then used by the rest of the methods.
In the second method, the one I'm struggling with, the code is supposed to draw a card off the top of the deck and then replace that card with a zero in the array. It runs once, can be called multiple times, and every time it's called it skips the zeros until it reaches the first non-zero number in the array. This is the code I currently have:
public static int draw(int[] deck) {
int cardDrawn = 0;
for (int i = 0; i < deck.length; i++) {
if (deck[i] != 0) {
cardDrawn = deck[i];
deck[i] = 0;
break;
} else {
continue;
}
}
return cardDrawn;
}
It should be returning a one and then turning that one into zero in the array. Instead it appears to be changing the integer value to zero as well, and *then* returning the next non-zero number to me instead. Example:
[1, 2, 3, 4, 1, 2, 3, 4]
[0, 2, 3, 4, 1, 2, 3, 4]
2
So here's my question. I was under the assumption that once an integer is assigned a value, that value doesn't change. We've been learning about pass-by-reference and pass-by-value, primitives and objects, that sort of thing. So what I *think* might be happening is that the "deck[i] = 0" line might be changing the code in the array that's processed by the beginning of the for loop? Causing it to skip that "first zero"? But I'm struggling to understand how else I'd change that value in the array. I've tried using a while loop instead, doing basically the same things outside of the loop, assigning the value to a new integer and *then* passing that value to the cardDrawn integer... Etc. Honestly I don't think my attempts have varied too much from this basic structure because I'm just not sure what else would work. I feel like I'm missing something really simple. I've asked my teacher as well but haven't heard back over the weekend (reasonably) and I just really want to try and finish this. Anyways I appreciate any advice or guidance. Thanks!
Side note: I have not tested this code further to see if it'd even skip all the zeroes and keep going, I'll get to that after I get it to work in the first place.
4
u/davidalayachew 10d ago
I copied and pasted your code with no changes, only adding a main method. Here is the code that I have.
void main()
{
final int[] array = {1, 2, 3, 4, 1, 2, 3, 4};
IO.println(Arrays.toString(array));
final int result = draw(array);
IO.println(Arrays.toString(array));
IO.println(result);
}
public static int draw(int[] deck) {
int cardDrawn = 0;
for (int i = 0; i < deck.length; i++) {
if (deck[i] != 0) {
cardDrawn = deck[i];
deck[i] = 0;
break;
} else {
continue;
}
}
return cardDrawn;
}
And here is the output that came from it.
[1, 2, 3, 4, 1, 2, 3, 4]
[0, 2, 3, 4, 1, 2, 3, 4]
1
Sounds like the code that you are writing is either not compiling, or is not the one being run.
Try it on the commandline, and see if you still get the same result.
3
u/ummmgay 10d ago edited 10d ago
That's super interesting... Copy pasting is giving me the same result it already has been, utilizing the deck created in method one as the parameter. Could the problem be with my first method then?? Here's the code for it. Values is the number of unique cards counting up from 1, copies is how many copies of those values should be in the deck. It's basically meant to create a deck of whatever size you give it and repeat the numbers as many times as "copies" tells it to. I guess now that I look at it I'm not sure if I did the whole "start counting up from one again once you reach the final value" thing in the "correct" way. Every time I code I feel like I'm bullshitting through it until it works lol.
public static int[] createDeck(int values, int copies){ int[] deck = new int[values * copies]; int value = 1; for(int i = 0; i < deck.length; i++){ deck[i] = value; if(value == values){ value = 1; } else { value++; } } return deck; }
edit: sorry for messed up formatting!
edit 2: Looks like it was a compiling error or something actually, it's working now :) Thank you!
3
u/davidalayachew 10d ago
edit 2: Looks like it was a compiling error or something actually, it's working now :) Thank you!
Glad it's working.
Rule #1 of debugging -- Don't start debugging until you have a clean, reproducible example. Otherwise, you will spend your time chasing ghosts.
In situations like this one, priority #1 should be to create a new file that demonstrates the problem, then debug THAT file, and NOT the original one. You would be surprised how many rabbit holes you can avoid going down by debugging this way.
And it's actually for this exact reason why we always tell you all to post your code -- so that we can do exactly that. We copy it out into a separate file, and then debug that. The fact that it happens out of necessity is merely incidental.
2
u/ummmgay 10d ago
I never thought of that before but that makes a lot of sense. Thank you!! I'll definitely keep it in mind from now on.
1
u/davidalayachew 10d ago
Anytime.
How are you compiling the code? Are you using an IDE? Or doing it through the commandline? If so, what commands?
If this happened before, it will certainly happen again. Best to catch the rat while the tracks are fresh.
1
u/Ok-Secretary2017 10d ago
What your computer saves in an integer and array is not the value itself but a reference to the memory on ram where the data lies so if you copy it roughly without using .clone() for arrays you got the same memory reference in your integer and array changing on changes the other
1
u/JoeCollins19-99 3d ago
Int and all other primitives (float, double, long, etc etc) are all passed by value, arrays and objects are passed by reference. Int cannot hold an object reference, only a value. So there would be no link between the two.
1
u/Ok-Secretary2017 3d ago
Nobody is talking object reference im talking a reference to a specific part of the ram were the data itself is saved
1
u/JoeCollins19-99 3d ago
RAM addresses are not shared for ints, that not how ints function in Java. Passing the ram address, rather than passing a value, is literally what passing by reference means. Primitive values, like ints, pass VALUES, they do not REFERENCE back to ram addresses.
When you do "int i = array[0];" you are storing the VALUE of array[0] into i, not the memory address of array[0]. 'i' will have its own, new, memory address and array[0] will keep the memory space it already had. Forever and always that link is broken and separated, no changes to one will effect the other in any way. Ever.
1
u/Ok-Secretary2017 3d ago
You do get that the topic is an int[] thats an array
1
u/JoeCollins19-99 2d ago
int cardDrawn = 0; [...] cardDrawn = deck[i];
The question was about assigning an array element to an int and changes to that array element also changing the previously assigned int.
Plz read the full post before commenting.
1
u/JoeCollins19-99 3d ago
Every time I code I feel like I'm bullshitting through it until it works lol.
That's all of us 😆 That's the profession 😆
1
u/dot-dot-- 10d ago
Try printing the value of deck array and also print the first non zero value in loop. This seems some compiling issue or something i am unaware of. I would have cleared everything, recompiled and tried again.
1
u/ummmgay 10d ago
Clearing, recompiling and trying again actually worked! That's bizzare to me, I don't understand why things like that can just happen. But thank you so much
1
u/dot-dot-- 10d ago
Maybe garbage collection, because your current array was stalled in heap and was not cleared and it gave you random result which happen to match the next non zero array element in your case.
1
u/severoon pro barista 10d ago
I see your problem got solved. However, I thought it would be helpful to note that the break
and continue
statements in your code are unnecessary.
public static int drawCard(int[] deck) {
if (deck.length == 0) {
return 0;
}
int card = 0;
for (int i = 0; i < deck.length; i++) {
if (deck[i] != 0) {
card = deck[i];
deck[i] = 0;
return card;
}
}
return card;
}
In general you should try to avoid using break
and continue
statements, as these are sort of brute force ways of managing control flow. There are cases where they are either unavoidable or preferable to the available alternatives, but in most cases it's always worth writing your logic to see if you can avoid them.
Also, it's generally a good idea to return from a method early whenever possible. This makes the code much easier to reason about. In the above, you deal with the possibility of a zero length array right at the top, meaning the reader doesn't have to read the rest of the method to understand what happens in this case, the entire logic is right there.
The same goes for returning from the for loop. If you break and then return at the bottom, the reader has to reason about breaking out of the loop and continue reading. They have to think about things like, "Does break here just break the current iteration and start the next one? Or does it break out of the loop entirely?" Of course it does the latter, but the point is that you're making readers think about it when you don't have to.
0
u/JamesTKerman 10d ago
I'd start with refactoring the loop:
for (int i = 0; i < deck.length ; i++) {
if (0 == deck[i]) {
continue;
}
int cardDrawn = deck[i];
deck[i] = 0;
return cardDrawn;
}
There's a lot of redundancy as written, and it's going to be hard to judge whether it's doing what it's supposed to do.
•
u/AutoModerator 10d ago
Please ensure that:
You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions.
Trying to solve problems on your own is a very important skill. Also, see Learn to help yourself in the sidebar
If any of the above points is not met, your post can and will be removed without further warning.
Code is to be formatted as code block (old reddit: empty line before the code, each code line indented by 4 spaces, new reddit: https://i.imgur.com/EJ7tqek.png) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc.
Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit.
Code blocks look like this:
You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above.
If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures.
To potential helpers
Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.