I'm trying to restart a program using an if-test based on the input from the user.
This code doesn't work, but it's approximately what I'm after:
answer = str(raw_input('Run again? (y/n): '))
if answer == 'n':
print 'Goodbye'
break
elif answer == 'y':
#restart_program???
else:
print 'Invalid input.'
What I'm trying to do is:
I got really close to a solution with a "while true" loop, but the program either just restarts no matter what you press (except n), or it quits no matter what you press (except y). Any ideas?
This question is related to
python
You can do this simply with a function. For example:
def script():
# program code here...
restart = raw_input("Would you like to restart this program?")
if restart == "yes" or restart == "y":
script()
if restart == "n" or restart == "no":
print "Script terminating. Goodbye."
script()
Of course you can change a lot of things here. What is said, what the script will accept as a valid input, the variable and function names. You can simply nest the entire program in a user-defined function (Of course you must give everything inside an extra indent) and have it restart at anytime using this line of code: myfunctionname()
. More on this here.
Using one while loop:
In [1]: start = 1
...:
...: while True:
...: if start != 1:
...: do_run = raw_input('Restart? y/n:')
...: if do_run == 'y':
...: pass
...: elif do_run == 'n':
...: break
...: else:
...: print 'Invalid input'
...: continue
...:
...: print 'Doing stuff!!!'
...:
...: if start == 1:
...: start = 0
...:
Doing stuff!!!
Restart? y/n:y
Doing stuff!!!
Restart? y/n:f
Invalid input
Restart? y/n:n
In [2]:
I create this program:
import pygame, sys, time, random, easygui
skier_images = ["skier_down.png", "skier_right1.png",
"skier_right2.png", "skier_left2.png",
"skier_left1.png"]
class SkierClass(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("skier_down.png")
self.rect = self.image.get_rect()
self.rect.center = [320, 100]
self.angle = 0
def turn(self, direction):
self.angle = self.angle + direction
if self.angle < -2: self.angle = -2
if self.angle > 2: self.angle = 2
center = self.rect.center
self.image = pygame.image.load(skier_images[self.angle])
self.rect = self.image.get_rect()
self.rect.center = center
speed = [self.angle, 6 - abs(self.angle) * 2]
return speed
def move(self,speed):
self.rect.centerx = self.rect.centerx + speed[0]
if self.rect.centerx < 20: self.rect.centerx = 20
if self.rect.centerx > 620: self.rect.centerx = 620
class ObstacleClass(pygame.sprite.Sprite):
def __init__(self,image_file, location, type):
pygame.sprite.Sprite.__init__(self)
self.image_file = image_file
self.image = pygame.image.load(image_file)
self.location = location
self.rect = self.image.get_rect()
self.rect.center = location
self.type = type
self.passed = False
def scroll(self, t_ptr):
self.rect.centery = self.location[1] - t_ptr
def create_map(start, end):
obstacles = pygame.sprite.Group()
gates = pygame.sprite.Group()
locations = []
for i in range(10):
row = random.randint(start, end)
col = random.randint(0, 9)
location = [col * 64 + 20, row * 64 + 20]
if not (location in locations) :
locations.append(location)
type = random.choice(["tree", "flag"])
if type == "tree": img = "skier_tree.png"
elif type == "flag": img = "skier_flag.png"
obstacle = ObstacleClass(img, location, type)
obstacles.add(obstacle)
return obstacles
def animate():
screen.fill([255,255,255])
pygame.display.update(obstacles.draw(screen))
screen.blit(skier.image, skier.rect)
screen.blit(score_text, [10,10])
pygame.display.flip()
def updateObstacleGroup(map0, map1):
obstacles = pygame.sprite.Group()
for ob in map0: obstacles.add(ob)
for ob in map1: obstacles.add(ob)
return obstacles
pygame.init()
screen = pygame.display.set_mode([640,640])
clock = pygame.time.Clock()
skier = SkierClass()
speed = [0, 6]
map_position = 0
points = 0
map0 = create_map(20, 29)
map1 = create_map(10, 19)
activeMap = 0
obstacles = updateObstacleGroup(map0, map1)
font = pygame.font.Font(None, 50)
a = True
while a:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
speed = skier.turn(-1)
elif event.key == pygame.K_RIGHT:
speed = skier.turn(1)
skier.move(speed)
map_position += speed[1]
if map_position >= 640 and activeMap == 0:
activeMap = 1
map0 = create_map(20, 29)
obstacles = updateObstacleGroup(map0, map1)
if map_position >=1280 and activeMap == 1:
activeMap = 0
for ob in map0:
ob.location[1] = ob.location[1] - 1280
map_position = map_position - 1280
map1 = create_map(10, 19)
obstacles = updateObstacleGroup(map0, map1)
for obstacle in obstacles:
obstacle.scroll(map_position)
hit = pygame.sprite.spritecollide(skier, obstacles, False)
if hit:
if hit[0].type == "tree" and not hit[0].passed:
skier.image = pygame.image.load("skier_crash.png")
easygui.msgbox(msg="OOPS!!!")
choice = easygui.buttonbox("Do you want to play again?", "Play", ("Yes", "No"))
if choice == "Yes":
skier = SkierClass()
speed = [0, 6]
map_position = 0
points = 0
map0 = create_map(20, 29)
map1 = create_map(10, 19)
activeMap = 0
obstacles = updateObstacleGroup(map0, map1)
elif choice == "No":
a = False
quit()
elif hit[0].type == "flag" and not hit[0].passed:
points += 10
obstacles.remove(hit[0])
score_text = font.render("Score: " + str(points), 1, (0, 0, 0))
animate()
Link: https://docs.google.com/document/d/1U8JhesA6zFE5cG1Ia3OsTL6dseq0Vwv_vuIr3kqJm4c/edit
This line will unconditionally restart the running program from scratch:
os.execl(sys.executable, sys.executable, *sys.argv)
One of its advantage compared to the remaining suggestions so far is that the program itself will be read again.
This can be useful if, for example, you are modifying its code in another window.
Here's a fun way to do it with a decorator:
def restartable(func):
def wrapper(*args,**kwargs):
answer = 'y'
while answer == 'y':
func(*args,**kwargs)
while True:
answer = raw_input('Restart? y/n:')
if answer in ('y','n'):
break
else:
print "invalid answer"
return wrapper
@restartable
def main():
print "foo"
main()
Ultimately, I think you need 2 while loops. You need one loop bracketing the portion which prompts for the answer so that you can prompt again if the user gives bad input. You need a second which will check that the current answer is 'y'
and keep running the code until the answer isn't 'y'
.
Source: Stackoverflow.com