How do I add points to a total in treasure hunt game? - python

So Im making a treasure hunt game in which the user is placed on a grid as 'P' and can move around to collect coins from chests ('X') which are shown on the grid. On the same gird, bandits('B') are also present which take away all previously collected coins.
Now, Ive gotten as far as allowing the player to move around the board but dont know how to add coins to the already created coins variable when the player lands on the treasure.
This is the relevant part of the code which randomly placed 5 Bandits and 10 treasure chests on the board:
def bandits(board):
added_bandits = 0
while added_bandits < 5:
x_bandit = r.randint(0,7)
y_bandit = r.randint(0,7)
if board[x_bandit][y_bandit] == 'O':
board[x_bandit][y_bandit] = 'B'
added_bandits = added_bandits + 1
def treasures(board):
added_treasure = 0
while added_treasure < 10:
x_treasure = r.randint(0,7)
y_treasure = r.randint(0,7)
if board[x_treasure][y_treasure] == 'O':
board[x_treasure][y_treasure] = 'X'
added_treasure = added_treasure + 1

I would create a class Player, where you store this information and that manage the adding/removing of the coins of the player.
class Player(object):
def __init__(self, name):
self.playername = name
self.total_coins = 0
def add_coins(self, number):
self.total_coins += number
def remove_coins(self, number):
self.total_coins -= number
def move(self, move_data):
#implement here the players's move semantic
def print_total_coins(self):
print("Total coins %d" % (self.total_coins))
That way you can get the total coins score like this:
player1 = Player("Player 1")
player1.print_total_coins()
I would further encapsulate the bandits and the treasures in classes too.

Related

Why is my card deck adding more cards in a sequence the more you draw in a loop?

I'm trying to make a deck of cards, and it's' gone very good for the most part. I'm stuck right now because when I try to draw a card, it adds a card every time. For example, during the third loop of drawing cards, I ask to draw three. It actually gives me information for five cards. Please help if you can.
Here's my code:
class Card:
def __init__(self, direction, arrows):
self.direction = direction
self.arrows = arrows
def show(self):
print("This card has", self.arrows, self.direction, "facing arrows.")
class Deck:
def __init__(self):
self.cards = []
self.build()
def build(self):
for d in ["north", "east", "south", "west"]:
for a in range(1, 4):
self.cards.append(Card(d, a))
def show(self):
for c in self.cards:
c.show()
def shuffle(self):
for i in range(len(self.cards) - 1, 0, -1):
r = random.randint(0, i)
self.cards[i], self.cards[r], = self.cards[r], self.cards[i]
def drawCard(self):
return self.cards.pop()
class Player:
def __init__(self, name):
self.name = name
self.hand = []
def draw(self, deck):
self.hand.append(deck.drawCard())
return self
def showHand(self):
for card in self.hand:
card.show()
cardamount = 24
while cardamount > 1:
choice = input("What do you want to do?\n")
deck = Deck()
joe = Player
if choice == "draw":
numberchoice = (int(input("How many?\n")))
if numberchoice <= cardamount:
for count in range(numberchoice):
deck.shuffle()
joe.draw(deck)
joe.showHand()
deck.shuffle()
cardamount = cardamount - 1
else:
print("NOT AN OPTION")
print("You ran out of cards.")```
for count in range(numberchoice):
deck.shuffle()
joe.draw(deck)
joe.showHand()
deck.shuffle()
cardamount = cardamount - 1
Each time through the loop, you draw one card and then show the whole hand.
So if you draw three cards, you would draw the first card and show it, then draw the second card and show both of them, then draw the third card and show all three, for a total of six cards shown.
To fix this, move showHand() outside of the draw loop.

Drawing unique cards from a deck for a game of BlackJack in Python

I'm making a multi-player game of blackjack and having been encountering issues getting the code (in python) to deal unique cards to multiple players. The code below has been dealing the same set of cards to all players.
An example of the results for 2 players is as follow:
Player1's first card is Four of Hearts.
Player1's second card is Nine of Clubs.
Player2's first card is Four of Hearts.
Player2's second card is Nine of Clubs.
I have been reviewing the code and making amendments to the function of dealingcards, e.g. by using a while loop to go through each player and appending two cards to their hand. However, the result is no different.
Will anyone be able to advise where the error in the code lies? Thank you.
Code as shown below:
"""This is a game of Blackjack."""
import random
"""Defining the attributes of the cards"""
suits = ('Hearts', 'Diamonds', 'Spades', 'Clubs')
ranks = ('Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King', 'Ace')
"""Class class must be able to understand the Suit and Rank of a card"""
class Card:
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
def __str__(self):
return self.rank + " of " + self.suit
"""Deck class must be able to:
Instantiate a new deck and hold as a list of card objects;
Shuffle a deck through a method call; and
Deal cards from the deck."""
class Deck:
def __init__(self):
self.all_cards = []
for suit in suits:
for rank in ranks:
created_card = Card(suit,rank)
self.all_cards.append(created_card)
def shuffle(self):
random.shuffle(self.all_cards)
def deal_one(self):
return self.all_cards.pop()
def __str__(self):
statement = ""
for card in self.all_cards:
statement = statement + card.rank + " of " + card.suit + "\n"
return statement
"""Hand class must be able to:
Store the hands of the player;
Compute the value of each hand"""
class Playerhand:
def __init__(self,name,hands=[[],[],[],[]]):
self.name = name
self.hands = hands
def num_of_hands(self):
num_of_hands = 0
for hand in self.hands:
if hand != []:
num_of_hands += 1
else:
pass
return num_of_hands
def show_first_card(self):
print("{}'s first card is {}".format(self.name,self.hands[0][0]))
print("{}'s second card is {}".format(self.name,self.hands[0][1]))
def value_of_hands(self):
value_of_hands = []
for hand in self.hands:
total_value = 0
values = {'Two':2, 'Three':3, 'Four':4, 'Five':5, 'Six':6, 'Seven':7, 'Eight':8, 'Nine':9, 'Ten':10, 'Jack':10, 'Queen':10, 'King':10, 'Ace':11}
check_for_aces = []
for card in hand:
if card.suit == 'Ace':
check_for_aces.append('Ace')
else:
pass
for card in hand:
total_value = total_value + values[card.rank]
for item in range(0,len(check_for_aces)):
if total_value > 21:
total_value = total_value - 10
else:
pass
value_of_hands.append(total_value)
return value_of_hands
"""Pre-game:
Asking for the number of players to CREATE A LIST OF PLAYERS ['Dealer', 'P1', 'P2', etc.] and a DICTIONARY OF WAGERS {"P1": $X, "P2": $Y, etc.}"""
def number_of_players():
number_of_players = input("How many players are we expecting? Please enter 1 to 7: ")
while number_of_players.isdigit() == False or int(number_of_players) not in range(1,8):
number_of_players = input("Only accepting integer values between 1 to 7. Please enter 1 to 7: ")
return int(number_of_players)
def check_float(potential_float):
try:
float(potential_float)
return True
except:
return False
def playername(no_of_players):
print("We are expecting {} player(s). We are going to start collecting information on player names and wager!".format(no_of_players))
player_list = ['Dealer']
for number in range(1,no_of_players+1):
name = input("Player {}, what is your name? ".format(number))
while name in player_list:
name = input("Player {}, your chosen name has been taken. Please give us an alternative: ")
player_list.append(name)
return player_list
def playerwager(player_list):
player_wager = {}
for number in range(1, len(player_list)):
wager = input("{}, how much are you betting? Please input number: $ ".format(player_list[number]))
while check_float(wager) is False:
wager = input("{}, please input a valid wager in number: $ ".format(player_list[number]))
wager = float(wager)
player_wager[player_list[number]] = wager
player_wager["Dealer"] = 0
return player_wager
def dealingcards(player_list):
newdeck = Deck()
newdeck.shuffle()
print(newdeck) # Remove in due course.
for player in player_list:
for item in range(0,2):
Playerhand(player).hands[0].append(newdeck.deal_one())
Playerhand(player).show_first_card()
#GAME ON
x = number_of_players()
playerlist = playername(x)
playerwager(playerlist)
dealingcards(playerlist)
This part of the code is wrong:
for player in player_list:
for item in range(0,2):
Playerhand(player).hands[0].append(newdeck.deal_one())
Playerhand(player).show_first_card()
You have to store the playerhand and not redefine it when showing the first card:
playerhands = []
for player in player_list:
playerhands.append(Playerhand(player,hands=[[],[],[],[]]))
for item in range(0,2):
playerhands[-1].hands[0].append(newdeck.deal_one())
playerhands[-1].show_first_card()
EDIT: This is the true source of the problem
"Least Astonishment" and the Mutable Default Argument
While Heiner is on the right track, I went through with a debugger and found that doing:
ph = Playerhand(player)
Mysteriously wasn't clearing the hand. The data seems to almost be static. However, a simple bandaid fix is as follows:
for player in player_list:
ph = Playerhand(player)
ph.hands[0] = []
for item in range(0, 2):
card = newdeck.deal_one()
ph.hands[0].append(card)
ph.show_first_card()
The hands were never clearing and that's why they kept outputting the same hand.

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()

Python game logic: "coins" variable is not incrementing

I am working on a game where the player is in search of treasure. Everything works perfectly, although my money system does not work. I need my code to work so that if the user lands on a treasure chest, they gain 10 extra coins. However, their number of coins is being set to 10 instead of adding 10.
import easygui
import time
from random import *
# Set up Initial Variables
Money = 0
grid = []
character = "X"
# player_loc will hold the x, y location of the player
player_loc = (0, 0)
# These are a mapping of direction
NORTH = "N"
SOUTH = "S"
EAST = "E"
WEST = "W" #All variables used for Later on
Treasure = "T"
Goblin = "G"
def menu(): #function
msg = "Would you like to...?" #Users choice to start game
buttons = ["start", "quit"]
while True:
title = "Menu"
selection = easygui.buttonbox(msg, title , buttons)
if selection == "quit":
exit()
elif selection == "start": #If users input is to start the game the all of this appears("Welcome to the treasure hunt game!")
easygui.msgbox("These are the rules! You have a choice of a grid ranging from a 3x3 choice to a 20x20 choice")
easygui.msgbox("In these grids, bandits and treasure chests will spawn at random locations, hidden to you.")
easygui.msgbox("You will have a choice of the amount of goblins and treasures you would like to spawn in, ranging from 1-2")
easygui.msgbox("You will move around the map, in search of treasures which will give you 10 gold. Although landing on a goblin would deduct the amount of gold to 0.")
easygui.msgbox("Furthurmore, just deciding on a position you would like to move to, would give you an extra 1 piece of gold.")
easygui.msgbox("You can only find the same treasure chest two times before it's replaced by a bandit.")
easygui.msgbox("To check the amount of gold you have and the amount of bandits and treasure chests in the grid. Simply type 'status'")
easygui.msgbox("Don't forget! If you have collected all the treasure chests and you don't have 100 gold, you lose the game!")
easygui.msgbox("Good luck, you will now be entered into the game")
easygui.msgbox("Ok! let's jump into the game!")
setupGrid()
Chests_and_Goblins()
def setupGrid(): #New function for creating grid
global grid #Adding/creating global variables
global row
global N
N = easygui.integerbox("How big would you like the grid to be?") #User input
while int(N) > 20: #Changing N to an integer so computer understamds
N = easygui.intergerbox("That number is too high, The grid has to be at a size of under 20x20")
else:
while int(N) < 3 : # Asking the user to input again as number is too high or low
N = easygui.integerbox("That number is too low, the grid has to be a size of over 3x3. Please try again")
for x in range(0, (int(N))):#For everything in range N
row = [] #The N amount of rows are created
for y in range(0, (int(N))): #For everything in range N
if x == player_loc[0] and y == player_loc[1]: #If the positions is equal to th player location
row.append(character) # Add the character in
else:
row.append('O') #Add the same amount of 0's as N
grid.append(row)
def Chests_and_Goblins(): #Function used for adding the treasures and goblins in the grid
global grid
global row
global Treasure
B = easygui.enterbox(" How many chests would you like in the grid? The amount of chests you like is given by the amount of C's")
F = easygui.enterbox(" How many Bandits would you like in the grid? The amount of bandits you like is given by the amount of B's")
for each in B:
grid[randint(0, int(N)-1)][randint(0, int(N)-1)] = Treasure
for each in F:
grid[randint(0, int(N)-1)][randint(0, int(N)-1)] = Goblin
gridRunner()
def moveSouth(n):
global player_loc
grid[player_loc[0]][player_loc[1]] = "O"
grid[player_loc[0] + n][player_loc[1]] = character
player_loc = (player_loc[0] + n, player_loc[1])
money()
def moveNorth(n):
global player_loc
grid[player_loc[0]][player_loc[1]] = "O"
grid[player_loc[0] - n][player_loc[1]] = character
player_loc = (player_loc[0] - n, player_loc[1])
money()
def moveEast(n):
global player_loc
grid[player_loc[0]][player_loc[1]] = "O"
grid[player_loc[0]][player_loc[1] + n] = character
player_loc = (player_loc[0], player_loc[1] + n)
money()
def moveWest(n):
global player_loc
grid[player_loc[0]][player_loc[1]] = "O"
grid[player_loc[0]][player_loc[1] - n] = character
player_loc = (player_loc[0], player_loc[1] - n)
money()
def gridRunner():
while True:
for row in grid:
print (row)
switch = {NORTH : moveNorth,
SOUTH : moveSouth,
EAST : moveEast,
WEST : moveWest }
print (" ")
P = easygui.enterbox("What direction would you like to move in? North (N), South(S), East(E) or West(W)?")
if P not in switch:
easygui.msgbox("invalid move")
continue
distance = easygui.integerbox("How far would you like to move in this direction? (blocks are the units)")
switch[P](distance)
def money():
global player_loc
global character
global Treasure
if player_loc == Treasure:
print("Well done, You have gained coins")
money = 10
else:
print ("You got nothing")
money = 0
menu()
In this part here:
if player_loc == Treasure:
print("Well done, You have gained coins")
money = 10
You are setting the money to 10, not adding 10. All you need to do is:
money += 10
Also make sure def money(): isn't indented; it won't work as it currently is indented.
It looks like you have to indent the code under your money() function first:
def money():
global player_loc
global character
global Treasure
if player_loc == Treasure:
print("Well done, You have gained coins")
money = 10
else:
print ("You got nothing")
money = 0

Passing Objects Between functions?

I am new to programming in python and, I started writing a simple text based adventure game. I came across a problem when passing an object from one function to another. Here is my code:
import random
import time
num = random.randint(0,2)
xp1 = random.randint(1,2)
class player:
def __init__ (self, name, health, strength, defense, potion, xp, level):
self.__health = health
self.__strength = strength
self.__defense = defense
self.__name = name
self.__potion = potion
self.__xp = xp
self.__level = level
def getName(self):
return self.__name
def getHealth(self):
return self.__health
def getStrength(self):
return self.__strength
def getDefense(self):
return self.__defense
def getPotion(self):
return self.__potion
def getXP(self):
return self.__xp
def getLevel(self):
return self.__level
def setHealth(self):
self.__health = 10
def setLevel(self):
self.__level = 1
def subHealth(self, num):
self.__health -= num
def subPotion(self):
self.__potion -= 1
return self.__health
def addPotion(self, num1):
self.__potion += num1
def addHealth(self):
self.__health +=2
def addStrength(self):
self.__strength += 1
def addDefense(self):
self.__defense += 1
def addXP(self):
self.__xp += xp1
def addLevel(self):
self.__level += 1
self.__addHealth += 1
self.__defense += 1
self.__strength += 1
def battle(enemy, player1, name1):
player1 = player(name1, player1.getHealth(), player1.getStrength(), player1.getDefense(), player1.getPotion(), player1.getXP(), player1.getLevel())
enemy = player('Dongus', enemy.getHealth(), enemy.getStrength(), enemy.getDefense(), enemy.getPotion(), enemy.getXP(), enemy.getLevel())
s = 0
while s == 0:
time.sleep(1)
attack =int(input("Type 1 to attack, type 2 to use a potion."))
if attack == 1:
time.sleep(1)
print("Dongus's health is", enemy.subHealth(num))
print("Dongus hit you and your health is now at", player1.subHealth(num-player1.getDefense()))
elif attack == 2:
time.sleep(1)
print("You used a potion.")
player1.addHealth(), player1.subPotion()
if player1.getHealth() > 10:
player1.setHealth()
print("Dongus hit you and your health is now at", player1.subHealth(num-player1.getDefense()))
if enemy.getHealth()<=0:
print("Congratulations, you won! You recieved", xp1, "xp!")
player.addXP()
s = 2
def main():
name1 = input("What would you like your name to be?")
time.sleep(1)
print("Hello,", name1, "you are on a quest to save otis from the evil Dongus. You must slay him, or Otis will poop.")
time.sleep(2)
player1 = player(name1, 10, 2, 1, 0, 0, 1)
enemy = player('Dongus', 8, 4, 0, 0, 0, 0)
print("Your stats are, health:", player1.getHealth(), "strength:", player1.getStrength(), "and defense:", player1.getDefense())
time.sleep(2)
print("Fight!")
pick = input("You found a health potion! Press 'p' to pick it up.")
p = 0
while p == 0:
if pick == "p":
print("You added a potion to your inventory.")
player1.addPotion(1)
p = 2
else:
print("You have no potions, you should probably pick this one up.")
player1.addPotion(1)
p = 2
battle(enemy, player1, name1)
if self.__getXP() == 1:
print("You leveled up. You are now level 2.")
player1.addLevel()
print("Your stats are, health:", player1.getHealth(), "strength:", player1.getStrength(), "and defense:", player.getDefense())
loot1 = int(input("Type ''1'' to loot the enemy chest."))
if loot1 == 1:
print("You recieved two potions!")
player1.__addPotion(2)
enemy.setHealth(10)
battle(enemy, player1, name1)
main()
Now the problem is when I run the game, I get to a point where I type "1" to attack the enemy, but it says, for some reason, that after attacking the enemy, the enemies health is at "None". This is the same case when the enemy attacks player1, it says player1's health is at "None". I assume that "None" is the default value in python 3.4.1, so my thinking is that the player1's object from def main() are not being transferred over to def battle() and I cannot see the reason why this is happening. I most likely am missing something here, or it is something I do not already know about Python that is causing the issue. Does anybody know what I can do to fix this, and why it is doing this?
BTW some of the terms I am using may be wrong, so please correct me if they are... I have only been coding for 2 weeks :p.
Thanks!!!
First, received not recieved
2nd yes, If you have a Python function that does not return a value, the result is None
# dummy will return "Positive" or None
def dummy(x):
if X > 0:
return "Positive"
So, you probably want to change
def subHealth(self, num):
self.__health -= num
to
def subHealth(self, num):
self.__health -= num
return self.__health
Your question re: the "player" classes from def main() are not being transferred over to def battle() does not really make sense to me.
But, I see that in the first 2 lines of battle, you are replacing the formal parameters player1 and enemy with local variables, this seems like odd usage in your program.

Categories

Resources