I am creating a simple game that takes a user input (either 0 or 1) and compares it to the computer input. Depending on the input of the user in the previous moves, the computer will take the decision to play 0 or 1.
select_difficulty = int(input("Choose the type of game (1: Easy; 2: Difficult): "))
moves = int(input("Enter the number of moves: "))
MS = 0
PS = 0
xi = 1234
throw00 = []
throw01 = []
throw10 = []
throw11 = []
The conditions are the following:
throw00 = count of the number of times the human player chose 0 given that in the previous move he chose 0
throw01 = count of the number of times the human player chose 0 given in the previous move he chose 1
throw10 = count of the number of times the human player chose 1 given that his previous move was 0 throw11 = count of the number of times the human player chose 1 given his/her previous bid was 1
the following cases may occur:
If the player's last throw was 0:
If throw10 > throw00: then the computer chooses 1
If throw10 < throw00: then the computer chooses 0
If throw10 = throw00: then the computer chooses randomly 0 or 1
If the player's last throw was 1:
If throw11 > throw01: then the computer chooses 1
If throw11 < throw01: then the computer chooses 0
If throw11 = throw01: then the computer chooses randomly 0 or 1.
I've tried to this by saving the player move in a list and then access the previous move (one turn later) from that list.
if select_difficulty == 2:
for turn in range(moves):
player_move_dif = [int(n) for n in input("Choose your move number %s (0 or 1):" % (turn+1)).split()]`
player_previous_move = player_move_dif[1]
Based on these two variables on these two variables I then append the player_move choices (0 or 1) to the respective list which is in turn used by the "computer" to choose his move
if player_move_dif == 0 and player_previous_move == 0:
throw00.append(player_move_dif)
elif player_move_dif == 0 and player_previous_move == 1:
throw01.append(player_move_dif)
elif player_move_dif == 1 and player_previous_move == 0:
throw10.append(player_move_dif)
else:
throw11.append(player_move_dif)
#define computer behavior depening on previous player move
if player_previous_move == 0:
if len(throw10) > len(throw00):
computer_move = 1
elif len(throw10) < len(throw00):
computer_move = 0
else:
computer_move,xi = linear_congruence(xi)
elif player_previous_move == 1:
if len(throw11) > len(throw01):
computer_move = 1
elif len(throw11) < len(throw01):
computer_move = 0
else:
computer_move,xi = linear_congruence(xi)
else:
computer_move,xi = linear_congruence(xi)
this does not work since I need the values from the player moves (as integers) for print statements to show how the game goes on
if player_move_dif == computer_move:
MS = MS + 1
print("player = %d machine = %d - Machine wins!" % (player_move_dif, computer_move))
print("You: %d Computer: %d" % (PS, MS))
else:
PS = PS + 1
print("player = %d machine = %d - Player wins!" % (player_move_dif, computer_move))
print("You: %d Computer: %d" % (PS, MS))
print('PLAYER: ' + '*'*PS)
print('MACHINE: ' + '*'*MS)
if turn == moves and PS > MS:
print("The game has ended, you win!")
elif PS == MS:
print("The game has ended, it is a draw!")
else:
print("the game has ended, the machine wins!")
this way this currently results in a TypeError %d format: a number is required, not list. I suspect I am on the wrong path how to solve this the way I'm trying now as I cannot find solution to define the variables the way I want to while simultaneously be able to access them later as needed.
Besides i'm not sure if the logic of the game is implemented correctly, i found some issues which led to your error.
If you want to save the player's move into a list, you have to create an empty list before the for loop, otherwise you overwrite it again and again. Also you got the problem, that there are no previous moves at the very first move, so you need a start number at first:
player_move_dif = [] #create an empty list out of your for-loop
for i, turn in enumerate(range(moves)): #use enumerate() to count the loops
if i > 0: #first move has no previous one
player_move_dif.append(input("Choose your move number %s (0 or 1):" % (turn+1)).split()))
player_previous_move = int(player_move_dif[i-1])
else:
player_move_dif.append(input("Choose your start number %s (0 or 1):" % (turn+1)).split()))
continue #no action after the first move
Then you can access the current moves by an index of your move list. In your case the last index of your list is the last move the player did:
if player_move_dif == computer_move:
MS = MS + 1
print("player = %d machine = %d - Machine wins!" % (int(player_move_dif[-1]), computer_move)) #pick the last move from play_move_dif
print("You: %d Computer: %d" % (PS, MS))
else:
PS = PS + 1
print("player = %d machine = %d - Player wins!" % (int(player_move_dif[-1]), computer_move)) #pick the last move from play_move_dif
print("You: %d Computer: %d" % (PS, MS))
Related
I am trying to prevent the user from inputting a square that is already marked, but the for loop moves on to the next player's input without decrementing the value of i by one, so the player 1 can repeat his input. How do I fix this?
arr = [[0,0,0],[0,0,0],[0,0,0]]
grid = grid(arr)
grid.print_grid()
for i in range(9):
row = int(input("Enter the row name: "))
col = int(input("Enter the column name: "))
if(arr[row][col] == 0):
if(i%2):
arr[row][col] = 1
else:
arr[row][col] = 2
else:
print("\nThat square has already been marked! Please select another square")
i = i-1
continue
grid.print_grid()
res = grid.grid_checker()
if (res == 1):
print("\nPlayer 1 wins the game!")
break
elif(res == 2):
print("\nPlayer 2 wins the game!")
break
elif(i == 8):
print("\nThe game has ended in a draw!")
You need to store another variable to keep track of whose turn it is. You cannot modify the variable you are looping on while you are in the loop body. This means that i cannot be manipulated while you are running in the loop. Here's how I would change it.
turn = 0
while True:
row = int(input("Enter the row name: "))
col = int(input("Enter the column name: "))
if(arr[row][col] == 0):
if(i%2):
arr[row][col] = 1
turn = turn + 1
else:
arr[row][col] = 2
turn = turn + 1
else:
print("\nThat square has already been marked! Please select another square")
continue
grid.print_grid()
res = grid.grid_checker()
if (res == 1):
print("\nPlayer 1 wins the game!")
break
elif(res == 2):
print("\nPlayer 2 wins the game!")
break
elif(turn == 8):
print("\nThe game has ended in a draw!")
Here we're saving the turn number in the variable turn and only incrementing the variable when we can confirm a player has successfully completed their turn.
Why you cannot modify i: For optimisations, loops are often expanded by python before they are converted to assembly instructions. For example a simple loop like this:
for i in range(9):
print(i)
May be expanded to something like this:
i = 0
print(i)
i = 1
print(i)
# and so on, upto
i = 9
print(i)
This is done to avoid having to jump around in memory. So as you can see here, i is reassigned for every iteration of the loop. Therefore, even if you change the value of i in the body of the loop, it will simply be reassigned before the next iteration.
I am trying to make a grid in which a person can move, but stops only if he hits the boundaries.
He can either hit a boundary and stop, or keep walking until no more characters in the file are given. I am not sure how to approach the person stopping; I am a beginner and do not know if an array should be used, because the boundaries (length & width) should be random each time the script is run (except the East wall has a 5 tile gate each time).
try: #file argument
text = open(filename)
lines = text.readlines()
text.close()
except:
print("Error lacks reading permissions!", file=sys.stderr)
exit()
match=re.search("[nsew]", filename)
if match:
if 'n' in filename:
y+=1
elif 's' in filename:
y-=1
elif 'e' in filename:
x+=1
else:
x-=1
else:
print("filename contains characters other than n, s, e and w. Please use a file that only contains these characters.")
exit()
if x == 0 and y == 0:
counter+=1
else:
elephant=1 #placeholder
if x == ((length-1)/2) and -2 < y < 2:
print ("The walk was" steps "long, returned to the origin" counter "times. It ended because the drunk man reached the gate.")
elif x == ((length-1)/2) and y > 2 and y < -2:
print ("The walk was" steps "long, returned to the origin" counter "times. It ended because the drunk man reached the wall.")
else:
print ("The walk was" steps "long, returned to the origin" counter "times. It ended because the drunk man ran out of steps.")
*Q.Randomly generate a 4-digit number. Ask the user to guess a 4-digit number. For every digit that the user guessed correctly in the correct place, they have a “cow”. For every digit the user guessed the number in the wrong place is a “bull.”
Every time the user makes a guess, tell them how many “cows” and “bulls” they have. Once the user guesses the correct number, the game is over. Keep track of the number of guesses the user makes throughout the game and tell the user at the end.*
**Now, the problem is that I've made the program but it could generate any 4 - digit number, and that's when the problem arises. For example:
The generated number is 3568.
The user types: 3266
Then user gets 2 Cows And 2 Bulls.
But the user has no way of knowing which are the correct numbers in the number that he typed.
I want a function that can tell the user the numbers that he guessed right.
In the example, the program should tell the user that 3 and 6 are correct in the following places.**
import random
def compare_number(number, user_guess):
cowbull = [0, 0]
for i in range(len(number)):
if number[i] == user_guess[I]:
cowbull[1] += 1
else:
cowbull[0] += 1
return cowbull
if __name__ == "__main__":
playing = True
number = str(random.randint(1000, 10000))
guesses = 0
print("Let's Play A Game Of Cows And Bulls!")
print("I Will Generate A 4 Digit Number, And You Have To Guess The Numbers One Digit At A Time.")
print("For Every Number I The Wrong Place, You Get A Bull. For Every Number In The Right Place,
You Get A Cow.")
print("The Game Will End When You Get 4 Bulls.")
print("Type Exit At Any Prompt To Exit!")
while playing:
user_guess = input("Give Me The Best You Got!: ")
if user_guess.lower() == "exit":
break
cowbull_count = compare_number(number, user_guess)
guesses += 1
print(f"You Have {cowbull_count[1]} Cows, And {cowbull_count[0]} Bulls.")
if cowbull_count[1] == 4:
playing = False
print(f"You Win The Game After {guesses} Guess(es)!. The Number Was {number}.")
break
else:
print(f"Your Guess Isn't Quite Right, Tyr Again!.")
You can do something like this:
import random
def compare_number(number, user_guess):
cowbull = [0, 0, 0, 0]
for i in range(len(number)):
if number[i] == user_guess[i]:
cowbull[i] += 1
return cowbull
if __name__ == "__main__":
playing = True
number = str(random.randint(1000, 10000))
guesses = 0
print("Let's Play A Game Of Cows And Bulls!")
print("I Will Generate A 4 Digit Number, And You Have To Guess The Numbers One Digit At A Time.")
print("For Every Number I The Wrong Place, You Get A Bull. For Every Number In The Right Place, You Get A Cow.")
print("The Game Will End When You Get 4 Bulls.")
print("Type Exit At Any Prompt To Exit!")
while playing:
user_guess = input("Give Me The Best You Got!: ")
if user_guess.lower() == "exit":
break
cowbull_count = compare_number(number, user_guess)
guesses += 1
correct = sum(cowbull_count)
wrong = len(number) - correct
print(f"You Have {correct} Cows, And {wrong} Bulls.")
if correct == 4:
playing = False
print(f"You Win The Game After {guesses} Guess(es)!. The Number Was {number}.")
break
else:
print(f"Your Guess Isn't Quite Right, Try Again!.")
if correct >= 1:
print(str([user_guess[i] for i, x in enumerate(cowbull_count) if x == 1]) + " was correct!")
Changes made to your original code:
Instead of returning [numOfCorrect,numOfWrong], i returned [is 1 correct?, is 2 correct?, is 3 correct? is 4 correct?] // you need this to know which was right and which was wrong
the number of cows is = the number of correct which is equal to sum of 1's in cowbull_count //changed because of different return of compare_number
the number of bulls is = the number of wrong which is equal to number of digits - number of wrongs = len(numbers) - correct //changed because of different return of compare_number
if not all 4 digits were correct, show them which number they got correct // this is what you wanted
Sample run
You can replace your compare number function to print the index and value of the correct number.
def compare_number(number, user_guess):
cowbull = [0, 0]
for i in range(len(number)):
if number[i] == user_guess[I]:
cowbull[1] += 1
print("The number " + number[i] + " at index " + i " is correct")
else:
cowbull[0] += 1
print("The number " + number[i] + " at index " + i " is incorrect")
return cowbull
Add another method that return a list of positions: 4 element list, 0 if the user didn't guess a digit, 1 if he did. You can use it as you want in your function.
def digit_position(number, user_guess):
right_guesses = [0, 0, 0, 0]
for i in range(len(number)):
if number[i] == user_guess[i]:
right_guesses[i] = 1
return right_guesses
# Cow and Bull Game is a game in which User
# tries to guess the Secret code chosen by computer.
# We have 2 use cases i.e
# If Value in index of both User's and Computer's number are same than it is Cow.
# If Value Exists but not on same index as computer's than ita a Bull.
import random
# Following function generate a unique 4-digit number
def checkDuplication():
r = str(random.randint(1000, 9999))
for i in r:
if r.count(i) > 1:
return checkDuplication()
return r
# Following function check both number and returns Cow and Bull COUNTS.
def cowBullGame(human):
cow_count = bull_count = 0
for i in human:
if i in computer:
if human.count(i) > 1:
print('No Repeatative Numbers Allowed!')
return 0
if human.index(i) == computer.index(i): # Checking if both the value in index i are same or not
cow_count += 1
else:
bull_count += 1
print(str(cow_count)+' Cows, '+str(bull_count)+' Bulls')
return cow_count # Returning Cow_Count to check All Numbers are on right place.
computer = checkDuplication()
print(computer)
guesses = 1
# Infinite Loop till user gets 4 Cow_Counts
while True:
human = str(int(input('Guess a Number :')))
if cowBullGame(human) == 4:
print('Game Over. You made '+str(guesses)+' guesses')
break
guesses += 1
I'm making a program that is a game of pick up sticks. I'm still quite confused with the logic of the entire thing. My biggest problem is I have multiple nested while loops and want to end all of them. Heres my code.
x = 1
while x == 1:
sticks = int(input('How many sticks are on the tables (10 to 100): '))
if sticks not in range(10,101):
print('Invalid.')
continue
while x == 1:
print('There are',sticks,'sticks on the table.')
print('Player 1')
p1 = int(input('How many sticks do you want to remove?'))
if p1 == sticks:
print('Player one wins.')
x == 2
break
elif p1 not in range(1,4):
print('Invalid.')
continue
else:
while x == 1:
sticks -= p1
print('There are',sticks,'sticks on the table.')
print('Player 2.')
p2 = int(input('How many sticks do you want to remove?'))
if p2 == sticks:
print('Player two wins.')
x == 2
break
elif p2 not in range(1,4):
print('Invalid.')
continue
else:
sticks -= p2
My output continues to prompt player 1 and 2 for input.
I want the program to end after printing "Player _ wins".
Any helps/ tips would be greatly appreciated! Or even a simpler way to write the program.
I always find building a state machine for a multi-player turn-based game helps a lot. Because it provides a clear and easy way to decompose the logic and avoid using a lot of break and continue or even goto in nested loops.
For example, here is a state machine which has 4 states:
For each state, there's a handler function, it will decide which state to go next(even itself) based on current player, sticks and user input:
def initialize():
global sticks, state
n = int(input('How many sticks are on the tables (10 to 100): '))
if n not in range(10, 101):
print('Invalid. It should be between 10 ~ 100.')
else:
state = 'ask_player1'
sticks = n
def ask_player1():
global sticks, state
print('There are', sticks, 'sticks on the table.')
print('Player 1')
n = int(input('How many sticks do you want to remove?'))
if n not in range(1, 4):
print('Invalid. It should be between 1 ~ 4')
else:
sticks -= n
if sticks == 0:
print('Player one wins.')
state = 'end'
else:
state = 'ask_player2'
def ask_player2():
global sticks, state
print('There are', sticks, 'sticks on the table.')
print('Player 2')
n = int(input('How many sticks do you want to remove?'))
if n not in range(1, 4):
print('Invalid. It should be between 1 ~ 4')
else:
sticks -= n
if sticks == 0:
print('Player two wins.')
state = 'end'
else:
state = 'ask_player1'
state_machine = {
'initialize': initialize,
'ask_player1': ask_player1,
'ask_player2': ask_player2,
}
sticks = 0
state = 'initialize'
while state != 'end':
state_machine[state]()
Your best bet is probably to move the code into a function that returns. Multi-breaks have been proposed multiple times and have been rejected. You can put this whole code into a function that returns after "Player _ wins", so it doesn't keep running. Other alternatives are using a flag variable that is set after a player wins and raising an exception that is subsequently handled.
pointsToAdd = 30
strengthPoints = 0
healthPoints = 0
wisdomPoints= 0
dexterityPoints = 0
while pointsToAdd > 0:
choice = int(input("Choice(1-4): "))
if choice == 1:
pointsToAdd = int(input("How many Strength points would you like to add: "))
if pointsToAdd < 31 and pointsToAdd > 0 and pointsToAdd - strengthPoints > 0:
strengthPoints += pointsToAdd
pointsToAdd -= strengthPoints
print("You now have",strengthPoints,"strength points")
elif pointsToAdd > 30:
print("You cannot add that many!")
elif pointsToAdd<1:
print("You cannot add less than one point!")
elif pointsToAdd - strengthPoints <= 0:
print("You only have",pointsToAdd,"points!")
else:
print("We are sorry, but an error has occurred")
I am trying to make it so that the user can enter points for any of the four categories, but has no more than 30 points to expend(I have not yet written the code for the health, wisdom or dexterity points). Why when i run the program does the loop only run again if you choose to add a number of points between 1-30? If the user enters the points they want to allocate towards strengthPoints using numbers not between 1-30, the loop will run the associated if statement, but will not run through the loop again, why is this the case?
you are using the same variable for two different purposes pointsToAdd. You have it as the total points to assign, and what was selected by the user to add to a stat. Once you stomp the total points to assign with the users choice, you then add it to the 0 strength and subtract it from your user entered value, setting it to zero. Using to separate variables like below will fix it.
totalPointsToAdd = 30
strengthPoints = 0
healthPoints = 0
wisdomPoints= 0
dexterityPoints = 0
while totalPointsToAdd > 0:
choice = int(input("Choice(1-4): "))
if choice == 1:
pointsToAdd = int(input("How many Strength points would you like to add: "))
if pointsToAdd < 31 and pointsToAdd > 0 and pointsToAdd - strengthPoints > 0:
strengthPoints += pointsToAdd
totalPointsToAdd -= pointsToAdd
print("You now have",strengthPoints,"strength points")
You do
pointsToAdd = 30
Then in the loop
pointsToAdd = int(input("How many Strength points would you like to add: "))
Then in the test
# Here pointsToAdd is not 30, but the value inputed by the user
strengthPoints += pointsToAdd
# Here strengthPoints == pointsToAdd == the value from the input
pointsToAdd -= strengthPoints
# Here pointsToAdd == 0
This results in pointsToAdd == 0 after than.
You need to use another variable for the input of your user.
As other pointed out you are overwriting the same variable pointsToAdd. I also consider that you can cut down your conditions to two:
pointsToAdd = 30
strengthPoints = 0
while pointsToAdd:
print ('You have', pointsToAdd, 'available points.')
choice = int(input("Choice(1-4): "))
if choice == 1:
toBeAdded = int(input("How many Strength points would you like to add: "))
if toBeAdded < 1: # Can't assign negative or null values
print("You cannot add less than one point!")
continue
if toBeAdded > pointsToAdd: # Don't have enough points to spend
print("You only have", pointsToAdd, "available points!")
continue
strengthPoints += toBeAdded
pointsToAdd -= toBeAdded
print("You now have", strengthPoints, "strength points")
In Python 2.x use: raw_input
In Python 3.x use: input
If you want compatibility between Python 2.x and 3.x, you can use:
try:
input = raw_input
except NameError:
pass