0

On my website I have a button that selects a random quote from a list of quotes and projects the randomly selected quote into a text box. This is done using JavaScript.

Although I have this working, I'd like an additional piece of code that will prevent the directly subsequent quote being the same as the previous. I'd like any quote used to be able appear again however, just not directly following.

If possible I'd also like it so any quote used does not appear again for a minimum of another 3 clicks - but this would just be a bonus.

Anyway the code I currently have is as follows:

<head>    
  <script language="javascript"><!--
    function GenerateQuote(){var aquote=new Array;
      aquote[0]="\"Quote0\"";
      aquote[1]="\"Quote1\"";
      aquote[2]="\"Quote2\""
      aquote[3]="\"Quote3\"";
      aquote[4]="\"Quote4\"";
      aquote[5]="\"Quote5\"";
      aquote[6]="\"Quote6\"";
    rdmQuote=Math.floor(Math.random()*aquote.length);
    document.getElementById("quoteBox").value=aquote[rdmQuote];
    }
  -->
  </script>
</head>

<body>
  <textarea id="quoteBox" readonly></textarea>
  <button onClick="GenerateQuote()">Entertainment & Hobbies</button>
</body>

Thanks in advance; I'm sure it won't be too hard for you brainiacs!

1
  • 1
    The way to do this is to shuffle the list of quotes in some stable way, rather than just picking a random element. Commented Dec 27, 2011 at 14:36

4 Answers 4

1
  1. Fill an array of quotation, then create a copy.
  2. Scramble the copy of the array (you can just use .sort() method or even better you can look for a js implementation of Fisher-Yates alghoritm
  3. Call pop() over the array on each click event so you will generate every time a different quote until the array is fully consumed
  4. When length of the array is zero goto 1)

Reference:

Sign up to request clarification or add additional context in comments.

Comments

1
<head>
    <script type="text/javascript">
!function (){
    var quotes = ["quote0", "quote1", "quote2", "quote3", "quote4", "quote5", "quote6", "quote7", "quote8"],
        shuffleAfter = quotes.length, cur = 0;


    function shuffle( arr ) {
        var l = arr.length, j, i, tmp;

        for( i = l - 1; i > 0; --i ) {
            j = ( Math.random() * ( i + 1 ) ) >>> 0;
            tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        }

        return arr;
    }

    function generateQuote(){
        var r;

        if( cur++ % shuffleAfter === 0 ) {
            shuffle(quotes);
        }

        r = quotes.shift();

        quotes.push( r );

        return r;
    }


    window.generateQuote = generateQuote;
}()
    </script>
</head>
<body>
    <textarea id="quoteBox" readonly></textarea>
    <button onClick="document.getElementById('quoteBox').value = generateQuote()">Entertainment & Hobbies</button>
</body>

Results from calling generateQuote() 27 times:

2,9,7,5,8,1,3,4,6,9,6,1,7,5,4,3,2,8,3,1,6,5,2,7,9,4,8,2

As you can see, after a full cycle the quotes are shuffled again and there is a chance the same quote will appear if it was last in the last cycle and is first in the new cycle. It should be much better than playlist shuffling in my mp3 player at least :P

5 Comments

i like this one, because random isn't done at each call, but this is also the bad part this is less random as shuffle is called only when all quotes are already given once. Depend on the real needs but this one is a nice one for me :)
@malko yes there is a chance that a quote will appear again right after but only after a full cycle. Dunno if that's good enough here.
Thanks for your help, this seems to be the best response! Only problem is I'm having trouble implementing this; do I need to use this code along with my original Function, or is it instead of it? I ask because I need the quote to be projected in the 'quoteBox' text box, and there does not seem to be a mention of it in the code you provided? Sorry, I'm rather new to JavaScript!
@Galeforce the whole thing will replace the whole thing between your <script> tag. Then you need to change onClick="GenerateQuote()" to onClick="generateQuote()"... in javascript functions that are not meant to be invoked as a constructor start with a lower case character so I changed the function name as well.
@Galeforce also the function returns the quote it doesn't put it anywhere, I have edited that in.
0

use

var lastQuote=-1;

outside your function, then

var rdmQuote=lastQuote;
while (rdmQuote==lastQUote) rdmQuote=Math.floor(Math.random()*aquote.length);
lastQuote=rdmQuote;

inside your function

1 Comment

will work nice to avoid direct subsequent call but won't do the extra 3 another click part
0

you can tweak dontRepeatUntil to sweats your need There's certainly better way but this one should work

var latestQuote = []
    , dontRepeatUntil=3
    , rdmQuote = null
    , quotes=[
        "\"Quote0\""
        ,"\"Quote2\""
        ,"\"Quote3\""
        ,"\"Quote4\""
        ,"\"Quote5\""
        ,"\"Quote6\""
    ]
;
function GenerateQuote(){
if(latestQuote.length >= dontRepeatUntil){
    latestQuote = latestQuote.slice(latestQuote.length-dontRepeatUntil+1);
}
    do{
        rdmQuote=Math.floor(Math.random()*quotes.length);
    }while(latestQuote.join(',').match(new RegExp('(^|,)'+rdmQuote+'(,|$)')));
    latestQuote.push(rdmQuote);
    document.getElementById("quoteBox").value=quotes[rdmQuote];
}

1 Comment

Thanks for this response, I've implemented yours as I can't get Esailija's working as of yet. This one seems to be working great though so I'll tick this answer if I still can't get Esailija's to execute.

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.