1

I'm wondering how I would go about achieving this effect:

I'm working on a text based game and I store players in a list and I want to be able to iterate through the list until only 1 person remains.

So far I got

While len(mylist) != 1:
 for player in game:
   ...

but where I run into problems is that I want to be able to reverse the for loop if a certain flag gets set. I need to be able to reverse it because a part of the game is being able to reverse the turn order. Anyone have any ideas about how I would go about this?

datmellow
  • 15
  • 1
  • 4
  • 2
    Sounds like you want some [features of a `deque`](http://stackoverflow.com/questions/22772764/circular-queue-python). – TigerhawkT3 Mar 12 '17 at 00:36
  • Agree with @TigerhawkT3. You could put this into a queue, and deque them to another queue, and then when you need to reverse deque the new list. – nullByteMe Mar 12 '17 at 00:40
  • Thanks, I'll look into this lib :) – datmellow Mar 12 '17 at 00:56
  • If you use a python "for" loop, you accept its behavior. If you want to change the way it iterates mid-execution, you may need to take control of the loop. Use a "while" loop, where you control the iteration and termination conditions, maybe? If I misunderstood, and you just want to step through the whole thing in reverse, http://stackoverflow.com/questions/931092/reverse-a-string-in-python (it works on a list, too) – Kenny Ostrom Mar 12 '17 at 01:37
  • Don't know the details of your program but I would write `while len(mylist) > 1` instead of `while len(mylist) != 1`. Lowers the change you end up in an infinite `while` loop. – Elmex80s Mar 12 '17 at 02:37

3 Answers3

0
while 0 < i < range(len(game)):

    if flag:
        i += 1
    else:
        i -= 1

    player = game[i]
Elmex80s
  • 3,428
  • 1
  • 15
  • 23
0

You could use a reverse iterator:

game_iter = game if flag else reversed(game)
for player in game_iter:
   ...
Peter Gerber
  • 1,023
  • 10
  • 13
0

From your description of the problem, it sounds like you are removing characters as you iterate - if that's correct, then it would be easiest to use a deque (double-ended queue). It's a useful collection type available in the standard Python library and worth knowing about. If you wanted to pop characters out of the list, and switch the direction in which you're moving through the list, you can use a boolean flag to change directions as you pop from either the front or the back. Here's an example of how you can do that:

from collections import deque
import random

# Populate empty deck with integers 1 to 10
d = deque()
n = 10
for i in range(n):
    d.append(i+1)

print("Initial deque:")
print(d)

# Note you can also rotate the dequeue:
d.rotate(2)
d.rotate(-2)

# Pop from the list,
# moving from the front of the list (right) to the back of the list (left).
# If a random event happens, we switch directions and pop from the back (left).

print("Popping:")
move_forward = True
while d:
    if(move_forward):
        nxt = d.pop()
        print("Moving forward: %s"%(nxt))
    else:
        nxt = d.popleft()
        print("Moving backward: %s"%(nxt))

    # 70% chance that we continue moving forward
    if( random.random() < 0.7 ):
        move_forward = not move_forward

This initializes a deque with some integers, then iterates through the deque and removes items, reversing direction 70% of the time. Here's the output of the program, which I believe is the behavior you were looking for:

Initial deque:
deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
Popping:
Moving forward: 10
Moving backward: 1
Moving backward: 2
Moving forward: 9
Moving backward: 3
Moving backward: 4
Moving forward: 8
Moving forward: 7
Moving backward: 5
Moving forward: 6

Edit: If you wanted to save the characters, instead of losing them, when you pop, you can create a new deque called e, and right after you call nxt = d.pop() or nxt = d.popleft(), you can append it to e: e.append(nxt). (I don't see any elegant way to preserve the original order of the characters though.)

charlesreid1
  • 4,360
  • 4
  • 30
  • 52