我目前正在尝试编写一个程序,它是一个零重力的连接四游戏,这意味着你可以从棋盘的一个区域放置这个棋子,我正在努力选择一个柱子并从顶部放置我的棋子。此外,我的程序会询问用户他们希望在棋盘上放置多少块,这样会让游戏变得更难。在我输入例如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)
提前感谢!
答案 0 :(得分:5)
正如您已经注意到的那样,调试您所拥有类型的if
长串语句非常困难。事实上,大多数写得很好的程序很少包含任何东西,只要你的move
功能。 Linus Torvalds在 linux内核的style guide中说:
功能应该简短而且甜美,只做一件事。他们应该适合一个或 两个屏幕的文本(ISO / ANSI屏幕大小是80×24,我们都知道),并做一个 事情并做得很好。
换句话说,甚至(特别是!)当你编写像现代操作系统内核那样复杂的东西时,你的函数不应该超过48行代码 - 而且他在谈论 c 那里的代码,比Python更冗长。你在这里打破这条规则非常糟糕;您的move
功能超过100行!
所以我的答案不是一个真正的答案,而是一个元答案。将move
功能分解为几个较小的功能。对于您需要的每种输入,编写一个单独的函数来获取输入,确保它是正确的,并将其转换为程序可以使用的值。尽可能多地将上述if
逻辑转换为这些函数。然后让你的move
函数调用这些函数,并应用任何必要的顶级逻辑。我看到至少三个,并且可能五个或六个不同的函数在一个巨大的函数中混合在一起。
一旦你将它分开,用打印语句单独测试每个功能,以确保它们按照你的期望进行。一旦你完成了,并且你确定它们的行为符合预期,你就会知道你的问题在顶级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
从用户获取输入并基于它转换表。现在循环包含您需要的所有顶级逻辑。然后在程序的底部,执行此操作以启动主程序。 (这只是在Python中调用main
的标准方法;不要担心__name__
目前的含义:
if __name__ == '__main__':
main()
我知道我仍然没有回答你的实际问题;但我认为这些东西实际上比你正在寻找的特定bug更重要。我现在会开始尝试找到它。