Home > Back-end >  java.lang.StackOverflowError on a recursive function
java.lang.StackOverflowError on a recursive function

Time:11-05

I want to draw a random card from a deck and validates that it's always unique. I'm using the cardGenerator() recursive function to do that. If the random card picked has been shown then it calls itself again. Need a work around or if any of yall got a better logic please let me know.

import java.util.ArrayList;
import java.util.Random;

public class App {
    static ArrayList<Integer[]> deck = new ArrayList<>();
    static ArrayList<Integer[]> dealer = new ArrayList<>();

    static Integer[] cardGenerator() throws Exception{
        Random random = new Random();
        Integer[] card = {0, 0};
        Integer num = random.nextInt(13);
        Integer shape = random.nextInt(4);
        Integer[] deckSet = deck.get(num);
        if(deckSet[shape] == 1){
            deckSet[shape] = 0;
            deck.set(num, deckSet);
            card[0] = num;
            card[1] = shape;
            return card;
        }
        else return cardGenerator();
    }

    public static void main(String[] args) throws Exception {
        Integer[] deckSet = {1, 1, 1, 1};
        for(int i = 0; i < 13; i  ){
            deck.add(deckSet);
        }
        dealer.add(cardGenerator());
        dealer.add(cardGenerator());
        dealer.add(cardGenerator());
        dealer.add(cardGenerator());
        dealer.add(cardGenerator());
    }
}

expecting for dealer to store 5 unique cards, but java.lang.StackOverflowError occured on the cardGenerator function.

CodePudding user response:

You use the same deckSet array for all deck numbers. That means that after drawing for cards for all deck numbers the deckSet will be {0, 0, 0, 0}.

To solve it you need to initialize the deck as

    for(int i = 0; i < 13; i  ){
        Integer[] deckSet = {1, 1, 1, 1};
        deck.add(deckSet);
    }

CodePudding user response:

You need to make a new array for each element of the ArrayList, or else every element in the ArrayList is pointing to the same array. So for each of the 4 draws, it will turn 1 number in { 1, 1, 1, 1 } into 0, and on the 5th draw, a stack overflow occurs as there is no more 1s in the shared array.

You can fix the code by moving the new array declaration inside the loop, so a new array is created to be added to the list:

        for(int i = 0; i < 13; i  ){
            Integer[] deckSet = {1, 1, 1, 1}; // Moved inside
            deck.add(deckSet);
        }

Doesn't seem like you initialized all the Integers in the arrays in deck to be 1, so the conditional in the if statement is always false.

Consider doing

        if(deckSet[shape] == 0){ // Zero for unpicked card
            deckSet[shape] = 1; // One for picked card
            deck.set(num, deckSet);
            card[0] = num;
            card[1] = shape;
            return card;
        }
  • Related