1
WORDS=("lorem","ipsum","python")
words = random.choice(WORDS)
correct = words
length = 0
while length <len(words):
    i = random.randint(0,len(words))
    print(words[i],end=" ")
    length +=1

I am trying to make a word jumble game, where letters in a word are supposed to mash up. I wanted to ask if I can set a condition so that the ido not repeat the same value over and over again

Any help is appreciated.

Moinuddin Quadri
  • 46,825
  • 13
  • 96
  • 126
  • 2
    [shuffling-a-list-of-objects-in-python](http://stackoverflow.com/questions/976882/shuffling-a-list-of-objects-in-python) might help – SDekov Dec 19 '16 at 14:39
  • http://stackoverflow.com/questions/306400/how-do-i-randomly-select-an-item-from-a-list-using-python – ford prefect Dec 19 '16 at 14:40
  • Possible duplicate of [Pick N items at random from sequence of unknown length](http://stackoverflow.com/questions/9690009/pick-n-items-at-random-from-sequence-of-unknown-length) – frlan Dec 19 '16 at 14:41

4 Answers4

1

You may use random.shuffle which does in-place shuffling. For example:

>>> import random
>>> WORDS = ["lorem","ipsum","python"]  # But you need `list` not `tuple`; 
                                        # tuples are immutable
>>> random.shuffle(WORDS)
>>> WORDS  # List is shuffled
['ipsum', 'python', 'lorem']

For shuffling each word within the tuple you have, you need to do:

shuffled_words= []

for word in WORDS:
    word_list = list(word)  # Typecast `str` to `list`
    random.shuffle(word_list)  # shuffle the list
    shuffled_words.append(''.join(word_list)) # join the list to make `str`

Value hold by shuffled_words list will be:

>>> shuffled_words
['omelr', 'spmiu', 'pynhot']
Moinuddin Quadri
  • 46,825
  • 13
  • 96
  • 126
1

use random.sample (using random.shuffle needs to create a list since it works in-place):

shuffled = "".join(random.sample(words,len(words)))

BTW: Your code is bound to crash because it's using random.randint which may pick len(words) which is out of range. You should have chosen random.randrange

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • I think, creating a copy of list and do shuffle on it is better than doing `join` and calculating `len(words)` on list returned by `random.sample`. May be it is opinion based – Moinuddin Quadri Dec 19 '16 at 14:54
  • More to the point, the use case for `sample` is when you need *fewer* items than there are in the population you're taking a sample from. `sample` is slower than `shuffle` because it does more, e.g. it allocates a separate set to keep track of the items it's already seen. As a result, `y = random.sample(x, len(x))` is an inefficient way to express `y = x[:]; random.shuffle(y)`. – user4815162342 Dec 19 '16 at 15:02
0

I've written up a fairly simple class for you and will detail the usage afterwards

from random import random
from math import floor

class FairDice():
    def __init__(self, sides = 6):
        self.sides = sides
        self.history = []
        self.last = None
    def roll(self):
        number = random()
        roll = int(floor(number * self.sides)) + 1
        return roll

    def statefull_roll(self, remember = None):
        while True:
            roll = self.roll()
            remember = self.sides if remember is None else remember
            if len(self.history) >= remember:
                return None

            if roll not in self.history:
                self.history.append(roll)
                return roll

    def forget_history(self):
        self.history = []  

    def forget_one(self):
        self.history = self.history[1:]

I've created this FairDice class. You can do regular rolls by calling .roll() function. Or you can do rolls that remember what has been rolled by calling the statefull_roll() method. If there are no numbers left then None is returned. You can also call the forget_history() function to forget history.

Here is an example of usage:

dice = FiarDice(25) #creates a 25 sided dice  

for x in range(10):
    print("Regular Roll gives you: ", dice.roll())  

for x in range(25):
    print("Your sort of Roll gives you: ", dice.statefull_roll()) 

print ( dice.statefull_roll()) # Should return none after exhausting all possible characters. 

dice.forget_history() # forgets that any value have been recorded at all  

Lets say that it's ok to repeat letters after 5 rolls. I've added the none.

roll = dice.statefull_roll(remember = 5)  

This will return None after 5 rolls after which all you have to do is...

if roll is None:
    dice.forget_one()  
    roll = dice.statefull_roll(remember = 5)  

forget_one forgets your oldest roll.

What I've written is not much, but works and is flexible enough for usage in your game.

Conic
  • 998
  • 1
  • 11
  • 26
-1

No, but you can loop until you get a number you haven't seen yet:

import random

WORDS = ("lorem", "ipsum", "python")
words = random.choice(WORDS)
correct = words
length = 0
seen = set()
i = 0
while length < len(words):
    while i in seen:
        i = random.randint(0, len(words)-1)
    seen.add(i)

    print(words[i], end=" ")
    length += 1

But (as the commenters have pointed out) there's a much more efficient way to shuffle the characters of a word:

import random

WORDS = ("lorem", "ipsum", "python")
word = random.choice(WORDS)

charlist = list(word)
random.shuffle(charlist)
print(" ".join(charlist), end=" ")
Filip Haglund
  • 13,919
  • 13
  • 64
  • 113