Really struggling with classes..

0 Chris Nelson · January 3, 2015
So, I have been having a tough time getting the grasp of classes.. I am trying to throw some code together to get a better understanding but I keep receiving..


Traceback (most recent call last):
  File "C:/Users/chrisutpg/PycharmProjects/GuessGame/GuessGameV3.py", line 92, in <module>
    GuessGame.guess_num(Player.name)
AttributeError: type object 'Player' has no attribute 'name'


Isn't name, set in __init__ in the Players class?

Also, if you look at the way I figure out how many people are going to play, it seems so redundant? I thought about trying to create a blank dictionary and then run a for loop in range of number of players, and store the user input in each value. Which does work, however then I have no way to pass those values into __init__ in the Player class correct? The code below should explain it better.. Any help, would be great. I cannot wrap my head around this. I am sure I making it more complicated than it needs to be!

users = {}
for x in range(1,num_of_players+1):
users["user" + x] = input('What is your name? ')


Actual code below..


"""
Guessing Game Version 3.0 // 1/3/15
My attempt at creating and using classes.
Written by Chris Nelson.
"""

import time, random, os
__author__ = 'chrisutpg'

class Player:
    """
    This class will find out how many players are playing our game.
    It will also give out there starting values, and track there wins and losses.
    """
    def __init__(self, name):
        self.name = name
        self.guesses = 0
        self.games_won = 0
        self.games_lost = 0
        self.max_guesses = 10
        print("Hi {}, welcome to the game!\n"
              "you have {} guesses remaining!\n".format(self.name, self.max_guesses))

    def HowManyPlayers():
        global user1, user2, user3, user4
        print("The maximum number of players is 4!")
        num_of_players = input("How many players do you have? ")
        num_of_players = int(num_of_players)
        if num_of_players == 1:
            user1 = input("Please enter first user: ")
            user1 = Player(user1)
        elif num_of_players == 2:
            user1 = input("Please enter first user: ")
            user1 = Player(user1)
            user2 = input("Please enter second user: ")
            user2 = Player(user2)
        elif num_of_players == 3:
            user1 = input("Please enter first user: ")
            user1 = Player(user1)
            user2 = input("Please enter second user: ")
            user2 = Player(user2)
            user3 = input("Please enter third user: ")
            user3 = Player(user3)
        elif num_of_players == 4:
            user1 = input("Please enter first user: ")
            user1 = Player(user1)
            user2 = input("Please enter second user: ")
            user2 = Player(user2)
            user3 = input("Please enter third user: ")
            user3 = Player(user3)
            user4 = input("Please enter fourth user: ")
            user4 = Player(user4)
        else:
            print("Sorry, that is not a valid choice.\nYou either tried to exceed the maximum\n"
                  "amount of players or did not enter a number!\nTrying again..")
            time.sleep(2)
            return Player.HowManyPlayers()

    def get_guesses(self):
        print("You have taken {} guesses!".format(self.guesses))

    def get_game_record(self):
        print("{} you have {} wins, and {} losses!".format(self.name, self.games_won, self.games_lost))

class GuessGame:
    def __init__(self):
        self.random_number = random_number

    def guess_num(self):
        random_number = random.randint(1, 20)
        found = False
        while not found:
            print(random_number)
            userguess = input("{} Pick a number between 1 and 20..".format(u1.user1))
            userguess = int(userguess)
            Player.guesses += 1
            if userguess == random_number:
                Player.games_won += 1
                print("You won!")
                found = True
            elif Player.guesses == Player.max_guesses:
                Player.games_lost += 1
                print("Sorry, you reached the maximum guesses! Game over.")
                found = True
            else:
                print("That is not it.. Keep trying!")
                print("You have taken {} guesses!".format(Player.guesses))


u1 = Player
Player.HowManyPlayers()
GuessGame.guess_num(Player.name)
user1.get_game_record()
user2.get_game_record()

Post a Reply

Replies

Oldest  Newest  Rating
0 Jay Tauron · January 4, 2015
In the Player class, where you call the methods like Player.HowManyPlayers() or use variables like Player.guesses you need to use the self object instead, so self.HowManyPlayers() and self.guesses, also you cannot use variables from another class like when your GuessGame class references the Player class, it can't do that. At the end when you call methods from Player or GuessGame, you need to create an instance first. A class is sort of like a framework which you use to create other objects. It seems like you should create a player class for 1 player, then have the game class which takes the Player as an argument and then at the end get input to create different users with the Player class and then use the game class to play the game and will handle each player separately, it might possibly be easier to have the game class as a function in the Player class? If you're really stuck and/or confused I'll give you a hand with it and explain fully what's going on
+1 Chris Nelson · January 4, 2015
Thanks Jay. 

Do you pass the argument like  a regular variable? i.e GameClass.GuessGame(user1) -- which was created in the Player class, or do you pass it in like, GameClass.GuessGame(Players.user1)


I think, I understand how a class works. But I am having trouble applying it to this particular situation. i.e I could use a class to create students with different attributes on test scores, attendance, homework, etc. This is a good place to use a class because you may need to add or take away students. You wouldn't want to have to go back and do it manually for each student.

Maybe I'm just not trying to use them in the right way? Maybe the game doesn't really apply to using a class?

See I keep getting a name error here when I try calling the function add player:

class Player:
"""
This class asks the player for a name and sets
the maximum guesses. It also keeps track of the
players wins and losses
"""
def __init__(self, name):
self.name = name
self.player_max_guess = 20
self.player_wins = 0
self.players_losses = 0
print("{} welcome to our game!".format(self.name))

def GetPlayerName(self):
self.user1 = input("What is your name?")
Player(self.user1)

Player
self.GetPlayerName()
+1 Chris Nelson · January 4, 2015
Jay.. another opition I guess would be to just put the function outside a class, and then pass in the player information? this code seems to work for that.. 


__author__ = 'chrisutpg'
import random


class Player:
"""
This class asks the player for a name and sets
the maximum guesses. It also keeps track of the
players wins and losses
"""
def __init__(self, name):
self.name = name
self.player_max_guess = 20
self.player_wins = 0
self.players_losses = 0
print("{} welcome to our game!".format(self.name))

def guess_game(player):
random_number = random.randint(1, 20)
print(random_number)
guess = input("Guess a number between 1 and 20: ")
guess = int(guess)
if guess == random_number:
print("You win.")
player1.player_wins += 1
else:
print("You lost!")
player1.players_losses += 1


player1 = Player(input("What is your name? "))
guess_game(player1)
print(player1.players_losses)
print(player1.player_wins)

However, that brings me to the next thing. How would I create a way to figure out the number of players from human input and pass in whatever that number happened to be? Does that make sense..?

Look at this code..


class Player:
"""
This class asks the player for a name and sets
the maximum guesses. It also keeps track of the
players wins and losses
"""
def __init__(self, name):
self.name = name
self.player_max_guess = 20
self.player_wins = 0
self.players_losses = 0
print("{} welcome to our game!".format(self.name))

num_player = input("How many players are in playing? ")
num_player = int(num_player)
for x in range(1,num_player+1):
user1 = Player(input("What is your name? "))

print(user1.name)

this code works, however everytime it runs it just rewrites the name for user1. Is there anyway I can say..

ok, you have 5 players, create 5 variables, i.e user1, user2, user3, user4, user5. and assign those during the for loop?

I assume I probably can't do that because there would be no way to know how many users were input when calling back those variables?
0 Jay Tauron · January 4, 2015
I figured out how to do it with just classes, playing with the code myself helped. You were on the write track in your last comment in the end with the for loop, all you needed was an array to store them!

I worked on your original code and added comments to try and show what I did, a lot of making it work came from just testing the game over and over until i figured out what i wanted to happen and how to make it work

import random
__author__ = 'chrisutpg'


class Player:

    def __init__(self, name):
        self.name = name
        self.guesses = 0
        self.games_won = 0
        self.games_lost = 0
        self.max_guesses = 10
        print("Hi {}, welcome to the game!\n"
              "you have {} guesses remaining!\n"
              .format(self.name, self.max_guesses))

    def get_guesses(self):
        print("You have taken {} guesses!".format(self.guesses))

    def get_game_record(self):
        print("{} you have {} wins and {} losses!"
              .format(self.name, self.games_won, self.games_lost))


class GuessGame:

    def __init__(self):
        # Array to store all players
        players = []
        num_of_players = int(input("How many players do you have? "))

        # Create Player object for each user and append to array
        for i in range(num_of_players):
            tempName = input("Enter a name for user "+str(i+1)+": ")
            players.append(Player(tempName))

        # For each player, play the game
        while self.play():
            for i in range(len(players)):
                self.guess_num(players)

    def guess_num(self, player):
        # Practically as before but changed Player class to player variable
        random_number = random.randint(1, 20)
        found = False
        player.guesses = 0  # reset guesses at start of game
        while not found:
            userguess = int(input("{} Pick a number between 1 and 20.. "
                            .format(player.name)))
            player.guesses += 1
            if userguess == random_number:
                player.games_won += 1
                print("You won!")
                found = True
            elif player.guesses == player.max_guesses:
                player.games_lost += 1
                print("Sorry, you reached the maximum guesses! Game over.")
                found = True
            else:
                print("That is not it.. Keep trying!")
                print("You have taken {} guesses!".format(player.guesses))
            print()
        # added this to show player's record after game
        player.get_game_record()
        print()

    def play(self):
        if input("Would you like to play the Guessing Game? (y/n) ") == 'y':
            return True
        return False

game = GuessGame()
print("Thanks for playing!")
quit()

I added the GuessGame.play() function because your Player.get_game_record() function implied you wanted this game to be played over and over so i gave the option for the play to play again or leave whilst keeping the player's stats.
0 Chris Nelson · January 4, 2015
Hey Jay!

Thanks for that. Yes, I see I can use array to store those values. I was unaware of that. I had just started to use globals() which did work, but I read that IS NOT the way to do it.

Anyway, I ran that code with PyCharm and still go errors, once it actually tried to play the game. I was getting AttributeErrors, 'list' has no attribute 'name' , or 'guess' etc. 

I assume this is again, because you can not access the player class from within the game class? I think the easiest thing to do would just be create it all in one class. 

Then, I could still set initial stats for each player. But I could always call each player in the array during the game correct?
0 Jay Tauron · January 4, 2015
# For each player, play the game
while self.play():
for i in range(len(players)):
self.guess_num(players)



should be


# For each player, play the game
while self.play():
for i in range(len(players)):
self.guess_num(players\[i\])


without the slashes '\', for some reason if i have 'i' within square brackets, it disappears in the post
0 Chris Nelson · January 5, 2015
That is really nuts how that one missing thing can make sure a big difference.. Alright, if you don't mind me just asking a few questions on how this is actually working.. I have a better understanding already, just a few little things..


def __init__(self):
# Array to store all players
players = []
num_of_players = int(input("How many players do you have? "))

# Create Player object for each user and append to array
for i in range(num_of_players):
tempName = input("Enter a name for user "+str(i+1)+": ")
players.append(Player(tempName))

Ok, so the input into tempName is storied in the array, and it runs the __init__ in the Player class, with the name being whatever is input into tempName correct?
The only question I have here, is how does the rest of the game know what to print when we call say.. i.e

while not found:
userguess = int(input("{} Pick a number between 1 and 20.. "
.format(player.name)))

How does player.name print Chris is that is the first input, but that was passed to our Player class, and now we are calling player.name (lower case P, I thought they were case sensitive)

So, that is my only confusion left. How does the program know what we mean when we say player.name, since normally it would be..

player = chris
Player(player)
print("player.name")

and it would print 'chris'.

Any clarification would be awesome. But again, thanks a lot for the help thus far!
0 Jay Tauron · January 5, 2015
tempName will just store the string the user gave in the input e.g.  "Bob"
I then append to the array Player(tempName), which creates a new Player object with the name "Bob" so the array is actually storing Player instances (objects created from the Player class), which are all unique

For knowing which player to refer to, you can see the guess_num method takes a player parameter which is passed in when self.guess_num(players \[i\]) is called. So, for example, when it references player.name, its referencing the player object i passed to the method which was stored in the array, not the Player class itself
0 Chris Nelson · January 5, 2015
Hey Jay!

Yes I think I got it all figured out. I wrote a few simple classes and games today based off the code you put together and all worked as such. I would of never thought of passing an object from the Player class as a parameter into the Game class!

Thank a lot for your help!
0 Jay Tauron · January 6, 2015
Glad i could help
  • 1

Python

107,014 followers
About

This section is all about snakes! Just kidding.

Links
Moderators
Bucky Roberts Administrator