mit-scratch

why does pick random doesnt pick some numbers in scratch?


I am creating a mini housie game in scratch and I have used the pick random block to pick between 1 and 27. And I have 27 backdrops with 1 to 27 numbers written on them. However I notice that after about 21-22 numbers the random picker is not able to pick any of the remaining numbers. Below is how my code looks like - enter image description here

How can I fix this code so as to make sure it picks everything from 1 to 27 randomly?


Solution

  • Your problem is due to how the "contains" block works. It is natural to assume that it would compare the value you give it to each value in the list, and would evaluate to "true" if there's a match and "false" if there's not. But unfortunately, that's not what it does. Instead, it treats the list as a single string formed by concatenating all of the elements in the list (separating each element with a space), and then checks to see if the thing you asked was contained by the list is in that string.

    You can see this in action if you run this snippet:

    enter image description here

    You'll find that your sprite does in fact say "Hello", even though the list definitely does not contain "2 3" anywhere!

    In your script, this has the effect of excluding some of the single-digit numbers, depending on what order the numbers are chosen. For example, the number 1 is highly unlikely to be picked, because almost half the numbers you could pick have the digit 1 in them. Likewise 2. The other digits have much lower chances of being excluded, but it's a non-zero chance, and at least some of them tend to be excluded for the same reason.

    In other words, by the time you get to around 20 to 22 of the 27 numbers picked, the rest of the numbers that are left will be treated as though they were picked, even though they weren't.

    You can get your script to work if you implement a proper "contains" block, like this:

    enter image description here

    Then you can use it in your main script like this:

    enter image description here All that said, your approach to picking random numbers isn't ideal, because you have to do this looping and repeatedly picking and ignoring some numbers, more and more as the loop progresses. This can become entirely intractable if you start having to pick from a larger range of numbers.

    It would be better to implement as a proper "shuffle". There's a standard algorithm for this, called the Fisher-Yates shuffle. Essentially, you initialize your list with all the numbers you want to choose from, start at the first element, pick a random other element to swap with that element (the element you're on could be picked), swap the values, and then move on to the next element. With each iteration, you're picking a new element only from those remaining in the list.

    I leave the implementation of the Fisher-Yates shuffle in your Scratch program to you and other readers. It's an excellent programming exercise. :)