我试着在python中创建NIM游戏。我研究了几个关于如何总是在NIM比赛中获胜的视频。最后,我找到了一个方法,并且能够在我的代码中实现它。这就是结果..。
#---------------------
# NIM GAME
# Author : Akil Riaz
#---------------------
import random
import time
def welcome_message():
print("""
----------------------------------------------------------------------------
WELCOME TO THE GAME OF NIM!
----------------------------------------------------------------------------
Rules: 1 - The user plays against the computer.
2 - Only 1-3 sticks can be taken at a time.
3 - The person who is left with the last stick is the loser.
4 - Have FUN!
----------------------------------------------------------------------------
""")
def display_board(board):
print("\n----------------------------------------------------------------------------")
print(" ",*board, sep=" ")
print("----------------------------------------------------------------------------\n")
def who_starts(question):
choice = None
while choice not in ("F", "S","f","s"):
choice = input(question)
if choice.upper() == "F":
f_player = "USER"
s_player = "USER"
elif choice.upper() == "S":
f_player = "CMP"
s_player = "CMP"
else:
print("\nInvalid choice. Please re-enter your choice.")
return f_player, s_player
def users_pick(question,minStick,maxStick,userIn,board):
print("\n--USER'S TURN--")
while userIn not in range(minStick, maxStick) or userIn >= len(board):
try:
userIn = int(input(question))
if userIn not in range(minStick, maxStick) or userIn >= len(board):
print("\nYou can cannot choose that many sticks!")
userIn = int(input(question))
except Exception as e:
print("\nAn error has occured.\nError: " + str(e) + "\nPlease re-enter your choice.")
f_player = "CMP"
return userIn, f_player
def update_board(board,move):
valid_moves = (1,2)
if len(board) > move:
for i in range(move):
board.remove("/")
return board
elif len(board) <= move:
if move in valid_moves:
for i in range(move):
board.remove("/")
return board
else:
print("\n" + str(move) + " sticks cannot be taken.\nThe move you made was inavalid. Please re-enter.")
return board
def computers_move(board,userIn,s_player,winning_position,earlier_move):
best_move = 1
print("\n--COMPUTER'S TURN--")
if s_player == "CMP" and winning_position == False:
if len(board) % 4 ==1:
best_move = 0
while best_move not in range(1,len(board)+1):
best_move = random.randint(1,3)
else:
if userIn + earlier_move < 4:
best_move = 4 - (userIn + earlier_move)
winning_position = True
elif userIn + earlier_move > 4:
best_move = 8 - (userIn + earlier_move)
winning_position = True
elif s_player == "USER" or winning_position == True:
best_move = 4 - userIn
earlier_move = best_move
print("\nThe computer chooses to remove...")
time.sleep(1)
print(": " + str(best_move) + " stick(s).")
for sticks in range(best_move):
board.remove("/")
f_player = "USER"
return board, f_player, winning_position, earlier_move
def game_over(board,f_player):
if len(board) == 1 and f_player == "USER":
winner = "COMPUTER"
loser = "USER"
elif len(board) == 1 and f_player == "CMP":
winner = "USER"
loser = "COMPUTER"
else:
winner = None
return winner, loser
def keepPlaying():
while True:
another_go = input("\nDo you want to play again?[Y/N]: ")
if another_go in ("y","Y"):
return True
elif another_go in ("n","N"):
return False
else:
print("\nInavlid choice. Please re-enter.")
def main():
anotherGo = True
welcome_message()
while anotherGo == True:
earlier_move = 0
winning_position = False
nimBoard = ["/","/","/","/","/","/","/","/","/","/","/","/","/","/","/","/","/"]
winner = None
userIn = 0
print("----------------------------------------------------------------------------")
display_board(nimBoard)
print("\nWe begin with " + str(len(nimBoard)) + " sticks.")
f_player, s_player = who_starts("\nDo you want to start first or second? [F for fisrt/S for second]: ")
while len(nimBoard) != 1:
if f_player == "USER":
time.sleep(0.5)
userIn,f_player = users_pick("\nEnter your choice [1, 2 or 3]: ", 1, 4, 20,nimBoard)
nimBoard = update_board(nimBoard,userIn)
display_board(nimBoard)
print("\nThere are " + str(len(nimBoard)) + " stick(s) remaining.")
else:
time.sleep(1)
nimBoard, f_player,winning_position, earlier_move = computers_move(nimBoard,userIn,s_player,winning_position,earlier_move)
time.sleep(1)
display_board(nimBoard)
print("\nThere are " + str(len(nimBoard)) + " stick(s) remaining.")
time.sleep(1)
print("\nFinally...\nOnly one stick remains...")
game_winner, game_loser = game_over(nimBoard,f_player)
time.sleep(1)
print("\nThe " + game_loser + " is left with the last stick and so he is the loser...")
print("\nThe winner of the game is...\n: " + str(game_winner))
anotherGo = keepPlaying()
time.sleep(1)
print("\nThank you for playing!")
print("\n--GAME OVER--")
if __name__ == "__main__":
main()我没有遵循传统的方法,有不同的行/成堆的棍子,因为我发现这太具有挑战性(尽管我将在以后尝试)。这台电脑大部分时间都赢了。但是,如果用户知道我使用的策略,那么它是可以战胜的。
但我仍然觉得还有改进的余地。有什么可以改进的吗?
如果你们能提供任何简单的效率改进或任何形式的逻辑改进,我将不胜感激。
刚刚对程序做了一个简单的改进,计算机使用它的早期移动来确定一个更好的移动来击败用户.谢谢你的投票!)
发布于 2019-08-06 00:22:16
提示1使用条件时,不需要键入x == True,这意味着:
while anotherGo == True:可以是:
while anotherGo:提示2.不要毫无意义地使用time.sleep。它可能会造成混淆,为什么你要使用它,我认为,你使用它只是为了使程序不太快,但.你为什么要那样做?)
提示3使用if/else时,可以将通用代码移到条件的末尾或开头,这样可以删除代码重复:
if f_player == "USER":
time.sleep(0.5)
userIn,f_player = users_pick("\nEnter your choice [1, 2 or 3]: ", 1, 4, 20,nimBoard)
nimBoard = update_board(nimBoard,userIn)
display_board(nimBoard)
print("\nThere are " + str(len(nimBoard)) + " stick(s) remaining.")
else:
time.sleep(1)
nimBoard, f_player,winning_position, earlier_move = computers_move(nimBoard,userIn,s_player,winning_position,earlier_move)
time.sleep(1)
display_board(nimBoard)
print("\nThere are " + str(len(nimBoard)) + " stick(s) remaining.")变成:
if f_player == "USER":
userIn,f_player = users_pick("\nEnter your choice [1, 2 or 3]: ", 1, 4, 20,nimBoard)
nimBoard = update_board(nimBoard,userIn)
else:
nimBoard, f_player,winning_position, earlier_move = computers_move(nimBoard,userIn,s_player,winning_position,earlier_move)
display_board(nimBoard)
print("\nThere are " + str(len(nimBoard)) + " stick(s) remaining.")提示4如果您的所有打印都以换行开始,您可以考虑创建一个助手函数,这样您就不必每次都重新键入它:
def printn(s):
print("\n" + s)提示5为这些“魔术数字”创建常量。当我读到:
users_pick("\nEnter your choice [1, 2 or 3]: ", 1, 4, 20,nimBoard)
提示6您不支付每写字符,使用有意义的变量名称
您可以考虑将其命名为userIn,而不是有一个名为userInput的变量。这是..。更多的字符,但它所做的也更清楚
我需要检查函数定义,看看1,4,20是什么意思。如果您有名为MIN_STICK = 1, MAX_STICKS=4, USERIN=20的常量。
提示1如果多次创建具有相同值的数组,则可以:
# Notice how nice it is not to have to count to see the number of sticks
["/"] * 17而不是:
["/","/","/","/","/","/","/","/","/","/","/","/","/","/","/","/","/"]但我也认为你根本不需要这个数组。您可以简单地将棒数保持为int,并在必要时减少它。这个数组用于打印电路板,所以不应该将显示逻辑与游戏逻辑混合,这样可以使代码更易于维护和读取。
提示2只使用一种命名样式
您可以将snake_case和camelCase混合到您的代码中,这使得代码更难阅读。由于您使用的是Python,所以您应该坚持使用snake_case。
在users_pick方法中,您传递一个高于最大接受值的userIn,这样您的while循环才能工作(我怀疑)。不要这样做,事实上,您根本不应该将userIn作为参数传递,因为您完全忽略了输入。
再次出现在users_pick。这样做:userIn not in range(minStick, maxStick)可能看起来“很棒”,但它也意味着每次您调用它时都会生成一个范围,只为了检查值是否在其中,为什么不使用速度更快、更多的userIn < minStick or userIn > maxStick .合乎逻辑。
我不确定这是否是复制/粘贴错误,但在who_starts方法中,您将f_player和s_player设置为相同的值。
总之,我认为您应该尝试将代码中的显示逻辑和游戏逻辑分开。您在用户输入方面做得很好,但例如,您不需要保留一个/数组来查看游戏的位置。
发布于 2021-05-03 08:27:12
这已经是很久以前的事了,但是已经对我自己的版本进行了编码,对您的代码进行了一些注释。
一般来说:
winning_position和earlier_move变量,只需知道len(board) % 4的值就可以得到所需的一切。详情如下:
当您只需使用min时:
best_move = random.randint(1,min(3,len(board))我提供了一个基于罗塞塔码版本的更简单的版本(但在Rosetta的初始条件下,计算机总是获胜)
#!python3
import random
misere=1 # 0 for "normal game", 1 for "misere game"
if misere: print("Py Nim, misere game: don't take last token")
else: print("Py Nim, normal game: be the one to take last token")
def get_tokens(tokens):
take=0
while (take < 1 or take > min(3,tokens)):
take = int(input("How many tokens would you like to take? "))
tokens = tokens - take
print(f'You take {take} tokens.')
print(f'{tokens} tokens remaining.\n')
if tokens==misere:
print ('You win!')
return 0
elif tokens==0:
print('Strange way of losing, this was a misere game...')
return 0
else:
return comp_turn(tokens)
def comp_turn(tokens):
take = (tokens-misere) % 4
if take==0:
take=random.randint(1,3)
tokens = tokens - take
print (f'Computer takes {take} tokens.')
print (f'{tokens} tokens remaining.\n')
if tokens==misere:
print ('Computer wins!')
return 0
return tokens
tokens = random.randint(12,16)
print (f'We start with {tokens} tokens.')
if (input("Should the computer play first? (y/n)").upper()=="Y"):
tokens=comp_turn(tokens)
while (tokens > 0):
tokens=get_tokens(tokens)如果你用多少个记号来回答电脑是否先玩,你总是可以赢的。
https://codereview.stackexchange.com/questions/160403
复制相似问题