Using *rand in a choice

This discussion is also relevant: Non repeatable strings (code example here) You can create a random shuffle of 20 names, show 5 and then another 5.

1 Like

Using a shuffled array is nice because you don’t need variables to track whether a name was seen before; the shuffling ensures you see everything once, in a random order.

You’ve already gotten your answer, but I thought I’d share my crack at it just for fun:

*create name ""

*label name_randomizer
*temp offset 0
*temp human_name_1 "Arthur"
*temp human_name_2 "Alice"
*temp human_name_3 "Christopher"
*temp human_name_4 "Beatrice"
*temp human_name_5 "Frederick"
*temp human_name_6 "Elizabeth"
*temp human_name_7 "James"
*temp human_name_8 "Grace"
*temp human_name_9 "Louis"
*temp human_name_10 "Matilda"
*temp human_name_11 "Nicholas"
*temp human_name_12 "Penolope"
*temp human_name_13 "Richard"
*temp human_name_14 "Sophie"
*temp human_name_15 "Shiloh"
*temp human_name_16 "Quinn"
*temp human_name_17 "Emerson"
*temp human_name_18 "Marlowe"
*temp human_name_19 "Rory"
*temp human_name_20 "Rowan"
*gosub shuffle_array "human_name" 20

*label name_choice
What is your name?
    *set name human_name[1+offset]
    *set name human_name[2+offset]
    *set name human_name[3+offset]
    *set name human_name[4+offset]
    *set name human_name[5+offset]
  #Show me more
    *if (offset < 15)
      *set offset + 5
      *goto name_choice
      You've seen all the names. Rerolling...
      *goto name_randomizer
Your name is ${name}?
  #No, let me pick again.
    *goto name_choice

*label shuffle_array
*params array array_length
*temp i 1
*temp j 0
*label shuffle_array_loop
*if (i < array_length)
  *rand j i array_length
  *if (j != i)
    *temp val_i {(array&"_")&"${i}"}
    *set {(array&"_")&"${i}"} {(array&"_")&"${j}"}
    *set {(array&"_")&"${j}"} val_i
  *set i + 1
  *goto shuffle_array_loop

Wow, this is a piece of art. 14 lines for the core logic. Very compact and reusable. I like the way you used redirection to sort any given array. Well done!

Two minor suggestions:

  • you can skip the test j!=i and always swap even if they are equal
  • if you do *temp prefix (array&"_") then you can do simply *set {prefix&i} {prefix&j} (more readable)

Agree - that’s a level of logic I hadn’t considered for iterating through a list. Very clever.

This topic was automatically closed 24 hours after the last reply. If you want to reopen your WiP, contact the moderators.