2013-02-16 11 views
6

Sto provando a riavviare un programma utilizzando un if-test basato sull'input dell'utente.Come si riavvia un programma in base all'input dell'utente?

Questo codice non funziona, ma è circa quello che sto cercando:

answer = str(raw_input('Run again? (y/n): ')) 

if answer == 'n': 
    print 'Goodbye' 
    break 
elif answer == 'y': 
    #restart_program??? 
else: 
    print 'Invalid input.' 

Quello che sto cercando di fare è:

  • se si risponde y - il riavvio del programma dall'alto
  • se si risponde n - il programma termina (quella parte funziona)
  • se si immette qualcos'altro, si deve stampare "input non valido. per favore inserisci y o n ... 'o qualcosa, e chiedi di nuovo per un nuovo input.

ho avuto molto vicino a una soluzione con un "vero while", ma il programma sia appena riavviato non importa ciò che si preme (tranne n), o si chiude non importa quello che preme (tranne y). Qualche idea?

risposta

4

Prova questo:

while True: 
    # main program 
    while True: 
     answer = raw_input('Run again? (y/n): ') 
     if answer in ('y', 'n'): 
      break 
     print 'Invalid input.' 
    if answer == 'y': 
     continue 
    else: 
     print 'Goodbye' 
     break 

Il ciclo while interno ripete fino a quando l'ingresso è o 'y' o 'n'. Se l'input è 'y', il ciclo while si riavvia (la parola chiave continue salta il codice rimanente e passa direttamente alla successiva iterazione). Se l'input è 'n', il programma termina.

Si noti inoltre che la conversione di raw_input in un str() è ridondante poiché raw_input restituisce già una stringa.

1

Ecco un modo per farlo con un decorator divertente:

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() 

In definitiva, credo che avete bisogno di 2 cicli while. È necessario un ciclo di parentesi tra parentesi per la parte che richiede la risposta in modo da poter richiedere nuovamente se l'utente fornisce un input non valido. È necessario un secondo che verificherà che la risposta corrente sia 'y' e continui a eseguire il codice finché la risposta non è 'y'.

2

Utilizzando uno ciclo while:

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]: 
+0

Ok, Ok. Giusto. Non hai * bisogno di * 2 'while' loop - Ma penso ancora che sia più pulito in questo modo :) - In realtà mi è piaciuta la mia soluzione di decoratore, ma potrebbe essere un po 'avanzato per una domanda come questa ... – mgilson

+0

@ mgilson - Forse. Ma il decoratore * è certamente * abbastanza ordinato, +1. – root

0

creo questo programma:

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

+2

Questo è troppo, troppo lungo per spiegare in modo conciso come riavviare un programma. –

10

Questa linea sarà incondizionatamente riavviare il programma in esecuzione da zero:

os.execl(sys.executable, sys.executable, *sys.argv) 

Uno dei suoi vantaggi rispetto ai suggerimenti rimanenti è che il programma stesso verrà nuovamente letto.

Questo può essere utile se, ad esempio, si modifica il codice in un'altra finestra.

+1

Questo non funziona su Windows se Python è installato in un percorso con spazi – Beefster

+1

@Beefster questo può essere risolto utilizzando invece 'subprocess.call (sys.executable + '"' + os.path.realpath (__ file__) + ' "')' –

+0

@EladAvron Il problema con questa soluzione è che crea una catena infinita di sottoprocessi che finirà per causare l'esaurimento della memoria del sistema operativo. Non sono sicuro di cosa succede a quel punto. – Beefster

2

È possibile farlo semplicemente tramite le funzioni definite dall'utente.Il codice più o meno così:

def script() 
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() 

Naturalmente si può cambiare un sacco di cose qui. Cosa viene detto, ciò che lo script accetterà come input valido, i nomi di variabili e funzioni. Puoi semplicemente nidificare l'intero programma in una funzione definita dall'utente (Ovviamente devi dare tutto all'interno di un trattino extra) e farlo riavviare in qualsiasi momento usando questa riga di codice: myfunctionname(). Altro su questo here.

+0

Certo, fammi sapere se questo fallisce e proverò a risolvere –

Problemi correlati