I'm running a odd/even game in Python and I get stuck once I need to define a winner - python-3.x

#Here I define the user and cpu function
cpu_num = random.randint(1,6)
user_selection = ["Odd", "Even"]
def cpu_choice():
choice = random.randint(1,6)
print("The computer's choice is",choice)
return choice
def user_choice():
while(True):
choice = input("Odd or Even? ")
if choice in user_selection:
print("Your choice is",choice)
return choice
else:
print("You did not write your answer correctly, please try again.")
#In this function I define the result of each round based on previous formulas and two new variables (num_rounds and user_lives) and everything works well
def round_result():
num_rounds = 0
user_lives = 10
while num_rounds < 8 and user_lives > 0:
user_pick = user_choice()
cpu_pick = cpu_choice()
if (cpu_pick % 2 == 0) and (user_pick == "Even"):
print (f'You have {user_lives + cpu_pick} lives left')
num_rounds += 1
user_lives = user_lives + cpu_pick
if (cpu_pick % 2 == 0) and (user_pick == "Odd"):
print (f'You have {user_lives - cpu_pick} lives left')
num_rounds += 1
user_lives = user_lives - cpu_pick
if (cpu_pick % 2 != 0) and (user_pick == "Even"):
print (f'You have {user_lives - cpu_pick} lives left')
num_rounds += 1
user_lives = user_lives - cpu_pick
if (cpu_pick % 2 != 0) and (user_pick == "Odd"):
print (f'You have {user_lives + cpu_pick} lives left')
num_rounds += 1
user_lives = user_lives + cpu_pick
#Everything works well until here, I don't know what am I doing wrong in the winner function
def winner():
user_won = user_lives > 0 and num_rounds == 8
cpu_won = user_lives < 0
game = round_result()
while game:
if user_won is True:
print ('You won')
if cpu_won is True:
print ('Cpu won')

Related

Running a loop 10,000 times in order to test expected value

Playing a 2 person game where player A and B take turns drawing stones out of a bag.
10 stones, 9 white, 1 black
You lose if you draw the black stone.
Assuming you alternate drawing stones, is going first an advantage, disadvantage, or neutral?
I'm aware that this can be solved using conditional probability, but I'd like to also prove it by using significant sample size data
import random
import os
import sys
stones = 4
player1Wins = 0
player2Wins = 0
no_games = 100000
gameCount = 0
fatal_stone = random.randint(1, int(stones))
picked_stone = random.randint(1, int(stones))
def pick_stone(self, stones):
for x in range(1, int(stones) + 1):
if picked_stone == fatal_stone:
if (picked_stone % 2) == 0:
player2Wins += 1 print("Player 2 won")
break
if (picked_stone % 2) == 1:
player1Wins += 1
print("Player 1 won")
break
else:
stones -= 1 picked_stone = random.randint(1, int(stones))
self.pick_stone()
pick_stone()
# def run_games(self, no_games): #for i in range(1, int(no_games) + 1): #gameCount = i #self.pick_stone()
print(fatal_stone)
print(picked_stone)
print(int(fatal_stone % 2))
print(int(picked_stone % 2))
print(gameCount)
print("Player 1 won this many times: " + str(player1Wins))
print("Player 2 won this many times: " + str(player2Wins))
The following code works. And it suggests that both players' chances of winning are equal, regardless of who plays first.
import random
import os
import sys
num_stones = 4
no_games = 100000
player1Wins = 0
player2Wins = 0
def pick_stone(player: int, stones: list, fatal_stone: int):
global player1Wins, player2Wins
picked_stone = random.choice(stones)
stones.remove(picked_stone)
if (picked_stone == fatal_stone):
if player == 1:
player2Wins += 1
else:
player1Wins += 1
return False
return True
def run_games(no_games: int):
for _ in range(no_games):
stones = [i for i in range(num_stones)]
fatal_stone = random.choice(stones)
# player 1 and 2 pick stones in turn
player = 1
playing = True
while playing:
playing = pick_stone(player, stones, fatal_stone)
player = player % 2 + 1
print(f"Total rounds: {no_games}")
print("Player 1 won this many times: " + str(player1Wins))
print("Player 2 won this many times: " + str(player2Wins))
run_games(no_games)

My minesweeper program works just fine until I click on the top left tile. Everything looks fine

I am attempting to make minesweeper in Python by using tkinter. When the program checks for bombs, it works just fine unless the tile clicked is at 0, 0 (top left), in which case the program always has tileNorth and tileWest True, causing the program to check a variable that doesn't exist. This causes an error and leaves the 0, 0 tile blank. The checking works in every other tile, including corners, just not the top left. This should not be happening.
TLDR:
My minesweeper program works just fine, but it always messes up at 0, 0 and creates an error. I don't understand what's wrong...
The Error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "<string>", line 11, in <lambda>
File "/home/pi/Documents/Python/Minesweeper/Minesweeper.py", line 133, in tileClicked
stringVar_{x}_{y}.set(tileValue)""")
File "<string>", line 56
if bomb_-1_-1 == True:
^
SyntaxError: invalid token
It mentions bomb_-1_-1 which doesn't exist and can't exist... This is why that one if statement needs to work.
My Code:
import random
import tkinter
# Functions
def tileClicked(x, y): # Function is ran when a tile is clicked. The tile is defined by the inputted 'x' and 'y' values.
exec(f"""
global tileNorth, tileEast, tileSouth, tileWest
if y > 0:
tileNorth = True
else:
tileNorth = False
if x < game.size[0] - 1:
tileEast = True
else:
tileEast = False
if y < game.size[1] - 1:
tileSouth = True
else:
tileSouth = False
if x > 0:
tileWest = True
else:
tileWest = False""")
print(f"""{tileNorth}
{tileEast}
{tileSouth}
{tileWest}
DIV""")
exec(f"""
print("{x}, {y}")
if bomb_{x}_{y} == True:
stringVar_{x}_{y}.set("Bomb")
game.failed = True
if x == 0 and y == 0:
tileValue = int(0)
if tileNorth == True:
if tileEast == True:
if bomb_{x + 1}_{y - 1} == True:
tileValue += 1
if tileEast == True:
if bomb_{x + 1}_{y} == True:
tileValue += 1
if tileSouth == True:
if tileEast == True:
if bomb_{x + 1}_{y + 1} == True:
tileValue += 1
if tileWest == True:
if bomb_{x - 1}_{y + 1} == True:
tileValue += 1
if bomb_{x}_{y + 1} == True:
tileValue += 1
if tileWest == True:
if bomb_{x - 1}_{y} == True:
tileValue += 1
else:
tileValue = int(0)
if tileNorth == True:
if tileEast == True:
if bomb_{x + 1}_{y - 1} == True:
tileValue += 1
if tileWest == True:
if bomb_{x - 1}_{y - 1} == True:
tileValue += 1
if bomb_{x}_{y - 1} == True:
tileValue += 1
if tileEast == True:
if bomb_{x + 1}_{y} == True:
tileValue += 1
if tileSouth == True:
if tileEast == True:
if bomb_{x + 1}_{y + 1} == True:
tileValue += 1
if tileWest == True:
if bomb_{x - 1}_{y + 1} == True:
tileValue += 1
if bomb_{x}_{y + 1} == True:
tileValue += 1
if tileWest == True:
if bomb_{x - 1}_{y} == True:
tileValue += 1
if tileValue == 0:
tileValue = "Clear"
stringVar_{x}_{y}.set(tileValue)""")
# Classes
class game:
title = "Minesweeper"
bg = "white"
fg = "black"
size = [10, 10]
tileWidth = 3
tileHeight = 2
failed = False
bombFrequency = 4
flagMode = False
# Execution
window = tkinter.Tk() # The window.
window.title(game.title)
window.config(bg = game.bg)
mainFrame = tkinter.Frame(window, bg = game.bg) # Main frame that everything is located in.
titleFrame = tkinter.Frame(mainFrame, bg = game.bg) # Title frame.
titleLabel = tkinter.Label(titleFrame, bg = game.bg, fg = game.fg, text = game.title, font = "none 20").grid(row = 0, column = 0)
titleFrame.grid(row = 0, column = 0)
tileFrame = tkinter.Frame(mainFrame, bg = game.bg) # Frame where tiles are located.
x = 0
y = 0
for tiles_x in range(game.size[0]): # Generates tiles.
for tiles_y in range(game.size[1]):
exec(f"""global tile_{x}_{y}, stringVar_{x}_{y}, bomb_{x}_{y}
bomb_{x}_{y} = random.randint(1, game.bombFrequency)
if bomb_{x}_{y} == 1:
bomb_{x}_{y} = True
else:
bomb_{x}_{y} = False
stringVar_{x}_{y} = tkinter.StringVar(tileFrame)
tile_{x}_{y} = tkinter.Button(tileFrame, bg = 'lightgrey', fg = 'black', width = game.tileWidth, height = game.tileHeight, textvariable = stringVar_{x}_{y}, command = lambda: tileClicked({x}, {y})).grid(row = {y}, column = {x})""")
y += 1
x += 1
y = 0
tileFrame.grid(row = 1, column = 0)
mainFrame.pack() # The main frame is packed so everything is centered.
window.mainloop()
I don't care if you think dynamic variables are inefficient, it's my choice. I don't want people to comment on my methods of accomplishing a task... unless it's causing the problem...
Thanks!
Using dynamic variables is bad practice, and your experience is a good demonstration why.
Variable names cannot have a minus sign in them. The minus sign is interpreted as the arithmetic operator. So bomb_-1_-1 is interpreted as bomb_ - 1_ - 1. The bomb_ part is understood as a variable name, the 1 as a number, but the underscore following that number is triggering the syntax error.
This also demonstrates that dynamic code is not that great: syntax errors only pop up when certain circumstances are created (like selecting a particular cell).
A quick fix, just to show a work around, is to test first the values of x and y:
if {x} >= 0 and {y} >= 0 and bomb_{x}_{y} == True:
You would have to do similar tests for any other place where you create a dynamic reference like that. So also:
if {x} >= 1 and {y} >= 1 and bomb_{x-1}_{y-1} == True:
...etc.
But this is really patching a terrible design.
Note that even if only one of the variables is negative, you'll evaluate an expression that you did not really intend. You could get this for when only y == -1: bomb_5_-1. This produces no syntax error, but it evaluates as bomb_5_ minus 1. Obviously that is not intended by the algorithm.
Instead of dynamic variables and parsing code at run-time, use lists. They can be nested to have the 2D coverage.

Passes the first case but fails the other cases

Okay so I finished a code on hackerrank. It passes the test case but once I submit it fails the others. I have scanned through the code several times without a solution. Any thoughts on this? I have attached the screenshot of the question and my code as well as the test case scenarios that failed.
My code:
#!/bin/python3
import math
import os
import random
import re
import sys
def batting_stats(lst):
rgh,rgf,totr,totbf,totd,crat = 0,0,0,0,0,0 #rgh: runs greater than 100, rgf: runs greater 50
#totr:total runs, totbf:total balls faced, #totd: total
#dismissals, crat: conversion rate
results = []
for inning in lst:
runs_scored = inning[0]
balls_faced = inning[1]
dismissed = inning[-1]
totr += runs_scored
totbf += balls_faced
totd += dismissed
if runs_scored >= 100:
rgh += 1
elif runs_scored == 50:
rgf += 1
average = totr // max(totd, 1)
strikeRate = int((totr / totbf) * 100)
if rgf > 0:
crat = ( rgh // rgf ) * 100
results.append([average, strikeRate, crat])
return results
if __name__ == '__main__':
fptr = open(os.environ['OUTPUT_PATH'], 'w')
innings_count = int(input().strip())
innings = []
for _ in range(innings_count):
innings_item = list(map(int, input().rstrip().split()))
innings.append(innings_item)
result = batting_stats(innings)
for x in result or []:
fptr.write(' '.join(map(str, x)))
fptr.write('\n')
fptr.close()
I don't have access to your grader, but here are some obvious issues I see.
if runs_scored >= 100:
rgh += 1
elif runs_scored == 50:
rgf +=1
should be
if runs_scored >= 100:
rgh += 1
rgf +=1 (because a 100 plus score is also a 50 plus score)
elif runs_scored >= 50: (at least 50 is the condition not exactly 50)
rgf += 1
Next,
average = totr // max(totd, 1)
should be
if totd==0:
average=totr
else:
average=totr/totd
And,
crat = ( rgh // rgf ) * 100 should be
crat = ( rgh / rgf ) * 100
I have included these edits together with a few more, and have tested this code on the one available input and a few others. It returns, as expected, a list of lists with numbers that match the expected output. Please try this out in the grader.
import math
def batting_stats(lst):
rgh,rgf,totr,totbf,totd,crat = 0,0,0,0,0,0
results = []
for innings in lst:
totr += innings[0]
totbf += innings[1]
totd += innings[2]
if innings[0] >= 100:
rgh += 1
rgf +=1
elif innings[0] >= 50:
rgf+=1
if totd==0:
average=totr
else:
average=totr/totd
strikeRate = (totr / totbf) * 100
if rgf > 0:
crat = ( rgh / rgf ) * 100
else:
crat=0
results.append([math.floor(average), math.floor(strikeRate), math.floor(crat)])
return results

Testing divisibility of a list and appending if prime

I'm writing a short snippet for a class that is supposed to run through a given list of numbers and append any primes. Right now it is returning all numbers in the range though.
I've found examples online for how to do this, but wanted to try it myself but I've seem to hit a wall... Here is my code:
from random import randrange
from time import sleep
def prime():
user_num = eval(input("Input a number: "))
list_prime = []
for i in range(2,user_num):
if (i % 2) == 1 and\
(i % 3) == 1 and\
(i % 4) == 1 and\
(i % 5) == 1 and\
(i % 6) == 1 and\
(i % 7) == 1 and\
(i % 8) == 1 and\
(i % 9) == 1 or\
i == 2:
list_prime.append(i)
if list_prime == '':
print('No prime numbers.')
if list_prime != '':
print('\nPrime numbers from 1 to ' + str(user_num) + ': ' + str(list_prime))
sleep(1)
print('\nClosing console in 60 seconds...')
sleep(60)
prime()
As he said, you werent correctly checking for prime numbers.
from random import randrange
from time import sleep
list_prime = []
user_num = 0
def prime():
user_num = eval(input("Input a number: "))
for i in range(2,user_num):
j = 2
isprime = 1
while (j <= i/2):
if (i % j == 0):
isprime = 0
break
j+=1
if (isprime == 1):
list_prime.append(i)
prime()
if list_prime == '':
print('No prime numbers.')
if list_prime != '':
print('\nPrime numbers from 1 to ' + str(user_num) + ': ' + str(list_prime))
sleep(1)
print('\nClosing console in 60 seconds...')
sleep(60)
Checking if the result of a modulo operation is 1 is not the correct approach. For example, 6 % 5 is 1, but 6 definitely isn't a prime number. Instead, for each suspect N you should check that no number X exists such that N % X == 0.
A wildly sub-optimal implementation could look like this:
list_prime = []
for i in range(2, user_num):
if all(n % x for x in list_prime):
list_prime.append(i)

Pig Two Computers Game

I have an assignment where I need the computer to play a game of pig on his own and stop once 100 is rolled. So, I have two computer players going head to head, but the problem is that although the players could've had 100 total they keep going until turntotal >= 20 which in return gives the other player a chance to win because there was a point where 100 could be reached. It specifically states in our assignment to look out for this problem, but I have no clue how to go about solving this issue. Also any ways to make the code cleaner would be helpful.
def playerOne(score):
turntotal = 0
scoretotal = 0
while(scoretotal >= 0 and scoretotal <= 100):
while(scoretotal < 100):
roll = random.randint(1,6)
print('Rolled a ', roll)
if(turntotal <= 20 and roll != 1):
turntotal = turntotal + roll
scoretotal = scoretotal + roll
if(turntotal >= 20):
break
if(roll == 1):
scoretotal = scoretotal - turntotal
turntotal = 0
print('Pigged Out!!!')
break
print('Turn score =', turntotal)
turntotal = 0
return scoretotal
def printScore():
print(' ')
print("Player One score is", PlayerOneScore)
print("Player two score is", PlayerTwoScore)
print(' ')
PlayerOneScore = 0
PlayerTwoScore = 0
flipcoin = random.randint(1,2)
if(flipcoin == 1):
while(PlayerOneScore < 100 or PlayerTwoScore < 100):
printScore()
print("Player 1's turn")
PlayerOneScore += playerOne(PlayerOneScore)
if(PlayerOneScore >= 100):
break
printScore()
print("Player 2's turn")
PlayerTwoScore += playerOne(PlayerTwoScore)
if(PlayerTwoScore >= 100):
break
else:
while(PlayerOneScore < 100 or PlayerTwoScore < 100):
printScore()
print("Player 2's turn")
PlayerTwoScore += playerOne(PlayerTwoScore)
if(PlayerTwoScore >= 100):
break
printScore()
print("Player 1's turn")
PlayerOneScore += playerOne(PlayerOneScore)
if(PlayerOneScore >= 100):
break
printScore()
if(PlayerTwoScore > PlayerOneScore):
print("PLAYER 2 WINS")
else:
print("PLAYER 1 WINS")

Resources