Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android

FunFact app Not random fact.

Hey!

I'm doing some trial and error on the FunFact app and i ws wondering if it is possible to get the Random function to not show the same fact twice?

I have been trying to read on other places like Stockowerflow and other places but since this is my first coding in java and android i don't understand what they mean.

one of the tips was: " 1.create array of size n. 2.loop through and initialize each value at index i to the value i (or i+1 if you wish to have the numbers 1 to n rather than 0 to n-1).

  1. finally, loop through the array again swapping each value for a value at a random index." "

im not saying this is the best way, but maybe some of you could help me whit this?

3 Answers

If you're looking to sort the array in place, you can do something like this:

import java.util.Random;

public class Shuffle {
    private String[] facts = {
        "#1", "#2", "#3", "#4", "#5", "#6", "#7"
    };

    public void shuffleFacts() {
        Random random = new Random();

        for (int i = facts.length - 1; i > 0; i--) {
          int swapIndex = random.nextInt(i + 1);
          swapFacts(i, swapIndex);
        }
    }

    private void swapFacts(int from, int to) {
        String temp = facts[to];

        facts[to] = facts[from];
        facts[from] = temp;
    }

    // Display results 
    // If you want to mess around with it in Workspaces

    public void print() {
        for(String fact : facts)
            System.out.print(fact + " ");
        System.out.println();
    }

    public static void main(String... args) {
        Shuffle app = new Shuffle();

        System.out.println("Sorted: ");
        app.print();
        System.out.println("Shuffled: ");
        app.shuffleFacts();
        app.print();
    }
}

You could iterate through the array until you hit the end then reshuffle, mention there's no more facts, or whatever you want.

If you happen to be using a List you can use the standard library:

import java.util.Collections;

//...
    Collections.shuffle(facts);
//...

Using a List would give you the advantage of removing facts until it was empty if you wanted the program to end after the last fact.

Thank you Dan Johnson !

Where you write "If you want to mess around with it in Workspaces"

Do you then mean that that goes in to the original .java file (FunFactsActivity.java) ?

private String[] facts = {
        "#1", "#2", "#3", "#4", "#5", "#6", "#7"
    };

and does this "#1","#2" refer to the facts? if so, do i need to input somewhere the amount of facts? or does this work like code under so it understands that there is as many facts as lines?

Random randonGenerator = new Random(); //Construct a new random number generator
        int randomNumber = randonGenerator.nextInt(mfacts.length);

And the last question ( i think )

Is the "" stated here where the last message would show?

public void print() {
        for(String fact : facts)
            System.out.print(fact + " ");
        System.out.println();
    }

That example won't run directly on an Android device. It's a console app that you can just copy and paste into a new Workspace. Here's how you can set it up:

On the left you'll see an icon that's a window with angle brackets in it, click that and you can create a new project. Select "Java" for the environment type and name it whatever you want. Make a new file called "Shuffle.java" and paste in the code. Finally run these two commands in the console:

javac Shuffle.java
java Shuffle

Run those again after you make changes if you want to experiment.

The Strings I had ("#1", "#2", etc.) are just placeholders. You could change the contents of the Strings or even change the types completely and it'll still shuffle (though the printing might get messed up).

The space in the print method is just to separate out the facts when they're being printed.

I'll download the FunFacts app later and try to wire everything up for an Android example.

Could you just make a variable called mLastFactPicked and then set it when you show a fact(to the index) . Then just add in a if/else statement checking to make sure it's not the same when you go to display the fact. Then set it to the index of the fact it displays

Just a thought I had, hope it helps..

Stephen.

You can, though when dealing with random numbers you could end up repeatedly failing the check without accomplishing much. It wouldn't matter much for the FunFacts app but it's not ideal.

You'd also have to keep track of all indexes if you didn't want to repeat anything until the end.

Here's the modified FunFacts:

FactBook

public class FactBook {
    public String[] mFacts = {
            "Ants stretch when they wake up in the morning.",
            "Ostriches can run faster than horses.",
            "Olympic gold medals are actually made mostly of silver.",
            "You are born with 300 bones; by the time you are an adult you will have 206.",
            "It takes about 8 minutes for light from the Sun to reach Earth.",
            "Some bamboo plants can grow almost a meter in just one day.",
            "The state of Florida is bigger than England.",
            "Some penguins can leap 2-3 meters out of the water.",
            "On average, it takes 66 days to form a new habit.",
            "Mammoths still walked the earth when the Great Pyramid was being built." };
    private int currentFact = 0;
    private Context context;

    public FactBook(Context context) {
        this.context = context;
    }

    // Just to illustrate when the facts have been exhausted.
    private void notifyNoFactsLeft() {
        Toast.makeText(context, "No more facts! Starting again...", Toast.LENGTH_LONG).show();
    }

    private void shuffleFacts() {
        Random random = new Random();

        for(int i = mFacts.length - 1; i > 0; i--) {
            int swapIndex = random.nextInt(i + 1);
            swapFacts(i, swapIndex);
        }
    }

    private void swapFacts(int from, int to) {
        String temp = mFacts[to];

        mFacts[to] = mFacts[from];
        mFacts[from] = temp;
    }

    public String getFact() {
        if(currentFact == mFacts.length) {
            currentFact = 0;
            shuffleFacts();
            notifyNoFactsLeft();
        }

        return mFacts[currentFact++];
    }
}

FunFactsActivity

public class FunFactsActivity extends Activity {
    private FactBook mFactBook;
    private ColorWheel mColorWheel = new ColorWheel();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fun_facts);

        // Send this activty in as the context for FactBook
        mFactBook = new FactBook(this);

        final TextView factLabel = (TextView) findViewById(R.id.factTextView);
        final Button showFactButton = (Button) findViewById(R.id.showFactButton);
        final RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);

        // Avoid initial repeat
        factLabel.setText(mFactBook.getFact());

        View.OnClickListener listener = new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String fact = mFactBook.getFact();
                factLabel.setText(fact);

                int color = mColorWheel.getColor();
                relativeLayout.setBackgroundColor(color);
                showFactButton.setTextColor(color);
            }
        };
        showFactButton.setOnClickListener(listener);
    }
}

Normally I wouldn't pass in the Context to something like FactBook but I just wanted a quick way to show when the array was being reshuffled.

Forgot to mention this will run through once without sorting. If you want to have it sorted right away, just call shuffleFacts from the constructor.