I want to give the second instance of my Player class the remaining marker after the first instance gets one of them.
class Player():
available_markers = ['X', 'O']
num_of_players = 0
player2_marker = ' '
def __init__(self):
self.name = input('Please enter your name : ')
self.marker = ' '
Player.num_of_players += 1
def choose_marker(self):
while Player.num_of_players != 2:
self.marker = input('Choose X or O')
if self.marker == Player.available_markers[0]:
Player.player2_marker == Player.available_markers[-1]
else:
Player.player2_marker == Player.available_markers[0]
else:
self.marker = Player.player2_marke
I would like to accomplish this in the instance method but have went through a lot of code that doesn't quite work.
There are some misunderstandings of object-oriented coding in your code so I'll try to address them in my answer. One of the goals of object-oriented programming is the separation of concerns. If you have some logic about how a game works and you have some logic about how a player works, you don't want the logic for both in the same place intermixed.
All the player really needs to know is what their name, marker and player number are:
class Player():
num_of_players = 0
def __init__(self, name, marker):
Player.num_of_players += 1
self.name = name
self.marker = marker
self.number = Player.num_of_players
print(self.number, self.marker)
Separate from that is how you want to start the game and initialize the players. You could create another class called Game but for now, I'll just do a function:
def start_game():
available_markers = ['X', 'O']
print("Player 1")
name = input('Please enter your name : ')
Let's not trust that the user of the program will enter the right thing:
while True:
marker = input('Choose X or O: ')
We will loop forever and just break out of it if a valid option is chosen:
if marker in available_markers:
break
else:
print("Invalid choice. Please pick again")
player1 = Player(name, marker)
We'll remove that marker from the list so the list just has one element in it now:
available_markers.remove(marker)
print("Player 2")
name = input('Please enter your name : ')
player2 = Player(name, available_markers[0])
start_game()
# Player 1
# Please enter your name : Adam
# Choose X or O: X
# 1 X
# Player 2
# Please enter your name : Joe
# 2 O
Note that I create two separate instances of Player.
Let's talk briefly about class variables vs instant variables. I kept num_of_players as a class variable to track the total number of players (accessible by doing Player.num_of_players or player1.num_of_players both will return that there are 2 total players). I also created another variable number so each player can track what their number is. That's an instance variable and tracked separately for each instance.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I am working on a Mastermind game in python, and one of my classes is called the Game class. This runs a 'setup' of the game as such (like finding the player count, player names etc.). However, one of my methods which checks the name inputted against a player list previously defined/stored in a separate class is bringing up an AttributeError when I try to append the name to a new list created in my Game class. This is what my Game class currently looks like:
class WorldOfMastermind:
"""WOM class - Runs whole game, takes results from other classes and stores them (namely players and their scores)"""
def __init__(self):
self.__playerList = []
self.__playerDetails = dict()
def run(self):
"""Run method - holds the menu screen - allows for the user to add player, show scores, play game or quit"""
cpuNames = ComputerPlayer.addDetails(self)
self.__playerList.extend((cpuNames))
start = input('What would you like to do?\n (r) register a new user\n (s) show the score board\n (p) play a game\n (q) quit\n')
if start == 'r':
tempName = HumanPlayer.addDetails(self)
for i in self.__playerList:
if i == tempName:
print('')
print('Sorry, that name already exists')
print('')
self.run()
self.__playerList.append(tempName)
self.__playerDetails[tempName] = [0, 0, float(0)]
print('Welcome,', tempName + '!')
print('')
self.run()
elif start == 's':
self.printScoreBoard()
elif start == 'p':
print('Let\'s play the game of Mastermind!')
Game.startPrep(self, self.__playerList)
elif start == 'q':
print('Thank you for playing the World of Mastermind!')
exit()
else:
print('\nSorry, that is an invalid input')
print('')
self.run()
def printScoreBoard(self):
""" Print the scoreboard by iterating through the dictionary """
print('=====================================')
print('Name Score Games Average ')
print('=====================================')
for i in self.__playerDetails:
print('{:<15} '.format(i), '{:>5}'.format(self.__playerDetails[i][0]), '{:>5}'.format(self.__playerDetails[i][1]), '{:>7}'.format(self.__playerDetails[i][2]))
print('=====================================\n')
self.run()
class Game:
"""Begin the initialization of the game and return results to WOM class"""
def __init__(self, playerCount):
self.__playerCount = playerCount
self.__playingList = []
def startPrep(self, playerList):
"""Prepares the game"""
Game.getPlayerCount(self)
Game.getPlayerNames(self, playerList)
def getPlayerCount(self):
"""Gathers the number of players"""
while True:
try:
self.__playerCount = int(input('How many players (2-4)?'))
except ValueError:
print('Only numbers allowed')
else:
if self.__playerCount < 2 or self.__playerCount > 4:
print('Player count must be between 2-4 inclusive')
else:
break
def getPlayerNames(self, playerList):
"""Gathers names of players and puts them into a list"""
while True:
if self.__playerCount == 2:
while True:
player1 = input('What is the name of player #1?')
if player1 in playerList:
print('successful')
self.__playingList.append(player1)
break
else:
print('Invalid username')
while True:
player2 = input('What is the name of player #2?')
if player2 in playerList:
if player2 not in self.__playingList:
print('successful')
self.__playingList.append(player2)
break
else:
print(player2, 'is already in the game.')
else:
print('Invalid username')
break
Where I feel the error is coming from is in the calling of the getPlayerNames method. As it takes a parameter (the player list from another class), this is purely to check that the name inputted is actually in the game, and if so it prints 'successful' (which it does) but when trying to append the inputted name into the new 'playingList' it brings up the error. I'm not sure why this is as the append line doesn't have any need to reference attributes from another class. Any advice would be appreciated thanks!
Your code works for me, formatted as below.. If I run the following, it asks for the player count and makes sure the names you give are in the eligible player list.
class Game:
"""Begin the initialization of the game and return results to WOM class"""
def __init__(self, playerCount=0):
self.__playerCount = playerCount
self.__playingList = []
def startPrep(self, eligible):
"""Prepares the game"""
self.getPlayerCount()
self.getPlayerNames(eligible)
def getPlayerCount(self):
"""Gathers the number of players"""
while True:
try:
self.__playerCount = int(input('How many players (2-4)?'))
except ValueError:
print('Only numbers allowed')
else:
if self.__playerCount < 2 or self.__playerCount > 4:
print('Player count must be between 2-4 inclusive')
else:
break
def getPlayerNames(self, playerList):
"""Gathers names of players and puts them into a list"""
for i in range(self.__playerCount):
while True:
s = 'What is the name of player #%d? '%(i+1)
player = input(s)
if player in playerList:
print('successful')
self.__playingList.append(player)
break
else:
print('Invalid username')
g = Game()
g.startPrep(['bob','bill'])
I am creating a random name generator using OOP in python however i am very new to this concept which is why i am having so difficulties with accessing methods in other methods. I read a post on stack overflow which said to call a method inside another method in a class, you must add self.funcname(param) however i have already done this and it still does not work
class Rndm_nme_gen:
def __init__(self):
print("THE RANDOM NAME GENERATOR")
self.value = ""
self.range = 5
self.counter = 0
self.loop = True
self.names = []
self.loop2 = True
self.take_input()
def take_input(self):
while self.loop:
user_input = input("ENTER A NAME: ")
self.num_check(user_input)
if self.value == "true":
print("INVALID NAME")
loop = True
elif self.value == "false":
self.counter += 1
self.names.append(user_input)
if self.counter == 5:
self.loop = False
self.genname()
#i am trying to call this function but it is not working as i hoped it would
def num_check(self, string):
self.string = string
for char in self.string:
if char.isdigit():
self.value = "true"
else:
self.value = "false"
def genname(self):
while self.loop:
gen = input("TYPE ENTER TO GENERATE A NAME OR TYPE 'q' TO QUIT").strip().lower()
if gen == " " or gen == "":
num = random.randint(0, 5)
print("NAME : " + str(self.names[num]))
loop == True
elif gen == 'q':
quit()
else:
print("UNKNOWN COMMAND")
loop = True
user1 = Rndm_nme_gen()
In the initialisation method, i called the take_input function so it automatically runs and from that function, i attempted to run the code from the genname function however the program would simply end
If you would like to run the code to see how it works, feel free to do so
Expected output:
ENTER NAME FDSF
ENTER NAME dfsd
ENTER NAME sdfds
ENTER NAME sfdff
ENTER NAME sfdf
TYPE ENTER TO GENERATE A NAME OR TYPE 'q' TO QUIT
it does not say TYPE ENTER TO GENERATE A NAME OR TYPE 'q' TO QUIT when i run the program
def letterChoice():
playerLetter = input('Please choose X or O.').upper()
if playerLetter in ['X','O']:
print('The game will now begin.')
while playerLetter not in ['X','O']:
playerLetter = input('Choose X or O.').upper()
if playerLetter == 'X':
computerLetter = 'O'
else:
computerLetter = 'X'
turnChooser()
def turnChooser():
choice = input("Would you like to go first, second or decide by coin toss?(enter 1, 2 or c) ")
while choice not in ["1","2","c"]:
choice = input("Please enter 1, 2 or c. ")
if choice == 1:
print("G")
cur_turn = letterChoice.playerLetter()
elif choice == 2:
print("H")
else:
print("P")
moveTaker()
I can't figure out how I'm supposed to inherit playerLetter into turnChooser(), I've tried putting playerLetter into the brackets of each function but they don't pass and create an argument error and the print("G") and so on are simply there to see if the code works but whenever I enter 1 or 2 "P" is outputted.
You need to define function Attributes for playerLatter
For EX:
def foo():
foo.playerletter=input('Please choose X or O.').upper()
>>> foo()
Please choose X or O.x
>>> foo.playerLetter
'X'
Accessing from another function
def bar():
variable=foo.playerLetter
print(variable)
>>> bar()
X
>>>
You can always check what Attributes are available for a given function
>>> [i for i in dir(foo) if not i.startswith('_')]
['playerLetter']
>>>
Edit turnchooser() to turnchooser(var), then when calling the function pass the letter to the function like this:
def LetterChoice():
Code...
turnchooser(playerletter)
And,
def turnchooser(var):
Code...
The letter will be placed in a variable called var, which means your code will use the letter as var not playerletter.
Of Course you can change the names to whatever you like.
You could add as many variables to the function however they all should have something assigned to them, aka you can't call the previous function like so:
turnchooser()
Unless you assign it a default value:
def turnchooser(var = 'x')
This way whenever the function is called the value of "var" is x unless stated otherwise.
Note that if you want to pass it from one function to another, u either have to assign the letter to a variable then call the function outside the "LetterChoice" or call it in the definition of "LetterChoice"
Within the function that has the variable in it type:
global variableName
Obviously change variableName to whatever the variable is actually called. Hope this helps!
Tommy
You should try using classes: Python documentation
This should be the code:
class Game:
def __init__(self):
self.cur_turn = ''
self.choise = ''
self.playerLetter = ''
self.computerLetter = ''
def letterChoice(self):
while True:
self.playerLetter = input('Please choose X or O.').upper()
if self.playerLetter in ['X','O']:
print('The game will now begin.')
if playerLetter == 'X':
self.computerLetter = 'O'
else:
self.computerLetter = 'X'
break
else:
print ('Please enter only X or O')
def turnChooser(self):
while True:
self.choice = input("Would you like to go first, second or decide by coin toss? (enter 1, 2 or c) ")
if self.choice in ["1","2","c"]:
if self.choice == 1:
print("G")
self.cur_turn = self.playerLetter()
elif self.choice == 2:
print("H")
else:
print("P")
break
else:
print ('Please enter 1, 2 or c')
game = Game()
game.letterChoice()
game.turnChooser()
# If you want to read any of the variables in Game just write 'self.VARIABLE_NAME'
This is a smaller portion of the main code I have been writing. Depending on user selection they can add player informationa and then print the information from the dictionary player roster. I want to store the information and then print in this format but I havent been able to figure out how to do this.
Name ****
Phone Number ****
Jersey Number ****
Im new to dictionaries but I have spent hours reading and searching over the past couple of days about dictionaries and have tried several different ways to do this but failed. I have gotten the closest the way I have it setup now but it still doesnt work right. I feel like I am storing the information incorrectly into the dictionary for starters, any help would be greatly appreciated.
player_roster = {}
def display_roster(self): #Print Roster
if len(player_roster) != 0:
for x in player_roster.keys():
print('Name:', x, 'Phone Number:', player_roster[x])
else: #Print No One on Roster
len(player_roster) == []
print('No names have been entered:')
def add_player(self,): #Enter Members Name
name = input('Enter New Players Name:')
phone_number = input('Enter Players Phone Number:')
jersey_number = int(input('Enter Players Jersey Number'))
player_roster[name] = phone_number, 'Jersey Number', jersey_number
#If I input Toby as Name 444-444 as Phone Number and 3 as Jersey number it outputs like this
Name: Toby Phone Number: ('444-4444', 'Jersey Number', 3)
# I would like it to output like
Name: Toby
Phone Number: 444-4444
Jersey Number: 3
There are some things i would change in your code but to keep this close to what you asked for take a look at this:
def display_roster():
if len(player_roster) != 0:
for x in player_roster.keys():
print('Name:', x)
print('Phone Number:', player_roster[x][0])
print('Jersey Number:', player_roster[x][1])
else:
print('Roster is empty.')
return
player_roster = {}
def add_player():
name = input('Enter New Players Name:\t')
phone_number = input('Enter Players Phone Number:\t')
jersey_number = int(input('Enter Players Jersey Number:\t'))
player_roster[name] = [phone_number, jersey_number]
return
add_player()
display_roster()
# PRINTS:
#Name: Toby
#Phone Number: 444-4444
#Jersey Number: 3
Printing in multiple lines gives you the result you want. As stated in the comments this can also be done with a single print() statement but i do not think compact code makes much difference to you yet.
Further, this len(self.player_roster) == [] line does not make sense. This is as good as simply writing True in a line. The "emptiness" of the team is checked by the else:.
Finally, i would slightly change the way players are stored in the "Roster" dictionary and have it like this: {"Toby": ['444-4444', 3], ...}
I would propose that you replace the print statement to this:
print(" Name: %s \n Phone Number: %s \n Jersey Number: %d") % player_roster[x]
You're pretty much there. The below modification would allow you to print as you need (and is slightly more readable):
class PlayerDictionary():
def __init__(self):
pass
player_roster = {}
def display_roster(self): #Print Roster
if len(self.player_roster) != 0:
for key, value in self.player_roster.iteritems():
print(str(key) + ": " + str(value))
else: #Print No One on Roster
len(self.player_roster) == []
print('No names have been entered:')
def add_player(self,):
self.player_roster['Name'] = input('Enter New Players Name:')
self.player_roster['Phone Number'] = input('Enter Players Phone Number:')
self.player_roster['Jersey Number'] = int(input('Enter Players Jersey Number'))
if __name__ == "__main__":
player = PlayerDictionary()
player.add_player()
player.display_roster()
A slightly more maintainable solution would be to create a class for Player. Set the properties on the object and overload the str function e.g.
class Player(object):
def __init__(self):
self.__name = ""
self.__phone_number = ""
self.__jersey_number = ""
#property
def name(self):
return self.__name
#property
def phone_number(self):
return self.__phone_number
#property
def jersey_number(self):
return self.__jersey_number
#name.setter
def name(self, val):
self.__name = val
#phone_number.setter
def phone_number(self, val):
self.__phone_number = val
#jersey_number.setter
def jersey_number(self, val):
self.__jersey_number = val
def __str__(self):
return ("Name: %s\nPhone Number: %s\nJersey Number: %s" % (str(self.__name), str(self.__phone_number), str(self.__jersey_number)))
if __name__ == "__main__":
player = Player()
player.name = input('Enter New Players Name:')
player.phone_number = input('Enter Players Phone Number:')
player.jersey_number = int(input('Enter Players Jersey Number'))
print(player)
I'm a complete novice to python and sage so I need some help and clarification on the steps all the way through. This is a question concerning game theory.
First I will describe the algorithm and then I will propose a solution the best I can.
The algorithm:
I want to start the program with a random variable from 1-100. This
variable will be defined 'S'. I also want to define a set of variables
'C' which can be deducted from S every turn, this set is {1,2,3,4,5,6}
(in other words the user and computer can deduct 1, 2, 3, 4, 5 or 6
from S. If variable S is divisible by 7 (e.g. 21), then print: "I
lose". If not, the game can begin.
Let's say that the random variable turns out to be 20. The player is
now prompted to enter a number within the range of C. When the player
has entered the number, I want the program to deduct that number from
S, so if the player enters 4 (a legal move), S is then 20-4=16. The
computer then calculates mod(S,7) and finds out that modulo 16,7 is 2
so it deducts 2 from S, in other words, 16-2=14.
If the player enters a number which results in S being divisible by 7, such as 6 (20-6=14) then the computer simply deducts 1 and attempts to get to such a number again next round.
The game continues until the computer eventually wins as the player is
eventually placed at 7 and has to deduct a number which the computer
can finish with (user deducts 6, computer deducts the last one and
wins). Print: "I win".
So like I said, I have literally no experience in python and sage so I can only go by my (limited) java experience:
I would attempt to establish a variable S with some 'ran' element (no idea what it's called in python). I would then attempt something like:
if S%7=0 then print "I lose"
else
prompt "Pick a number between 1 and 6, those included".
Declare user input as variable U.
Do S-U=S
Now do S-S%7=S
Now I want the program to realize when S=7 and then print: "You lose". If you can help me go all the way, though, that would be great.
import random
def playgame():
s = random.randint(1,100) #grabs a random integer between 1 and 100
POSS = range(1,7) #range ignores the last number, so this is [1,2,3,4,5,6]
if not s % 7: #if s%7 != 0
print("I lose")
return #exit the function
while s > 0: #while s is still positive
choice = 0 #set choice to 0 (this may as well have been "foo",
# I just needed it to not be in POSS)
while choice not in POSS: #until the user picks a valid number
choice = int(input("Select a number between 1 and 6: ")) #prompt for input
s -= choice #subtract choice from s, then set the difference to s
print("You subtracted {}, leaving {}".format(choice,s)) #print for the user
comp_choice = s%7 #the computer's choice is always s%7
s -= comp_choice #subtract the comp's choice from s, then set the diff to s
print("I subtracted {}, leaving {}".format(comp_choice,s)) #print for user
print("I win!") #since we know computer will always win, I don't have to do a check
playgame() #run the function
Here's a vastly more complicated function that does essentially the exact same thing ;-)
class Entity(object):
"""Base class that should not be instantiated on its own -- only
exists to be inherited from. Use Player() and Computer() instead"""
def __init__(self,name=None):
if name is None:
name = input("What's your name? ")
self.name = name
self.myturn = False
def __str__(self):
# this magic function means calling str(self) returns str(self.name)
# included so I can do print(player)
return self.name
def makemove(self,choice):
"""finds the global s and subtracts a given choice from it,
printing the choice and the result to the user."""
global s
s -= choice
print("{} chooses {}, leaving {}".format(self,choice,s))
return choice
def activate(self):
self.myturn = True
return self
def deactivate(self):
"""does exactly self.myturn = False"""
self.myturn = False
class Player(Entity):
"""A player-controlled Entity"""
def getchoice(self):
"""Prompts the user for a choice, ensuring it's between 1 and 6, then
calls Entity's makemove() with that as an argument"""
choice = None
while choice not in range(1,7):
choice = int(input("Pick a number between 1 and 6: "))
return super().makemove(choice)
class Computer(Entity):
def __init__(self):
super().__init__(name="Computer Player")
#overrides to ensure every Computer object has the name Computer Player
def getchoice(self):
"""grabs a number for the computer, and makes its move"""
global s
choice = s%7
if choice == 0: #edge case where computer goes first on an s where s%7==0
choice = random.randint(1,6)
return super().makemove(choice)
class Game(object):
"""Class defining an instance of the Game
FUNCTIONS:
Game.start() <-- use this to start the game"""
def __init__(self,playerArray=[]):
"""defines s as a global, ensures the players array is built
correctly, and gives s a random int value between 1-100"""
global s
if type(playerArray) is Player:
playerArray = [playerArray]
while len(playerArray) < 2:
playerArray.append(Computer())
self.players = playerArray
s = random.randint(1,100)
def start(self):
"""Let's play!"""
global s
print ("""
====================================
THE GAME BEGINS NOW!!!
We will begin with a value of: {:3}
====================================""".format(s).lstrip())
turn = random.randint(1,len(self.players))-1
while True:
try:active_player = self.players[turn].activate()
except IndexError: print(turn)
choice = active_player.getchoice()
if s <= 0: break
active_player.deactivate() # is active_player.myturn = False
turn += 1
if turn == len(self.players): turn = 0 #wrap the list
for player in self.players:
#this will execute the turn s becomes zero
if player.myturn:
winner = player
break
print("Winner: {}".format(winner))
import random
game = Game()
game.start()
S=random.randint(1,100) #will pick a random number
user_input = int(raw_input("Enter a number:")) #will get an integer from the user
#subtraction and modulo work just like in any other language ...
if(condition):
do_something() #is the format for if statements
does that cover all your questions? or did I miss some?