Games such a flip a coin, rolling dice, and choosing cards - python

im trying to make a game board and i have taken some notes from my class and im just struggling to do this assignment. We never have done anything like this in class before. I need to do a coin flip, roll two dice a 6 sided one and a 20 sided one and i need to pick a card.
import random
def flip_coin():
# TODO: implement this function
# get a random int between 0 and 1
# if the number is 0, return "Coin flip: Tails"
# if the number is 1, return "Coin flip: Heads"
# delete this next line:
return 0
def roll_d6():
# TODO: implement this function
# get a random int between 1 and 6
# return "D6 roll: [that number]"
# delete this next line:
return 0
def roll_d20():
# TODO: implement this function
# get a random int between 1 and 20
# return "D20 roll: [that number]"
# delete this next line:
return 0
def pick_card():
# TODO: implement this function
# get a random number between 0 and 3
# [card suit]: 0=spades, 1=hearts, 2=diamonds, 3=clubs
# then get a random number between 1 and 13
# [card value]: 1=Ace, 11=Jack, 12=Queen, 13=King, 2-10 are normal (no translation)
# return "Your card: [card value] of [card suit]"
# delete this next line:
return 0
# TODO: put the following lines into a loop, to allow the user to repeat until they quit
print('Welcome to the game center!\nHere are your options:')
print('\t1) Flip a coin\n\t2) Pick a random playing card')
print('\t3) Roll a 6-sided dice\n\t4) Roll a 20-sided dice')
choice = input('What would you like to do? ')
# TODO: based on what the user selects, call the appropriate function above (print the result)

There are faster solutions to this: but these are the most simple solutions.
import random
def coin_flip():
generated_num = random.randint(0, 1) # generate a random number from 0 to 1
if generated_num == 0:
return "Coin flip: Tails"
else:
return "Coin flip: Heads"
def roll_d6():
generated_num = random.randint(1, 6)
return f"D6 roll: {generated_num}"
def roll_d20():
generated_num = random.randint(1, 20)
return f"D20 roll: {generated_num}"
def pick_card():
suit = random.randint(0, 3)
if suit == 0: suit = "Spades"
if suit == 1: suit = "Hearts"
if suit == 2: suit = "Diamonds"
if suit == 3: suit = "Clubs"
value = random.randint(1, 13)
if value == 1: value = "Ace"
if value == 11: value = "Jack"
if value == 12: value = "Queen"
if value == 13: value = "King"
return f"Your card: {value} of {suit}"
NOTE
Here is a better way to pick the suit:
def pick_card():
suit = random.choice(['Spades','Hearts','Diamonds','Clubs'])
...

Related

Program will not stop when the conditions are passed

I'm writing a sum up game where two players will take turns picking a random number in the range (1,9), no repeated number allowed. If the first player picks [7, 2, 3, 5], he will win because 7+3+5 = 15
So my question is why doesn't the program stop when first_player has a sum of inputs that == 15
Below is the readme file
The game doesn't stop when first player's inputs equal 15 because you ask for second player's input regardless of whether the first player won. You can see this in your testing code, where you have two while statements for each player's input. If you complete that round with second player's input, your program works and stops there. To stop when a player wins on input, just add the conditional check to break out of main loop before asking for next player's input.
Your script is too verbose. If you made it more dynamic, with reusable logic, it becomes much easier to work with. I rewrote your game as an example.
notes:
All the game states are reused in fstrings, as dict keys, and even to represent the player
The game loop (update()) represents a single turn, and the player that turn corresponds to is toggled at the end of the loop
make_move also represents one turn
the entire game is contained in the class
reset() is used to clear the window, reset all the game properties, and start the loop, but the very first time it is called it acts as an initializer for all of the game properties.
There is never going to be an instance where both players have 15 points
import os
UNFINISHED = "unfinished"
DRAW = "draw"
FIRST_WON = "First"
SECOND_WON = "Second"
CLEAR = lambda: os.system('cls') #windows only
class AddThreeGame:
#property
def current_state(self):
return self.__state
#property
def player(self):
return self.__rotation[self.__player]
def __init__(self):
self.__rotation = [FIRST_WON, SECOND_WON]
self.__states = {
UNFINISHED:'We have unfinished business, come back for more\n',
DRAW:'Draw game\n',
FIRST_WON:'First player won this game!!!\n',
SECOND_WON:'Second player won this game!!!\n',
}
self.reset()
def make_move(self, player, number):
if number not in range(1, 10) or number in self.__input:
return False
self.__input.append(number)
self.__players[self.player].append(number)
if len(self.__players[self.player]) >= 3:
L = self.__players[self.player]
for i in range(0, len(L)-2):
for j in range(i+1, len(L)-1):
for k in range(j+1, len(L)):
if (L[i] + L[j] + L[k]) == 15:
self.__state = player
return True
if len(self.__input) == 9:
self.__state = DRAW
return True
def update(self):
while True:
num = int(input(f'{self.player} player please enter a number from 1 to 9: '))
while True:
if self.make_move(self.player, num):
break
else:
num = int(input("Wrong input, please try a different number: "))
if self.current_state == UNFINISHED:
if self.__player == 1: #technically, this is player 2
print(self.__states[self.current_state])
#next player
self.__player = (self.__player + 1) % 2
else:
print(self.__states[self.current_state])
break
if input('Play Again? (y or n): ') == 'y':
self.reset()
def reset(self):
CLEAR()
self.__player = 0
self.__input = []
self.__state = UNFINISHED
self.__players = {
FIRST_WON:[],
SECOND_WON:[],
}
self.update()
if __name__ == '__main__':
AddThreeGame()

Trying to assign score values to cards and get a final score across multiple classes

So,I'm trying to basically assign different values to different cards in class Deck and use them in class Player to get a score. How could i fix this to do that? Sorry, about this again.
class Deck:
...
def Cards(self):
for suit in ["S","C","D","H"]:
for rank in range(1, 14):
value = rank
if rank == 1:
rank = 'A'
elif rank == 11:
rank = 'J'
elif rank == 12:
rank = 'Q'
elif rank == 13:
rank = 'K'
if (value == 11) or (value == 12) or (value == 13):
value = 10
elif rank == 1:
value == 11
self.__value = value
self.__cards.append(Card(suit, rank))
# ---------------------------------------------
class Player:
def __init__(self, name, score):
self.__name = name
self.__hand = []
self.__Deck = Deck()
self.__score = score
...
def draw(self, deck, CardCount):
count = 0
while count != CardCount
count += 1
self.__score += self.__value
self.__hand.append(deck.drawCard())
return self
make a class card
class Card:
def __init__(self,card_val,suite):
self.card_val = card_val
self.suit = suit
def score(self):
if self.card_val <= 10:
return self.card_val
if self.card_val == 13:
return 11
return 10
now make a hand class
class Hand:
cards = []
def score(self):
scores = [c.score() for c in self.cards]
aces = scores.count(11)
total = sum(scores)
while total > 21:
if aces <= 0:
break
aces -= 1
total -= 10
return total
then use the hand
h = Hand()
h.cards = [Card(13,1),Card(13,2),Card(13,3),Card(8,2)]
print(h.score())
Since you didn't fully specify the Card or Deck classes, I went ahead and filled it based on what I imagined you would want. I've included what #tsh has said in the comments related to how the assign of value should work.
from dataclasses import dataclass, field
from typing import List
import random
#dataclass
class Card:
suit: str
rank: str
value: int
#dataclass
class Deck:
unused: List[Card]
used: List[Card] = field(default_factory=list)
def draw_card(self):
random.shuffle(self.unused)
card = self.unused.pop(0)
self.used.append(card)
return card, Deck(self.unused, self.used)
#staticmethod
def generate_deck():
cards = []
for suit in ["S","C","D","H"]:
for rank in range(1, 14):
if rank in [11, 12, 13]:
value = 10
elif rank == 1:
value = 11
else:
value = rank
if rank == 1:
rank = 'A'
elif rank == 11:
rank = 'J'
elif rank == 12:
rank = 'Q'
elif rank == 13:
rank = 'K'
cards.append(Card(suit, str(rank), value))
return Deck(unused=cards)
Note while you don't want to paste in your entire codebase, it is helpful if you provide something that is paste-able/compiling as I did above. So now for the actual question. As #tsh mentioned self.__value is meaningless as that suggests the value of self which is in this case the Player. Instead you want to value of the card that is drawn. See the following.
#dataclass
class Player:
name: str
def draw(self, deck, card_count):
count = 0
score = 0
hand = []
while count != card_count:
count += 1
card, deck = deck.draw_card()
score += card.value
hand.append(card)
return deck, hand, score
deck = Deck.generate_deck()
deck, hand, score = Player("Foo").draw(deck, 5)
print(f"Hand is {hand}.")
print(f"Score is {score}")
Example output
Hand is [Card(suit='S', rank='2', value=2), Card(suit='D', rank='6', value=6), Card(suit='D', rank='Q', value=10), Card(suit='H', rank='4', value=4), Card(suit='H', rank='10', value=10)].
Score is 32

Python probability of a pair

I am trying to make a poker game where it would check if it is a pair or three of a kind or four of a kind.
I am trying to figure out where to insert a while loop. if I should put it in front of the for card in set(cards): statement or the for i in range(5):
I want to keep printing 5 cards until it shows either a pair, 3 of a kind, or 4 of a kind.
Then what I want to do is to print the probability of printing one of those options
import random
def poker():
cards = []
count = 0
for i in range(5):
cards.append(random.choice([1,2,3,4,5,6,7,8,9,10,11,12,13]))
print(cards)
for card in set(cards):
number = cards.count(card) # Returns how many of this card is in your hand
print(f"{number} x {card}")
if(number == 2):
print("One Pair")
break
if(number == 3):
print("Three of a kind")
break
if(number == 4):
print("Four of a kind")
break
You should put the while above cards but bring count outside of that loop so you can maintain it. You do this because you need to repeat the entire card creation/selection process each time until you meet the condition you are looking for.
import random
def poker():
count = 0
while True:
cards = []
for i in range(5):
cards.append(random.choice([1,2,3,4,5,6,7,8,9,10,11,12,13]))
print(cards)
stop = False
for card in cards:
number = cards.count(card) # Returns how many of this card is in your hand
print(f"{number} x {card}")
if(number == 4):
print("Four of a kind")
stop = True
break
elif(number == 3):
print("Three of a kind")
stop = True
break
elif(number == 2):
print("One Pair")
stop = True
break
if stop:
break
else:
count += 1
print(f'Count is {count}')

Monty Hall simulation not working as intended

I've been trying out to solve the monty hall problem in Python in order to advance in coding, which is why I tried to randomize everything. The thing is: I've been running into some trouble. As most of you probably know the monty problem is supposed to show that changing the door has a higher winrate (66%) than staying on the chosen door (33%). For some odd reason though my simulation shows a 33% winrate for both cases and I am not really sure why.
Here's the code:
from random import *
def doorPriceRandomizer():
door1 = randint(0,2) #If a door is defined 0, it has a price in it
door2 = randint(0,2) #If a door is defined either 1 or 2, it has a goat in it.
door3 = randint(0,2)
while door2 == door1:
door2 = randint(0,2)
while door3 == door2 or door3 == door1:
door3 = randint(0,2)
return door1,door2,door3 #This random placement generator seems to be working fine.
while True:
loopStart = 0
amountWin = 0
amountLose = 0
try:
loopEnd = int(input("How often would you like to run this simulation: "))
if loopEnd < 0:
raise ValueError
doorChangeUser = int(input("[0] = Do not change door; [1] = Change door: "))
if doorChangeUser not in range(0,2):
raise ValueError
except ValueError:
print("Invalid input. Try again.\n")
else:
while loopStart != loopEnd:
gameDoors = doorPriceRandomizer()
inputUser = randint(0,2)
if doorChangeUser == 0:
if gameDoors[inputUser] == 0:
amountWin += 1
loopStart += 1
else:
amountLose += 1
loopStart += 1
elif doorChangeUser == 1:
ChangeRandom = 0
while gameDoors[ChangeRandom] == gameDoors[inputUser]:
ChangeRandom = randint(0,2)
if gameDoors[ChangeRandom] == 0:
amountWin += 1
loopStart += 1
else:
amountLose += 1
loopStart += 1
print("Win amount: ",amountWin,"\tLose amount: ",amountLose)
What am I doing wrong? I really appreciate all help! Thanks in advance!
ChangeRandom = 0
while gameDoors[ChangeRandom] == gameDoors[inputUser]:
ChangeRandom = randint(0,2)
This doesn't do what you think it does. Instead of checking if the ChangeRandom door is the same as the inputUser door, this checks if the ChangeRandom door and the inputUser door have the same value -- that is to say they're either both winners or both losers.
That said, that's not even what you want to do. What you want to do is to find a door that's not the user's input that IS a loser door, then switch to the OTHER one that isn't the user's input. This could be implemented with minimal change to your code as:
other_wrong_door = next(c for c, v in enumerate(gameDoors) if v != 0 and c != inputUser)
new_door = next(c for c, _ in enumerate(gameDoors) if c != inputUser and c != other_wrong_door)
But honestly this merits a re-examining of your code's structure. Give me a few minutes to work something up, and I'll edit this answer to give you an idea of how I'd implement this.
import random
DOORS = [1, 0, 0]
def runonce(switch=False):
user_choice = random.choice(DOORS)
if user_choice == 1:
# immediate winner
if switch:
# if you won before and switch doors, you must lose now
return False
else:
new_doors = [0, 0] # remove the user-selected winner
new_doors = [0] # remove another loser
return bool(random.choice(new_doors))
# of course, this is always `0`, but
# sometimes it helps to show it. In production you
# wouldn't bother writing the extra lines and just return False
else:
if switch:
new_doors = [1, 0] # remove the user-selected loser
new_doors = [1] # remove another loser
return bool(random.choice(new_doors))
# as above: this is always True, but....
else:
return False # if you lost before and don't switch, well, you lost.
num_trials = int(input("How many trials?"))
no_switch_raw = [run_once(switch=False) for _ in range(num_trials)]
switch_raw = [run_once(switch=True) for _ in range(num_trials)]
no_switch_wins = sum(1 for r in no_switch_raw if r)
switch_wins = sum(1 for r in switch_raw if r)
no_switch_prob = no_switch_wins / num_trials * 100.0
switch_prob = switch_wins / num_trials * 100.0
print( " WINS LOSSES %\n"
f"SWITCH: {switch_wins:>4} {num_trials-switch_wins:>6} {switch_prob:.02f}\n"
f"NOSWITCH:{no_switch_wins:>4} {num_trials-no_switch_wins:>6} {no_switch_prob:.02f}")
You have gotten the mechanics of the problem wrong so you are getting the wrong result. I have rewritten the choice mechanics, but I am leaving the user input stuff to you so that you can continue to learn python. This is one of many ways to solve the problem, but hopefully it demonstrates some things to you.
def get_choices():
valid_choices = [0, 1, 2] # these are the values for a valid sample
shuffle(valid_choices) # now randomly shuffle that list
return valid_choices # return the shuffled list
def get_door(user_choice):
return user_choice.index(0)
def monty_sim(n, kind):
"""
:param n: number of runs in this simulation
:param kind: whether to change the door or not, 0 - don't change, 1 = change door
:return: (win_rate, 1 - win_rate)
"""
wins = 0
for i in range(0, n):
game_doors = get_choices()
user_choice = get_door(get_choices()) # use the same method and find user door choice
# so there are two branches.
# In both, a door with a goat (game_door = 1) is chosen, which reduce the result to
# a choice between two doors, rather than 3.
if kind == 0:
if user_choice == game_doors.index(0):
wins += 1
elif kind == 1:
# so now, the user chooses to change the door
if user_choice != game_doors.index(0):
wins += 1
# Because the original choice wasn't the right one, then the new
# must be correct because the host already chose the other wrong one.
win_rate = (wins / n) * 100
return win_rate, 100 - win_rate
if __name__ == '__main__':
n = 1000
kind = 1
wins, loses = monty_sim(n, kind)
print(f'In a simulation of {n} experiments, of type {kind} user won {wins:02f} of the time, lost {loses:02f} of the time')

Appending a list which refers to a list inside a function

I have the task of producing a Blackjack game in Python which allows up to 4 human players to play plus the automated House.
I have to use a function 'get_deck' (see code below).
I am struggling to figure out how to get a card from 'get_deck' and append it to the player's list.
I managed to make the program when using my own defined list for the cards but for this assignment I have to use the 'get_deck' function. The '?????' in the below code are where I referenced my first card values list.
Here is my code:
def get_deck():
deck = [value + suit for value in '23456789TJQKA' for suit in 'SHDC']
random.shuffle(deck)
return iter(deck)
while True:
get_deck()
player1 = []
player2 = []
player3 = []
player4 = []
house = []
player1.append(random.choice(?????))
player2.append(random.choice(?????))
player3.append(random.choice(?????))
player4.append(random.choice(?????))
house.append(random.choice(?????))
player1_bust = False
player2_bust = False
player3_bust = False
player4_bust = False
house_bust = False
if number_players[0] == 1:
player1_total = total(player1)
while True:
player1_total = total(player1)
print "Player 1 has these cards %s with a total value of %d." % (player1, player1_total)
if player1_total > 21:
print "Bust!"
player1_bust = True
break
elif player1_total == 21:
print "Blackjack!"
break
else:
hit_stand = raw_input("Hit or Stand? (h or s): ").lower()
if 'h' in hit_stand:
player1.append(random.choice(?????))
else:
break
I hope this makes sense! Thanks in advance.
Using Python 2.7
The get_deck function is already randomly shuffling the deck for you. You don't need to get random elements from its list, because it's already randomized. Just get the next element from the iterator that get_deck returns.
https://docs.python.org/2/library/stdtypes.html#iterator-types

Categories

Resources