1

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!

4
  • 1
    Where do you set the values of demoniac, guard, etc.? They are always 0 by default. Commented Jan 28, 2016 at 21:45
  • Other than setting all the strings at position 0, for (int s = 1; s < characters.length; s++) doesn't look at the first element of the list. Collections are zero-indexed Commented Jan 28, 2016 at 21:49
  • Random - but no repeats? i.e. like a deck of cards being span though Commented Jan 29, 2016 at 16:01
  • Exactly @weston That's exactly what I need to achieve Commented Jan 29, 2016 at 16:09

3 Answers 3

1

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));
}
Sign up to request clarification or add additional context in comments.

10 Comments

Thank You for the very detailed answer, I've edited my question, maybe now I've expressed myself in a better way ;)
Awesome cricket, I think there's just one missing edit to do, the amount of the characters isn't always the same, it might be 1 or might be 0, and in the Villager case it might be a value from 5 to 12
@FET - doesn't need an edit. Just change the parameters in initDeck to whatever you want. If you need if-conditions, then update addCharacter
@FET - But I have made the edit anyways, because you were comparing strings incorrectly
Tried to mae the method foe the button this way, I need to take next String each time I click: public void pick(View view){ while(i < characters.size()) { randomButton.setText(characters.get(i)); i++; } }
|
1

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.

1 Comment

Thank you! I'll really consider about creating that class when redesigning my code, for now I'll keep on going this way, then I'll get to the cleaner and smarter way ahaha, by the way thumbs up for your help, thank you!
0

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)])
}

1 Comment

Why the need to take random card from a shuffled deck?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.