Classes in modules

H

hexusnexus

I'm trying to get this source code split into multiple files:

http://pygermanwhist.googlecode.com/files/pygermanwhist.12.py

I've been trying to make so that I have one class per file for easier
readability. My problem is that the interpreter keeps saying that it
can't find methods and so forth whenever I try to split the code up.

This has been a recurring problem for me in languages such as C++ and
Java. I'm used to programming in C.
 
H

hexusnexus

Yeah, I was a little embarrassed putting my code up to be examined.
Thanks for the reply. I typed up some classes, but I seemed to have
run into some more problems. One of the classes keeps getting an
error that it can't pop from an empty list. Here's the code so far:



################begin main.py#######look for more comments
#!/usr/bin/python

import random

#structure for holding card data
class Cards(object):
RANK =
["ace","2","3","4","5","6","7","8","9","10","jack","queen","king"]
SUIT = ["spades","clubs","hearts","diamonds"]
def __init__(self,rank,suit):
self.rank = rank
self.suit = suit
self.name = "%s of %s" % (Cards.RANK[self.rank],
Cards.SUIT[self.suit])

#deck functions
class Deck(object):
def __init__(self):
self.deck = []
for i in range(52):
self.deck.append(Cards(i % 13, i / 13))
def shuffle(self):
random.seed()
random.shuffle(self.deck)
def draw(self): #This is where my (first) problem
arises, though there may be more
return self.deck.pop() #IndexError: pop from empty list
def size(self):
return len(self.deck)
#Note: if anyone can find more errors in my code thus far, feel free
to criticize
#it's been a while since I've practised any OOP

#hand functions
class Hand(object):
def __init__(self):
self.cards = []
def pull(self, pos=0):
return self.cards.pop(pos)
def size(self):
return len(self.cards)
def put(self,crd):
self.cards.append(crd)
def cards(self):
return self.cards
def orgcards(self): #organizes cards, 2's to aces, trumps last
begin,end=0,0
for i in range(len(self.cards)-1):
for j in range(len(self.cards)-1):
if self.cards[j] > self.cards[j+1]:
temp = self.cards[j+1]
self.cards[j+1] = self.cards[j]
self.cards[j] = temp

for i in range(len(self.cards)):
for j in range(len(self.cards)-1):
if self.cards[j]%13==0 and self.cards[j]/
13==self.cards[j+1]/13:
temp=self.cards[j+1]
self.cards[j+1]=self.cards[j]
self.cards[j]=temp

for i in range(len(self.cards)-1,-1,-1):
if self.cards/13==Stock.trump():
end=i
break

if end>0:
end=0

for i in range(end,-1,-1):
if self.cards/13==Stock.trump():
begin=i
break

m=self.cards-1
for j in range(end,begin,-1):
l=0
k=j
while True:
l=k+1
if l > m:
break
temp = self.cards[l]
self.cards[l]=self.cards[k]
self.cards[k]=temp
k=l
m-=1

if self.cards<13:
for i in range(len(self.cards)-1):
for j in range(len(self.cards)-1):
if self.cards[j] == -1:
temp=self.cards[j+1]
self.cards[j+1]=self.cards[j]
self.cards[j]=temp
return self.cards


class Stock(Hand): #the stock class, slightly modified from Hand
def __init__(self):
self.cards = []
self.y = -1
self.cards.extend(Deck.deck)
def showtrump(self):
if self.y < 0:
self.y = self.cards[25]
return self.y



class Game(object): #the main game class
def __init__(self):
self.deck = Deck()
self.deck.shuffle()
self.player = Hand()
self.computer = Hand()
for i in range(self.deck.size()):
self.player.put(self.deck.draw())
self.computer.put(self.deck.draw())
self.stock = Stock()
print self.stock.showtrump()

mygame = Game()

#########################################################

If anyone can take a look at this and tell me where I went wrong, I'd
really appreciate it. I'm using Python v2.5.

I've been trying to make so that I have one class per file for easier

Unlike Java, which practically mandates the class<=>file format,
Python is perfectly happy with multiple related classes in one file --
and often /easier/ to read that way as one is not forced to jump around
finding dependent files to understand related classes.


This has been a recurring problem for me in languages such as C++ and
Java. I'm used to programming in C.

Please don't be offended, but looking at the specified file... it
shows...

Ignoring the language in use, I'd suggest a few studies in software
design, functional decomposition, data structures, and algorithms... to
start...

I lost count of how many times this
if rank==0:
rankstr = "ace"
elif rank==10:
rankstr = "jack"
elif rank==11:
rankstr = "queen"
elif rank==12:
rankstr = "king"
else:
rankstr=str(rank+1)

appears in the file, but a concept normally emphasized early in a
programming career is that when you have many identical (or near enough
that a minor tweak can serve for all) occurrences of the same code, it
should probably be turned into a function.

However, this is even better served by usage of data structures...

_RANKS = [ "ace", "two", "three", "four", "five",
"six", "seven", "eight", "nine",
"ten", "jack", "queen", "king" ]

as a module-wide "constant", and then replace all those if/elif...
blocks with a simple:

rankstr = _RANKS[rank]

Worse though, your code seems to have used the class keyword just
for the "see, I used classes" factor, with no logical concept of object
orientation. Instead you are creating singleton instances that are being
referenced as global data across the classes...

A simplistic approach for object orientation is to start with a text
description of the problem (in this case, a description of how the game
is played, perhaps). Find the key nouns in that description -- nouns
often (not always) turn into the classes. Find the verbs in the
description -- these are possible methods of the most closely related
noun. Find adjectives -- these may become attributes of the classes.

Generic Card Game:
The GAME uses one DECK of 52 playing CARDs (standard arrangement:
_ranks_ of Ace, 2, ..., 10, Jack, Queen, King, in the _suits_ of Clubs,
Diamonds, Hearts, Spades). _n_ PLAYERs take turns... The DECK is
/shuffled/, then CARDs are /dealt/ to each PLAYER, each, in turn,
/drawing/ one card from the DECK until they have a HAND of m-CARDs.

As a start (if you want multiple files)...

-=-=-=-=-=- carddeck.py
import random

class Card(object):
_RANKS = [ "ace", "two", "three", "four", "five",
"six", "seven", "eight", "nine",
"ten", "jack", "queen", "king" ]
_SUITS = [ "spades", "clubs", "hearts", "diamonds" ]

def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
self.name = "%s of %s" % (Card._RANKS[self.rank],
Card._SUITS[self.suit])

class Deck(object):
def __init__(self):
# cryptic initialization of 52 cards <G>
# relies on Python 2.4 or earlier behavior
# read the documentation for 2.5 or later to determine changes
self._deck = [Card(i % 13, i / 13) for i in range(52)]
self._discards = []
def shuffle(self):
self._deck.extend(self._discards) #combine
self._discards = []
random.shuffle(self._deck)
def draw(self):
return self._deck.pop() #returns one card from deck
def discard(self, crd):
self._discards.append(crd) #puts card into discard pile

-=-=-=-=-=- player.py
import carddeck #at this point, this may or may not be needed

class Hand(object):
def __init__(self):
self._cards = []
def pull(self, pos=0):
return self._cards.pop(pos)
def size(self):
return len(self._cards)
def put(self, crd):
self._cards.append(crd)
def cards(self):
return [ crd.name for crd in self._cards]

class Player(object):
def __init__(self):
self._hand = Hand()
def pull(self, pos=0):
#I'm pulling a "law of demeter" here; player does not
#directly manipulate cards in the hand
return self._hand.pull(pos)
def size(self):
return self._hand.size()
def put(self, crd):
self._hand.put(crd)
def showHand(self):
for crd in self._hand.cards():
print crd

-=-=-=-=- game.py
import carddeck
import player

class Game(object):
def __init__(self, numPlayers=2):
self._players = [player.Player() for i in range(numPlayers)
self._deck = carddeck.Deck()
self._deck.shuffle()
for i in range(7): #assume each player starts with 7 cards
for p in self._players:
p.put(self._deck.draw())

# rest left as an exercise for the student...

--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
G

Gabriel Genellina

Yeah, I was a little embarrassed putting my code up to be examined.
Thanks for the reply. I typed up some classes, but I seemed to have
run into some more problems. One of the classes keeps getting an
error that it can't pop from an empty list. Here's the code so far:

#deck functions
class Deck(object):
def __init__(self):
self.deck = []
for i in range(52):
self.deck.append(Cards(i % 13, i / 13))
def draw(self): #This is where my (first) problem
arises, though there may be more
return self.deck.pop() #IndexError: pop from empty list
def size(self):
return len(self.deck)

Next time post the whole traceback including the exception message. It
really contains valuable information. Without it, one has to guess...
"pop from empty list" means that you are trying to draw a card after the
deck is empty. The traceback would show the caller, but in this case it's
easy because there is a single place:
class Game(object): #the main game class
def __init__(self):
self.deck = Deck()
self.deck.shuffle()
self.player = Hand()
self.computer = Hand()
for i in range(self.deck.size()):
self.player.put(self.deck.draw())
self.computer.put(self.deck.draw())
self.stock = Stock()
print self.stock.showtrump()

The loop takes 52 iterations but you draw two cards in each iteration -
the 27th sees an empty deck.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,059
Latest member
cryptoseoagencies

Latest Threads

Top