principlepythonMinor
A game of NIM (Basic AI strategy)
Viewed 0 times
gamenimbasicstrategy
Problem
I tried creating the game of NIM in python. I researched a couple of videos on how to always win at NIM. Eventually, I found a method and i was able to implement it in my code. This is the result...
```
#---------------------
# 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: " +
```
#---------------------
# 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: " +
Solution
General coding style and other useful tips
Tip 1
When using conditions, you don't need to type
can be :
Tip 2 Don't use
Tip 3 When you use if/else, you can move the common code to the end or the beginning of the conditions, this removes code duplication :
Becomes :
Tip 4 If all your prints start with a line break, you could consider creating an helper function so you don't have to retype it every time :
Tip 5 Create constants for those "magic numbers". When I read :
Tip 6 You don't pay per character written, use meaningful variable names
Instead of having a variable named
I need to go check the function definition to see what
Python tips
Tip 1 If you create an array with the same value multiple times, you can do :
instead of :
But I also think you don't need this array at all. You could simply keep the number of sticks available as an
Tip 2 Use only one naming style
You mix
Code "cleanness"
In the
In
I'm not sure if it's a copy/paste error, but in the
All in all, I think you should try to separate the display logic and the game logic in your code. You've done it pretty well regarding user inputs, but for example, you don't need to keep an array of
Tip 1
When using conditions, you don't need to type
x == True, which means : while anotherGo == True:can be :
while anotherGo:Tip 2 Don't use
time.sleep for nothing. It could create confusion as to why you're using it when, I think, you're using it just so the program doesn't go too fast, but... why would you want that? :)Tip 3 When you use if/else, you can move the common code to the end or the beginning of the conditions, this removes code duplication :
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.")Becomes :
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.")Tip 4 If all your prints start with a line break, you could consider creating an helper function so you don't have to retype it every time :
def printn(s):
print("\n" + s)Tip 5 Create constants for those "magic numbers". When I read :
users_pick("\nEnter your choice [1, 2 or 3]: ", 1, 4, 20,nimBoard)Tip 6 You don't pay per character written, use meaningful variable names
Instead of having a variable named
userIn, you could consider naming it userInput. It's... 3 more characters, but it's also much clearer what it doesI need to go check the function definition to see what
1,4,20 mean. If you had constants named MIN_STICK = 1, MAX_STICKS=4, USERIN=20.Python tips
Tip 1 If you create an array with the same value multiple times, you can do :
# Notice how nice it is not to have to count to see the number of sticks
["/"] * 17instead of :
["/","/","/","/","/","/","/","/","/","/","/","/","/","/","/","/","/"]But I also think you don't need this array at all. You could simply keep the number of sticks available as an
int and decrease it when necessary. This array is used to print the board, so you shouldn't mix the display logic with the game logic, it'll make code easier to maintain and to read.Tip 2 Use only one naming style
You mix
snake_case and camelCase in your code, which makes the code harder to read. Since you're using Python, you should stick to snake_case.Code "cleanness"
In the
users_pick method, you pass a userIn that's higher than the maximal accepted value, only so that your while loop works (I suspect). Don't do this, as a matter of fact, you shouldn't pass userIn at all as a parameter, because you completely ignore the input.In
users_pick again. Doing this : userIn not in range(minStick, maxStick) might look "great", but it also means every time you call this you generate a range, only to check if the value is in there, why not use userIn maxStick that's much faster and more... logical.I'm not sure if it's a copy/paste error, but in the
who_starts method you set both f_player and s_player to the same values.All in all, I think you should try to separate the display logic and the game logic in your code. You've done it pretty well regarding user inputs, but for example, you don't need to keep an array of
/ to see where the game is at.Code Snippets
while anotherGo == True:while anotherGo: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.")def printn(s):
print("\n" + s)Context
StackExchange Code Review Q#160403, answer score: 2
Revisions (0)
No revisions yet.