-1

我目前正在尝试编写一个程序,该程序是一个零重力的四连棋游戏,这意味着您可以从棋盘的任何一侧放置棋子,我目前正在选择一列并从顶部放置棋子。我的程序还询问用户他们想在棋盘上放置多少块,使游戏更难。例如,当我键入 C8 时,它会通过列表中的第 8 行查看每个列表中的第 8 个元素。有什么想法吗?

我编辑的代码如下:

#this imports random for my blocks 
import random




#this makes my board
table = [[ "   ","C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10"],
         [ " R1|", " |", " |", " |", " |", " |", " |", " |", " |", " |", " |"],
         [ " R2|", " |", " |", " |", " |", " |", " |", " |", " |", " |", " |"],
         [ " R3|", " |", " |", " |", " |", " |", " |", " |", " |", " |", " |"],
         [ " R4|", " |", " |", " |", " |", " |", " |", " |", " |", " |", " |"],
         [ " R5|", " |", " |", " |", " |", " |", " |", " |", " |", " |", " |"],
         [ " R6|", " |", " |", " |", " |", " |", " |", " |", " |", " |", " |"],
         [ " R7|", " |", " |", " |", " |", " |", " |", " |", " |", " |", " |"],
         [ " R8|", " |", " |", " |", " |", " |", " |", " |", " |", " |", " |"],
         [ " R9|", " |", " |", " |", " |", " |", " |", " |", " |", " |", " |"],
       [ "R10|" ," |", " |", " |", " |", " |", " |", " |", " |", " |", " |"]]
#my two different player pieces
player1="#|"
player2="@|"
block="B|"
row=11
columns=11
#this is a function i can call to print the table
def printTable(table):
    for row in table:
        for value in row:
            print (value,end=' ')
        print ('\n')

#this ask the user how many blocks they want on their board then places it on there
def block(table):
    blockQuestion=(input("how many blocks would you like to put on the table? \n (please enter a number between 1 and 25)"))
    number=blockQuestion[:2]
    number=int(number)
    number=number-1
    print("this is number ",number)
    count = 0      
    number=int(number)
    while number >= count:
        x=random.randint(1,10)
        y=random.randint(1,10)
        print("x and y ", x,y)

        table[x][y]="B|"
        count +=1

    printTable(table)
    move()



#this is my function to ask the user for their move.
def move():
    move=input("Please choose where you would like to drop your marker \n (For instance C1, R5)")
    move.split()
    rorc=move[0:1]
    ans=move[1:3]
    answer=int(ans)

    print(rorc," ",answer)

    if "R" in move:
        row(answer)

    if "C" in move:
        col(answer)
#this is my function if the user wants to go by row
def row(answer):
    side=input("would you like to insert it from the right or left \n Please type R for right or L for left ")

    if "R" in side:

        try:
            table[answer].reverse()

            blockCheck=table[answer].index("B|")
            if blockCheck == 0:
                print ("you can not place a peice there because of the block")
                tryAgain()                   
        except:
            try:
                p1Check=table[answer].index("#|")
                if p1Check is 0:
                    print ("you can not place a peice there due to the opponents marker")
                    tryAgain()
            except:
                try:
                    p2Check=table[answer].index("@|")
                    if p2check is 0:
                        print ("you can not place a peice there due to the opponents marker")
                        tryAgain()
                except:
                    print('hi')
    try:
        tits=max(blockCheck,p1Check,p2Check)
        print("All three checks",tits)

    except:
        try:
            tits=max(blockCheck,p1Check)
            print("this is bc and p1c",tits)
        except:
            tits=(blockCheck)
            print("this is block check",tits)
    table[answer].reverse()
    table[answer][-tits]= (player1)
    printTable(table)
#this is my function if the user wants to go by columns
def col(answer):
    side=input("would you like to insert it from the top or bottom \nPlease type T for top or B for bottom")
    answer=int(answer)
    if "T" in side:
        try:   
            blockCheck=table[:][answer].index("B|")

            print("blockCheck ", blockCheck)
            if blockCheck == 1:
                print ("you can not place a peice there because of the block")
                tryAgain()
        except:
            try:
                p1Check=table[answer].index("#|")
                if p1Check is 1:
                    print ("you can not place a peice there due to the opponents marker")
                    tryAgain()
            except:
                try:
                    p2Check=table[answer].index("@|")
                    if p2check is 1:
                        print ("you can not place a peice there due to the opponents marker")
                        tryAgain()
                except:
                    print("whaa")       
        try:
            tits=min(blockCheck,p1Check,p2Check)
            print("All three checks",tits)

        except:
            try:
                tits=min(blockCheck,p1Check)
                print("this is bc and p1c",tits)
            except:
                try:
                    tits=(blockCheck)
                    print("this is block check",tits)
                except:
                    tits=11
        table[tits-1][answer]= (player2)
        printTable(table)
#function to restart the program to the move function
def tryagain():
    tryAgain=input('try again \nPlease type y or n ')
    if tryAgain == 'y':
        move()
    elif tryAgain =='n':
        bash





#calls the function to start the program 
block(table)

提前致谢!

4

1 回答 1

5

正如您无疑已经注意到的那样,调试if您在此处拥有的那种长链语句非常困难。事实上,大多数编写良好的程序很少包含只要你的move函数的任何东西。Linus Torvalds 在他的linux 内核风格指南中说:

函数应该短小精悍,只做一件事。它们应该适合一两屏文本(众所周知,ISO/ANSI 屏幕尺寸为 80×24),并且做好一件事。

换句话说,即使(尤其是!)当你在编写像现代操作系统内核这样极其复杂的东西时,你的函数也不应该占用超过 48 行代码——他说的是那里的c代码,也就是比 Python 更冗长。您在这里非常严重地违反了该规则;您的move函数超过 100 行!

所以我的答案不是真正的答案,而是一个元答案。将该move功能分解为几个较小的功能。对于您需要的每种输入,编写一个单独的函数来接受输入,确保它是正确的,并将其转换为您的程序可以使用的值。尽可能多地将上述if逻辑转移到这些函数中。然后让你的move函数调用这些函数,并应用任何必要的顶级逻辑。我看到至少三个,可能六个不同的功能在一个巨大的功能中融合在一起

一旦你把它分开,用 print 语句单独测试每个函数,以确保它们在做你期望的事情。一旦你这样做了,并且你确定它们的行为符合预期,你就会知道你的问题被隔离在顶层move函数中;从那里开始,调试应该不难——无论是对我们还是对你!


您的编辑使事情变得更好。但我很清楚,你对函数应该如何运作没有直观的感觉。考虑一下您是如何重构上述代码的。你写了一个函数。然后在该函数结束时,调用另一个函数。然后在该函数结束时调用另一个函数。你一遍又一遍地链接函数。如果我在上面绘制了您的代码的调用图,它看起来像这样:

block
 |
 -> move
     |
     -> row | col
         |
         -> ...keep on calling new functions...          

这不是它应该如何工作的。相反,您应该有一个主函数来调用其他函数并获取它们返回的值。考虑这个简单的例子:

def get_val():
    x = None
    while x is None:
        x = raw_input('Give me a value: ')
        try:
            x = int(x)
        except ValueError:
            print('Value must be an integer')
            x = None
    return x

def transform_val(x):
    return x * 2

def main():
    val = get_val()
    val = transform_val(val)
    print(val)

你看到上面的两个函数没有调用其他函数。他们只是做一些事情然后返回。调用图如下所示:

main
 |
 -> get_val
  <- |
 |
 -> transform_val
  <- |
 |

您会看到,在这种情况下,main它位于程序的“顶层”,它控制着一切。重组你的代码看起来像这样。您应该有一个 main 函数来调用对您的表进行操作的其他函数。由于table是可变的,这些大多不需要return任何东西,但它们绝对不应该以另一个函数调用结束。将其移至main函数中:

def main():
    # define some variables here
    block(table)
    while no_winner(table):
        move(table)

在这里no_winner查看桌子,看看是否有人赢了,或者是否没有更多的动作;它会做 return一些事情——对还是错,取决于是否有可能进行另一次移动。move从用户那里获取输入并根据它转换表格。现在循环包含您需要的所有顶级逻辑。然后在程序的底部,执行此操作以启动您的主程序。(这只是main在 Python 中调用的标准方法;现在不用担心是什么__name__意思:

if __name__ == '__main__':
    main()

我知道我仍然没有回答你的实际问题;但我认为这些东西实际上比你正在寻找的特定错误更重要。不过,我现在就开始尝试找到它。

于 2012-05-07T00:01:30.567 回答