-3

I have a bit of a problem here and really, I don't get why. I have written plenty of code that takes field variable in the parameters and then changes them. Here is the method:

public void hit(Array<Card> cards, int score, float spacing) {
    // Take the last card from the deck and store it in a temp card variable
    nextCard = deck.pop();
    // If the card value is equal to 11, it must be an ace, if it puts the
    // player over 21 it makes the ace have a value of 1
    if ((nextCard.getCardRealValue() == 11)
            && nextCard.getCardRealValue() + score > 21) {
        nextCard.setCardRealValue(1);
    }
    // Add the card to the array passed in the parameter
    cards.add(nextCard);
    // Check the last card in the array (the one just added) grab it's value, add it to total
    score += cards.peek().getCardRealValue();
    // Shrink the main deck, not sure if neccessary but not point in leaving empty memory
    deck.shrink();
    // Move the sprites 20 pixels
    spacing -= 20;
    // tbh this bit never gets called, stupid useless code lol
    if (score > 21) {
        if (cards.peek().getCardRealValue() == 11) {
            cards.peek().setCardRealValue(1);
            score -= 10;
        }
    }
    // if the first card has not been checked and score is over 21, if it is an ace change it to a value of 1
    if (!aceOne && score > 21 && cards.get(0).getCardRealValue() == 11) {
        cards.get(0).setCardRealValue(1);
        score -= 10;
        aceOne = true;
        // Same as above, just if second card is ace
    } else if (!aceTwo && score > 21
            && cards.get(1).getCardRealValue() == 11) {
        cards.get(1).setCardRealValue(1);
        score -= 10;
        aceTwo = true;

    }
}

This is basically the method that gets called when the player decides to "hit", it takes the array that holds the cards of the player, the players score and then this thing which I have called spacing, this basically shifts the card sprites -20 to the left to stop then trailing to the right of the screen and looking fugly.

Now when I try to call this method:

hit(playerCards, playerScore, playerSpacing);

Why is the playerScore and the playerSpacing not updating? The cards are being added just fine because they draw the respected Sprite, am I missing something?

Gibbo
  • 630
  • 1
  • 8
  • 22

3 Answers3

2

Java is always pass-by-value. You are changing your local variables score and spacing, but those are copies of playerScore and playerSpacing.

But why did changes to cards update playerCards? Because the object reference was passed by value. You have a copy of the reference, which refers to the same object. The object was changed (and can be changed through playerCards or cards). If you had done cards = new Array<Card>();, then you would have given a new value to the local variable cards and playerCards would be unchanged when you change cards.

rgettman
  • 176,041
  • 30
  • 275
  • 357
  • as far as I know "Java is always pass-by-value" is not a true statement. can you please give a reference to it? – guness Dec 03 '13 at 19:51
  • @bluebrain Please see [Is Java “pass-by-reference”?](http://stackoverflow.com/questions/40480/is-java-pass-by-reference). – rgettman Dec 03 '13 at 19:52
  • Thank you for the answer, another answer said I should replace my data types with objects such as Integer and Float instead of int/float. However this has not changed anything, any ideas? – Gibbo Dec 03 '13 at 19:58
  • @bluebrain An object doesn't get passed at all. The reference to an object is passed, and that reference is passed by value. – rgettman Dec 03 '13 at 19:58
  • @Gibbo That won't help because those wrapper types are immutable. You could create your own object to hold both the primitive values `score` and `spacing`. Pass a reference to that object into your `hit` method. Then you can change those values with a setter method. – rgettman Dec 03 '13 at 20:01
  • So it would be functional if I created a dealer and a player class that holds their hand (card array) and their total score + spacing? – Gibbo Dec 03 '13 at 20:04
1

The values must be updating but are reflected back to the calling statement because, in java, all built-in datatypes are passed by value and all class objects are passed by reference, hence no effect when you re-use it after calling statement. Replace built-in datatypes with respective classes everywhere in the code for them, int -> Integer and float -> Float, it should work.

Arpit
  • 953
  • 7
  • 11
  • Ok I understand, however that did change a thing, it is still not updating the score and spacing. – Gibbo Dec 03 '13 at 19:56
1

Here is the fixed code:

The player object which holds it's own hand, score and spacing:

public class Player {

int score = 0;
float spacing = 390;
Array<Card> hand = new Array<Card>();

public Player(){
    hand.ordered = false;
}

public int getScore() {
    return score;
}

public void setScore(int score) {
    this.score = score;
}

public float getSpacing() {
    return spacing;
}

public void setSpacing(float spacing) {
    this.spacing = spacing;
}

public Array<Card> getHand() {
    return hand;
}

public void addToHand(Card card){
    hand.add(card);
}

}

The new method:

public void hit(Array<Card> cards, Player player){
    nextCard = deck.pop();
    if ((nextCard.getCardRealValue() == 11)
            && nextCard.getCardRealValue() + player.getScore() > 21) {
        nextCard.setCardRealValue(1);
    }
    cards.add(nextCard);
    player.setScore(player.getScore() + player.getHand().peek().getCardRealValue()) ;
    deck.shrink();
    player.setSpacing(player.getSpacing() - 20);
    cardDeal.play();
    if (player.getScore() > 21) {
        if (cards.peek().getCardRealValue() == 11) {
            cards.peek().setCardRealValue(1);
            player.setScore(player.getScore() - 10);
        }
    }
    if (!aceOne && player.getScore() > 21
            && cards.get(0).getCardRealValue() == 11) {
        cards.get(0).setCardRealValue(1);
        player.setScore(player.getScore() - 10);
        aceOne = true;
    } else if (!aceTwo && player.getScore() > 21
            && cards.get(1).getCardRealValue() == 11) {
        cards.get(1).setCardRealValue(1);
        player.setScore(player.getScore() - 10);
        aceTwo = true;

    }
}

Everything works as expected except now my code is reusable, which is why I wrote this method. Since the dealer will be using the same code to play. Thanks guys.

Gibbo
  • 630
  • 1
  • 8
  • 22