Skip to main content
 首页 » 编程设计

python之python中的递归游戏问题

2025年05月04日14yjmyzz

我正在用 python 创建一个扫雷版本,但遇到了一个小问题。在这段代码中:

if winGame(mines): 
        printWorld(gameMap) 
        print 'You Win!' 
        answer = raw_input('Would you like to play again?') 
        if answer == 'y': 
            minesweeper() 
        else: 
            print 'Thanks for playing!' 
            break 

它再次调用扫雷函数,重新开始游戏。此代码在 while True 内:与游戏代码的其余部分一起循环。唯一的问题是,如果重新开始游戏,然后赢了,说不想再玩了,这并没有打破循环。我认为这与我使用递归再次调用函数这一事实有关。目前唯一可行的方法是使用 sys.exit(),但如果可行的话,我更愿意使用更合法的解决方案。

完整代码如下:

#Minesweeper Game 
 
#difficulty levels 
#make it look better text based 
 
from random import * 
import sys 
 
gameMap = ''' 
#123456789# 
1?????????1 
2?????????2 
3?????????3 
4?????????4 
#123456789#''' 
 
row = 0 
col = 0 
coord = [] 
response = '' 
numMines = 5 
mines = [] 
answer = '' 
 
 
#This runs the game 
def minesweeper(): 
 
    global gameMap 
    global row 
    global col 
    global coord 
    global mines 
    global response 
    global answer 
 
    #resets the gameboard after replaying. 
    gameMap = ''' 
#123456789# 
1?????????1 
2?????????2 
3?????????3 
4?????????4 
#123456789#''' 
 
    #generates the mines 
    generateMines() 
 
    #converts the world into a list of lists. exception is for when playing again since 
    #it would try to convert it to a list of lists again 
    try: 
        initWorld() 
    except Exception, e: 
        pass 
 
    #main loop of the game. 
    while True:                       
 
        #checks to see if you won the game 
        if winGame(mines): 
            printWorld(gameMap) 
            print 'You Win!' 
            answer = raw_input('Would you like to play again?') 
            if answer == 'y': 
                minesweeper() 
            else: 
                print 'Thanks for playing!' 
                break 
 
        #joins the list together so it can be printed 
        printWorld(gameMap) 
        print mines 
 
        #gets user input and converts it to an int, then adds coords to a list 
        getCoord()         
 
        #asks user what they want to do 
        clearOrFlag() 
 
        if response.lower() == 'c': 
            if isMine(mines): 
                answer = raw_input('Would you like to play again?') 
                if answer == 'y': 
                    minesweeper() 
                else: 
                    print 'Thanks for playing!' 
                    break 
            else: 
                clearSpace(mines) 
                print '\n' 
        elif response.lower() == 'f': 
            flagSpace() 
            print '\n' 
 
#randomly generates the mines and checks for duplicates 
def generateMines(): 
    global numMines 
    global mines 
    i = 0 
    mines = [] 
 
    while i < numMines: 
        mines.append([randint(1,4),randint(1,9)]) 
        i += 1 
 
    if checkDuplicateMines(mines): 
        generateMines() 
 
#gets coordinates from the user 
def getCoord(): 
 
    global row 
    global col 
    global coord 
    global gameMap 
 
    row = 0 
    col = 0 
    coord = [] 
 
    try: 
        row = raw_input('Enter an Row: ') 
        row = int(row) 
        col = raw_input('Enter a Column: ') 
        col = int(col) 
    except ValueError: 
        print 'Invalid Coordinates \n' 
        getCoord() 
 
    coord.append(row) 
    coord.append(col) 
 
def isMine(mines): 
 
    global coord 
    global gameMap 
 
    for x in mines: 
            if coord == x: 
                showSolution(mines, gameMap) 
                return True 
 
#asks user if they want to clear or flag a space 
def clearOrFlag(): 
 
    global response 
 
    response = raw_input("Clear (c), Flag/Unflag (f)") 
 
#clears a space. if it's a mine, the player loses. If not it will write the 
#number of surrounding mines to the space. Might break this up later. 
def clearSpace(mines): 
 
    #checks to see if selected square is a ? (playable).  
    global gameMap 
    global row 
    global col 
    global coord 
 
    if gameMap[row][col] == '?' or gameMap[row][col] == 'F':                        
        gameMap[row][col] = str(countMines(mines)) 
 
#flags a space, or unflags it if already flagged. 
def flagSpace(): 
 
    global gameMap 
    global row 
    global col 
 
    try: 
        if gameMap[row][col] == '?' : 
            gameMap[row][col] = 'F' 
        elif gameMap[row][col] == 'F': 
            gameMap[row][col] = '?' 
    except Exception, OutOfBounds: 
        print 'Invalid Coordinates \n' 
 
#Prints the world 
def printWorld(gameMap): 
 
    #just prints spaces to keep things tidy 
    print '\n' * 100  
 
    for row in gameMap: 
        print ' '.join(row) 
        print '\n' 
 
    print '\n' 
 
#initializes the world so it can be printed 
def initWorld(): 
 
    global gameMap 
 
    # convert the gamemap into a list of lists 
    gameMap = gameMap.split('\n') 
    del gameMap[0] 
 
    for index in range(0, len(gameMap)): 
        gameMap[index] = list(gameMap[index]) 
 
#prints the gameBoard with all of the mines visible 
def showSolution(mines, gameMap): 
 
    for x in mines: 
        gameMap[x[0]][x[1]] = 'M'  
 
 
    printWorld(gameMap) 
    print 'You Lose' 
 
#counts the number of surrounding mines in a space 
def countMines(mines): 
    global row 
    global col 
    count = 0 
 
    #theres probably a much better way to do this     
    for x in mines: 
        if [row+1,col] == x: 
            count += 1 
        if [row-1,col] == x: 
            count += 1 
        if [row,col+1] == x: 
            count += 1 
        if [row,col-1] == x: 
            count += 1 
        if [row+1,col+1] == x: 
            count += 1 
        if [row+1,col-1] == x: 
            count += 1 
        if [row-1,col+1] == x: 
            count += 1 
        if [row-1,col-1] == x: 
            count += 1 
 
    return count 
 
#counts the number of flags on the board 
def countFlags(mines): 
 
    global gameMap 
    numFlags = 0 
 
    for i in range (0, len(gameMap)): 
        for j in range (1, len(gameMap[0])-1): 
            if gameMap[i][j]=='F': 
                numFlags += 1 
 
    if numFlags == len(mines): 
        return True 
    else: 
        return False 
 
#counts the number of mines flagged 
def minesFlagged(mines): 
 
    global gameMap 
    count = 0 
 
    for x in mines: 
        if gameMap[x[0]][x[1]] == 'F': 
            count += 1 
 
    if count == numMines: 
        return True 
    else: 
        return False 
 
#checks to see if there were duplicate mines generated 
def checkDuplicateMines(mines): 
 
    mines.sort() 
 
    for x in range(0, len(mines)-1): 
        if mines[x] == mines[x+1]: 
            return True 
        x += 1 
 
    return False 
 
#checks to see if player won the game 
def winGame(mines): 
 
    if countFlags(mines): 
        if minesFlagged(mines): 
            return True 
    else: 
        return False 
 
minesweeper() 

请您参考如下方法:

如果你想使用递归,返回函数调用,不要只是调用它。

if winGame(mines): 
        printWorld(gameMap) 
        print 'You Win!' 
        answer = raw_input('Would you like to play again?') 
        if answer == 'y': 
            return minesweeper() 
        else: 
            print 'Thanks for playing!' 
            return 

这样,当您的一个递归函数结束时,它将 None 返回到前一个函数,它再次将 None 返回到前一个函数,依此类推,直到最后一个调用 return 结束整个递归循环。

它可能不是这个问题的最佳解决方案(看看 MathieuW 的回答,基本上是一样的)但它适用于任何情况,并且主要用于递归函数。