Cheat card game python project

Hi. Before I start I'll just let you know that this isn't for school, I'm just doing python as a hobby which I have pretty much taught my self.

I'm working on a project, it is the "cheat!" card game written in python, currently CLI but when it is bug-free and clean I'll try making a GUI. I made this a while ago, by myself, and it never actually completely worked. Now I've written it a second time, much more efficient, cleaner and legible. But it still is in the debugging stage. Right now, the IDE I use (PyScripter, I recommend it) crashes when it gets to a certain point in it, and command prompt just stops and does nothing when it gets to that point, being when a player wins. I will attach the file as a .txt file and paste it here. Just save it and then rename it with a .py extension and then open it up in your IDE if you want to look at it.

I have no specific questions, but take a look if you want, maybe some suggestions and comments or questions, constructive criticism, if you're feeling very generous test and debug it to find what's wrong (not that I expect you to).

Thats all for now.

Here's the code:

# "cheat.py" Module
# Created on 14-June-2009
# compiled with python 3.0.1 -> www.python.org
# edited with PyScripter -> http://pyscripter.googlepages.com
# by Mitchell Kember
# Copyright (c) 2009. All rights reserved.
"""
Created on 14-June-2009
This python script is Cheat version 2, the "Cheat" card game. It
is played using the command line. Future versions will use a GUI.
@author: Mitchell Kember
"""
from random import randint
from random import shuffle
from re import split
class player:
"""A player in the cheat game."""
def __init__(self, name):
"""Creates a player.
params: name - The name of the player."""
self.name = name
self.hand = []
def __eq__(self, obj):
"""How to comare two player objects for equality."""
if not isinstance(obj, player):
return False
return self.name == obj.name and self.hand == obj.hand
def __ne__(self, obj):
"""How to comare two player objects for inequality."""
return not self.__eq__(obj)
def __str__(self):
"""The string representation of a player object."""
return self.name
class human(player):
"""A human player in the cheat game."""
def __init__(self, name):
"""Creates a human (human) player.
params: name - See player class"""
super(human, self).__init__(name)
def __eq__(self, obj):
"""How to compare two human objects for equality."""
return super(human, self).__eq__(obj)
def __ne__(self, obj):
"""How to compare two human objects for inequality."""
return not self.__eq__(obj)
class computer(player):
"""A computer player in the cheat game."""
def __init__(self, name, difficulty=randint(1, 3)):
"""Creates a player and then initializes computer-specific fields.
params: name: See player class.
[difficulty = randint(1, 3)] - The difficulty of the computer player."""
super(computer, self).__init__(name)
self.difficulty = difficulty
def __eq__(self, obj):
"""How to compare two computer objects for equality."""
return super(computer, self).__eq__
(obj) and self.difficulty == obj.difficulty
def __ne__(self, obj):
"""How to compare two computer objects for inequality."""
return not self.__eq__(obj)
class diff:
"""Enum class for a computer player's difficulty."""
unknown = 0
EASY = 1
MEDIUM = 2
HARD = 3
def get_name(difficulty):
"""Returns the name of the difficulty level."""
return ['easy', 'medium', 'hard'][difficulty]
class deck:
"""Deck of 52 cards for the cheat game."""
def __init__(self, shuffled=True):
"""Creates a new deck of 52 regular playing cards.
params: [shuffled = true] - Whether deck will be shuffled or not."""
self.cards = []
for s in range(1, 5):
for v in range(1, 14):
self.cards.append(card(v, s))
if shuffled:
self.shuffle_deck()
def shuffle_deck(self):
"""Shuffles the deck."""
shuffle(self.cards)
def sort_hand(hand):
"""Sorts a player's hand of cards by value (ace through king).
params: hand - The list of card objects to sort."""
vals = []
for c in hand:
vals.append((c, c.val))
vals.sort(key=lambda a:a[1])
return [c[0] for c in vals]
class card:
"""A card in that makes up a deck."""
def __init__(self, value, suit):
"""Creates a card.
params: value - The card's value. (see the value class)
suit - The card's suit. (see the suit class)"""
self.val = value
self.su = suit
def __str__(self):
"""Returns the name of the card. (Format: \"The [value] of [suit]\")"""
return "the " + value.get_name(self.val) + " of " + \
suit.get_name(self.su)
def __eq__(self, obj):
"""How to compare two card objects for equality."""
if not isinstance(obj, card):
return False
return self.val == obj.val and self.su == obj.su
def __ne__(self, obj):
"""How to compare two card objects for inequality."""
return not self.__eq__(obj)
def __gt__(self, obj):
"""How to compare two objects for the greatest."""
if not isinstance(obj, card):
raise TypeError
return self.val > obj.val
def __ge__(self, obj):
"""How to compare two objects for the greatest or equality."""
if not isinstance(obj, card):
raise TypeError
return self > obj or self.val == obj.val
class value:
"""Enum class for a card's value."""
unknown = 0
ACE = 1
TWO = 2
THREE = 3
FOUR = 4
FIVE = 5
SIX = 6
SEVEN = 7
EIGHT = 8
NINE = 9
TEN = 10
JACK = 11
QUEEN = 12
KING = 13
def get_name(value):
"""Returns the name of a value.
params: value - The value to get the name of."""
return ['unknown', 'ace', 'two', 'three', 'four', 'five', 'six',
'seven', 'eight', 'nine', 'ten', 'jack', 'queen', 'king'][value]
class suit:
"""Enum class for a card's suit."""
unknown = 0
SPADES = 1
CLUBS = 2
HEARTS = 3
DIAMONDS = 4
def get_name(suit):
"""Returns the name of a suit.
params: suit - The suit to get the name of."""
return ['unknown', 'spades', 'clubs', 'hearts', 'diamonds'][suit]
def get_colour(suit):
"""Returns the colour of a suit.
params: suit - The suit to get the colour of."""
if suit == 1 or suit == 2:
return 'black'
elif suit == 3 or suit == 4:
return 'red'
else:
return 'unknown'
class game:
"""Cheat cardgame."""
# game.gameplay: The rules of cheat and how it is played.
gameplay = """ Cheat gameplay:
\tThe object of the game is to get rid of all your cards. The winner is the first
person to get rid of all their cards.
\tTo start the game, the entire deck of 52 cards is dealt evenly to everyone. Now,
the player with the ace of spades will start. On this first turn, he or she is
allowed to put down all of his or her aces. He or she will take the cards, place
them face-down on the pile of cards and say the number of cards they are putting
down and that turn's card (ex \"2 twos\", \"1 jack\"). The next player will put
down twos, the next three, etc. until king, then it goes back to aces.
\tOn each player's turn, they will have to cheat if they do not have
any of the correct card. This means they will put down cards other than the correct
ones. You are NOT allowed to put down your cards and say that you are putting down
a different number of cards (ex say \"1 king\" but actually put down two). So
you can put down an ace and an eight when you are supposed to put down kings
and say \"2 kings\". You can also cheat even if you don't have to, if you are
supposed to put down fours and you have 2 fours, you could put the fours down
and also put a queen and say \"3 fours\", or even put down a jack and say
\"1 four\", and not even put down the fours that you have at all!
\tAfter any player's turn, any other player can challenge them by accusing
\"Cheat!\". If the player cheated, they must take up the entire pile. If the
player hasn't cheated, the challenger must add the entire pile to their hand.
\tThis will continue until a player wins, and then the other players may
keep playing to get a 2nd place winner, and 3rd place winner, etc."""
# Ranks for the winners
ranks = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth',
'seventh', 'eighth']
def __init__(self, *players):
"""Creates a new game.
params: *players - the players in this game."""
self.players = list(players) # (So that it is mutable)
# Make sure there are no more than eight players:
if len(self.players) > 8:
print("There cannot be more than 8 players.")
return
# Make sure all players are instances of the class player
for p in self.players:
if not isinstance(p, player):
print('Error: players are not player objects.')
return
# self.c_player: The player whose turn it is.
# self.c_value: This turn's card value (ace through king).
self.winners = []
self.deck = deck()
self.pile = []
self.player_iter = iter(self.players)
self.c_player = None
self.value_iter = iter(range(1, 14))
self.c_value = 0
self.deal_cards()
# Move the player with the ace of spades to the front of the list
for ind, p in enumerate(self.players):
for c in p.hand:
if c == card(value.ACE, suit.SPADES):
self.players[0], self.players[ind] = \
self.players[ind], self.players[0]
self.next_turn()
def reset_player_iter(self):
"""Resets the player iterator by re-assigning it."""
self.player_iter = iter(self.players)
def reset_value_iter(self):
"""Resets the value iterator by re-assigning it."""
self.value_iter = iter(range(1, 14))
def deal_cards(self):
"""Deals the deck to each player."""
i = 0
for c in self.deck.cards:
if i == len(self.players):
i = 0
self.players[i].hand.append(c)
i += 1
# Delete self.deck, and use self.pile instead so to not have to use
# self.deck.cards.
del self.deck
def update_current(self):
"""Updates the current player and current value instance variables."""
while True:
# Go to the next player in the self.players list
try:
self.c_player = next(self.player_iter)
# If at the end of the list, go back to the start by calling
# self.reset_player_iter().
except StopIteration:
self.reset_player_iter()
self.c_player = next(self.player_iter)
if self.c_player not in self.winners:
break
# Go to the next card value in the list of numbers 1 through 14
# (enum values of the value class).
try:
self.c_value = next(self.value_iter)
# If at the end of the list, go back to the start by calling
# self.reset_value_iter().
except StopIteration:
self.reset_value_iter()
self.c_value = next(self.value_iter)
def next_turn(self):
"""Goes to the next turn in the game."""
# Check to see if there is only one player left (game is over).
# If there is, then print the ranks and end.
if len([p for p in self.players if p not in self.winners]) == 1:
print("The game is over.\n\nThe ranks:\n")
for place, p in enumerate(self.winners):
print("{0}: {1}".format(game.ranks[place], p))
print("{0}. {1}".format(game.ranks[len(self.winners)], self.c_player))
return
# Update self.c_player and self.c_value instance variables.
self.update_current()
print(" {0} ".format(len(self.c_player.hand))*10)
print("It's {0}'s turn. {0}, put down your {1}s.".format(
self.c_player, value.get_name(self.c_value)), end=' '*6)
input("Press enter to continue...")
# Go on to either human_turn() or computer_turn()
if isinstance(self.c_player, computer):
self.computer_turn()
elif isinstance(self.c_player, human):
self.human_turn()
else:
print("Error: Players are not human or computer objects.")
def human_turn(self):
"""Executed when it is a human player's turn."""
# Sort the player's cards by values, so that they go from ace to king.
self.c_player.hand = deck.sort_hand(self.c_player.hand)
print("{0}, here are your cards.".format(self.c_player) + \
"Type the number keys of the cards you want to play" , end=' '*6)
input("Press enter to continue...")
# Print the player's cards, and
# if the card's value is the self_c_value, then print it in CAPS.
for ind, c in enumerate(self.c_player.hand):
print("{0} : ".format(ind), end='')
if c.val == self.c_value:
print(str(c).upper())
else:
print(c)
# Loop until atleast one valid card is chosen by the human
while True:
# del_indexes: list to contain indexes of elements in card_indexes to
# delete. They can't be deleted in the for loop because it would
# mess it up if they are deleted while it is iterating them.
del_indexes = []
# card_indexes: The indexes of the cards put down.
# The indexes can be entered seperated by spaces or commas.
card_indexes = split('\W+', input("Enter the number keys: "))
for ind, c in enumerate(card_indexes):
# Make sure that each index is a number (digit).
if not c.isdigit():
del_indexes.append(ind)
continue
# Make sure the index is valid, that it is one of the indexes
# in the player's hand of cards.
if int(c) >= len(self.c_player.hand) or int(c) < 0:
del_indexes.append(ind)
# Delete the indexes that were appended to del_indexes
for ind in del_indexes:
del card_indexes[ind]
# Make sure at least one card is chosen.
if not card_indexes:
print("You have to chose at least one card.")
else:
break
del del_indexes
self.finish_turn(card_indexes)
def computer_turn(self):
"""Executed when it is a computer player's turn."""
card_indexes = []
skip = False
# If the player only has one card then just chose that one.
if len(self.c_player.hand) == 1:
card_indexes = [0]
skip = True
# If the computer player's difficulty is not diff.EASY, or if it is
# and a random number from 1 to 3 is 1 (33% chance), then find all
# the cards that the computer player has and can put down without
# cheating.
if (self.c_player.difficulty != diff.EASY or randint(1, 3) == 1) \
and not skip:
for ind, c in enumerate(self.c_player.hand):
if c.val == self.c_value:
card_indexes.append(ind)
# What the EASY computer player does:
if self.c_player.difficulty == diff.EASY and not skip:
# If the computer player already put down some cards from the
# 33% chance above, half the time leave it and don't add any more.
# Add either 1, 2, 3 or 4 more random cards
if not card_indexes or randint(1, 2) == 1:
for i in range(randint(1, 4)):
while True:
rand_num = randint(0, len(self.c_player.hand)-1)
if rand_num not in card_indexes:
card_indexes.append(rand_num)
break
# What the MEDIUM computer player does:
elif self.c_player.difficulty == diff.MEDIUM and not skip:
# It will add up to 3 cards if to the card_indexes if it is empy,
# or 1/5 of the time when card_indexes is not empty
if not card_indexes or randint(1, 5) == 1:
for i in range(randint(1, 3)):
while True:
rand_num = randint(0, len(self.c_player.hand)-1)
if rand_num not in card_indexes:
card_indexes.append(rand_num)
break
# What the HARD computer player does:
elif self.c_player.difficulty == diff.HARD and not skip:
pass
self.finish_turn(card_indexes)
def finish_turn(self, card_indexes):
"""Finishes the turn, human or computer.
params: card_indexes - The indexes of the cards that are chosen."""
print("{0} put down {1} {2}(s).".format(
self.c_player, len(card_indexes), value.get_name(self.c_value)))
# cards: The actual card objects that were put down.
cards = [self.c_player.hand[int(i)] for i in card_indexes]
# challenges: Get the challenges from other players.
challenges = self.get_challenges(len(card_indexes))
cheat = False
# If there are any challenges:
if challenges:
# Maybe later make this only include one challenge
for ch in challenges:
if ch == challenges[-1]:
print("Cheat! called by {0}.".format(ch.name),
end=' '*6)
else:
print("Cheat! called by {0}.".format(ch.name))
input("Press enter to continue...")
for c in cards:
# If the player cheated...
if c.val != self.c_value:
cheat = True
break
# If the player has cheated:
if cheat:
print("{0} Cheated! {0} gets to pick up the pile!".format(
self.c_player), end=' '*6)
self.c_player.hand += self.pile
self.pile = []
# If the player has not cheated:
else:
print("{0} is innocent! {1} gets to pick up the pile!".format(
self.c_player, challenges[0]), end=' '*6)
for c in cards:
self.c_player.hand.remove(c)
self.pile.append(c)
challenges[0].hand += self.pile
self.pile = []
# If the player has not been challenged:
else:
print("No one has accused {0} of cheating".format(self.c_player), end=' '*6)
for c in cards:
self.c_player.hand.remove(c)
self.pile.append(c)
input("Press enter to continue...")
# If the player has won (has no cards left):
if not self.c_player.hand:
print("{0} won in {1} place!".format(self.c_player, game.ranks[len(self.winners)]))
print("The game will continue.")
input("Press enter to continue...")
self.winners.append(self.c_player)
self.next_turn()
def get_challenges(self, cards_len):
"""Gets the challenges from other players.
params: cards_len - The amount of cards the player put down."""
if randint(1, 2) == 1:
return self.human_challenge(cards_len) + self.computer_challenge(cards_len)
else:
return self.computer_challenge(cards_len) + self.human_challenge(cards_len)
def human_challenge(self, cards_len):
"""Asks the human players if they would like to challenge.
params: cards_len - The amount of cards the player put down."""
# Get the human instances from the self.players list
human_players = [p for p in self.players if isinstance(p, human) and p not in self.winners]
# If the player whose turn it is is a human, remove him/her from the
# list (if the player isn't a human, he/she wouldn't be in the list
# anyway).
if isinstance(self.c_player, human):
human_players.remove(self.c_player)
if not human_players:
return []
shuffle(human_players)
human_challenges = []
# Go through each player in human_players and ask if they want
# to challenge, and give them information like how many cards the
# the player put down, and how many this human already has.
for h in human_players:
num_cards = 0
for c in h.hand:
if c.val == self.c_value:
num_cards += 1
print("{0}: Do you think {1} is cheating?".format(
h, self.c_player), end=' '*6)
input("Press enter for more info...")
print("{0} claims to have put down {1} {2}(s).".format(
self.c_player, cards_len, value.get_name(self.c_value)), end=' '*6)
input("Press enter for more info...")
print("You have {0} {1}(s).".format(num_cards, value.get_name(self.c_value)))
challenge = input('Enter Cheat, or press enter to pass... ')
if 'cheat' in challenge.lower():
human_challenges.append(h)
return human_challenges
def computer_challenge(self, cards_len):
"""Gets the challengese from the computer players.
params: cards_len - The amount of cards the player put down."""
# Get the computer instances from the self.players list
computer_players = [p for p in self.players if isinstance(p, computer) and p not in self.winners]
# If the player whose turn it is is a computer player, remove him/her
# from the list (if the player isn't a computer player, he/she
# wouldn't be in the list anyway).
if isinstance(self.c_player, computer):
computer_players.remove(self.c_player)
if not computer_players:
return []
shuffle(computer_players)
computer_challenges = []
for c in computer_players:
# unless the computer player's difficulty is diff.EASY, challenge
# if the number of cards the player put down plus the number of
# this computer player has is more then four.
if c.difficulty != diff.EASY:
num_cards = 0
for ca in c.hand:
if ca.val == self.c_value:
num_cards += 1
if num_cards + cards_len > 4:
computer_challenges.append(c)
continue
# Easy computer player challenges 1/5 of the time.
if c.difficulty == diff.EASY:
if randint(1, 5) == 1:
computer_challenges.append(c)
elif c.difficulty == diff.MEDIUM:
pass
elif c.difficulty == diff.HARD:
pass
return computer_challenges
if __name__ == "__main__":
game(computer('Bob', diff.EASY), computer('Bill', diff.EASY), computer('Tristan', diff.EASY))

The attachment preview is chopped off after the first 10 KB. Please download the entire file.

# "cheat.py" Module
# Created on 14-June-2009
# compiled with python 3.0.1 -> www.python.org
# edited with PyScripter -> http://pyscripter.googlepages.com
# by Mitchell Kember
# Copyright (c) 2009. All rights reserved.
"""
Created on 14-June-2009
This python script is Cheat version 2, the "Cheat" card game. It
is played using the command line. Future versions will use a GUI.
@author: Mitchell Kember
"""
from random import randint
from random import shuffle
from re import split
class player:
"""A player in the cheat game."""
def __init__(self, name):
"""Creates a player.
params: name - The name of the player."""
self.name = name
self.hand = []
def __eq__(self, obj):
"""How to comare two player objects for equality."""
if not isinstance(obj, player):
return False
return self.name == obj.name and self.hand == obj.hand
def __ne__(self, obj):
"""How to comare two player objects for inequality."""
return not self.__eq__(obj)
def __str__(self):
"""The string representation of a player object."""
return self.name
class human(player):
"""A human player in the cheat game."""
def __init__(self, name):
"""Creates a human (human) player.
params: name - See player class"""
super(human, self).__init__(name)
def __eq__(self, obj):
"""How to compare two human objects for equality."""
return super(human, self).__eq__(obj)
def __ne__(self, obj):
"""How to compare two human objects for inequality."""
return not self.__eq__(obj)
class computer(player):
"""A computer player in the cheat game."""
def __init__(self, name, difficulty=randint(1, 3)):
"""Creates a player and then initializes computer-specific fields.
params: name: See player class.
[difficulty = randint(1, 3)] - The difficulty of the computer player."""
super(computer, self).__init__(name)
self.difficulty = difficulty
def __eq__(self, obj):
"""How to compare two computer objects for equality."""
return super(computer, self).__eq__
(obj) and self.difficulty == obj.difficulty
def __ne__(self, obj):
"""How to compare two computer objects for inequality."""
return not self.__eq__(obj)
class diff:
"""Enum class for a computer player's difficulty."""
unknown = 0
EASY = 1
MEDIUM = 2
HARD = 3
def get_name(difficulty):
"""Returns the name of the difficulty level."""
return ['easy', 'medium', 'hard'][difficulty]
class deck:
"""Deck of 52 cards for the cheat game."""
def __init__(self, shuffled=True):
"""Creates a new deck of 52 regular playing cards.
params: [shuffled = true] - Whether deck will be shuffled or not."""
self.cards = []
for s in range(1, 5):
for v in range(1, 14):
self.cards.append(card(v, s))
if shuffled:
self.shuffle_deck()
def shuffle_deck(self):
"""Shuffles the deck."""
shuffle(self.cards)
def sort_hand(hand):
"""Sorts a player's hand of cards by value (ace through king).
params: hand - The list of card objects to sort."""
vals = []
for c in hand:
vals.append((c, c.val))
vals.sort(key=lambda a:a[1])
return [c[0] for c in vals]
class card:
"""A card in that makes up a deck."""
def __init__(self, value, suit):
"""Creates a card.
params: value - The card's value. (see the value class)
suit - The card's suit. (see the suit class)"""
self.val = value
self.su = suit
def __str__(self):
"""Returns the name of the card. (Format: \"The [value] of [suit]\")"""
return "the " + value.get_name(self.val) + " of " + \
suit.get_name(self.su)
def __eq__(self, obj):
"""How to compare two card objects for equality."""
if not isinstance(obj, card):
return False
return self.val == obj.val and self.su == obj.su
def __ne__(self, obj):
"""How to compare two card objects for inequality."""
return not self.__eq__(obj)
def __gt__(self, obj):
"""How to compare two objects for the greatest."""
if not isinstance(obj, card):
raise TypeError
return self.val > obj.val
def __ge__(self, obj):
"""How to compare two objects for the greatest or equality."""
if not isinstance(obj, card):
raise TypeError
return self > obj or self.val == obj.val
class value:
"""Enum class for a card's value."""
unknown = 0
ACE = 1
TWO = 2
THREE = 3
FOUR = 4
FIVE = 5
SIX = 6
SEVEN = 7
EIGHT = 8
NINE = 9
TEN = 10
JACK = 11
QUEEN = 12
KING = 13
def get_name(value):
"""Returns the name of a value.
params: value - The value to get the name of."""
return ['unknown', 'ace', 'two', 'three', 'four', 'five', 'six',
'seven', 'eight', 'nine', 'ten', 'jack', 'queen', 'king'][value]
class suit:
"""Enum class for a card's suit."""
unknown = 0
SPADES = 1
CLUBS = 2
HEARTS = 3
DIAMONDS = 4
def get_name(suit):
"""Returns the name of a suit.
params: suit - The suit to get the name of."""
return ['unknown', 'spades', 'clubs', 'hearts', 'diamonds'][suit]
def get_colour(suit):
"""Returns the colour of a suit.
params: suit - The suit to get the colour of."""
if suit == 1 or suit == 2:
return 'black'
elif suit == 3 or suit == 4:
return 'red'
else:
return 'unknown'
class game:
"""Cheat cardgame."""
# game.gameplay: The rules of cheat and how it is played.
gameplay = """ Cheat gameplay:
\tThe object of the game is to get rid of all your cards. The winner is the first
person to get rid of all their cards.
\tTo start the game, the entire deck of 52 cards is dealt evenly to everyone. Now,
the player with the ace of spades will start. On this first turn, he or she is
allowed to put down all of his or her aces. He or she will take the cards, place
them face-down on the pile of cards and say the number of cards they are putting
down and that turn's card (ex \"2 twos\", \"1 jack\"). The next player will put
down twos, the next three, etc. until king, then it goes back to aces.
\tOn each player's turn, they will have to cheat if they do not have
any of the correct card. This means they will put down cards other than the correct
ones. You are NOT allowed to put down your cards and say that you are putting down
a different number of cards (ex say \"1 king\" but actually put down two). So
you can put down an ace and an eight when you are supposed to put down kings
and say \"2 kings\". You can also cheat even if you don't have to, if you are
supposed to put down fours and you have 2 fours, you could put the fours down
and also put a queen and say \"3 fours\", or even put down a jack and say
\"1 four\", and not even put down the fours that you have at all!
\tAfter any player's turn, any other player can challenge them by accusing
\"Cheat!\". If the player cheated, they must take up the entire pile. If the
player hasn't cheated, the challenger must add the entire pile to their hand.
\tThis will continue until a player wins, and then the other players may
keep playing to get a 2nd place winner, and 3rd place winner, etc."""
# Ranks for the winners
ranks = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth',
'seventh', 'eighth']
def __init__(self, *players):
"""Creates a new game.
params: *players - the players in this game."""
self.players = list(players) # (So that it is mutable)
# Make sure there are no more than eight players:
if len(self.players) > 8:
print("There cannot be more than 8 players.")
return
# Make sure all players are instances of the class player
for p in self.players:
if not isinstance(p, player):
print('Error: players are not player objects.')
return
# self.c_player: The player whose turn it is.
# self.c_value: This turn's card value (ace through king).
self.winners = []
self.deck = deck()
self.pile = []
self.player_iter = iter(self.players)
self.c_player = None
self.value_iter = iter(range(1, 14))
self.c_value = 0
self.deal_cards()
# Move the player with the ace of spades to the front of the list
for ind, p in enumerate(self.players):
for c in p.hand:
if c == card(value.ACE, suit.SPADES):
self.players[0], self.players[ind] = \
self.players[ind], self.players[0]
self.next_turn()
def reset_player_iter(self):
"""Resets the player iterator by re-assigning it."""
self.player_iter = iter(self.players)
def reset_value_iter(self):
"""Resets the value iterator by re-assigning it."""
self.value_iter = iter(range(1, 14))
def deal_cards(self):
"""Deals the deck to each player."""
i = 0
for c in self.deck.cards:
if i == len(self.players):
i = 0
self.players[i].hand.append(c)
i += 1
# Delete self.deck, and use self.pile instead so to not have to use
# self.deck.cards.
del self.deck
def update_current(self):
"""Updates the current player and current value instance variables."""
while True:
# Go to the next player in the self.players list
try:
self.c_play

I didn't actually expect you to debug it :p It is interactive.. Look at the human_turn and human_challenge methods of the game class. To play it just save it as a .py, and in the if __name__ == "__main__":, just create an instance of game with 1 - 8 'player' object arguments (either 'human' or 'computer', not directly player). For example:

The code actually isn't completely done, I haven't done MEDIUM or HARD difficulties yet, only EASY. The whole module doesn't need to be debugged, only the 'game' class does (EDIT- which is only, uhh, 355 lines hehe). Like I said, it crashes when a player wins. I'll let you know of anything I figure out.

I didn't actually expect you to debug it :p It is interactive.. Look at the human_turn and human_challenge methods of the game class. To play it just save it as a .py, and in the if __name__ == "__main__":, just create an instance of game with 1 - 8 'player' object arguments (either 'human' or 'computer', not directly player). For example:

The code actually isn't completely done, I haven't done MEDIUM or HARD difficulties yet, only EASY. The whole module doesn't need to be debugged, only the 'game' class does (EDIT- which is only, uhh, 355 lines hehe). Like I said, it crashes when a player wins. I'll let you know of anything I figure out.

Oh wow this is a neat framework you have here.

Anyhow the gameplay may need some work. It's a little too verbose for my liking, and I have to press enter a LOT. I mean, I don't know how I would do this any better (blame it on my long day; too tired to think).

There are some nice subtleties in your UI though. For instance when printing my hand, the suite I'm being asked to put down is highlighted, if you may, so it catches my eye right away.

Jack claims to have put down 1 three(s). Press enter for more info...
You have 1 three(s).
Enter Cheat, or press enter to pass...
Cheat! called by Jack. Press enter to continue...
Jack Cheated! Jack gets to pick up the pile! Press enter to continue...

Thanks. Yeah I can change the press enters later. The real goal of this is making a nice GUI with it so the command line won't matter much then. But I'm open to suggestions. Later I'll add something like this:

Something like that, you get what I mean, just lets you get the game set up without editing the file.

I am pretty happy with how I've set up all the other classes like player, human, computer, card, deck, etc...

I've made some progress in the debugging! I fixed an infinite loop involving random numbers that have always already been chosen, and figured out the source of the only other problem that I think there is but yet to figure out how to fix it. I'll keep you posted :).

EDIT:

You have a bug. It's quite amusing actually.

Jack claims to have put down 1 three(s). Press enter for more info...
You have 1 three(s).
Enter Cheat, or press enter to pass...
Cheat! called by Jack. Press enter to continue...
Jack Cheated! Jack gets to pick up the pile! Press enter to continue...

Wow I thought that I made sure that couldn't happen... Ok thanks I'll check that out. Thanks.

WOOOT! The bugs have been exterminated! Not sure how I did it, I don't even think that I changed anything but anyway the first time ever that the whole game went through fine. I will polish it all up a bit (the comments, interface) then post the code. Then I will improve with people's suggestions, and then tackle the GUI. Thanks for the encouraging replies :).

I'll keep everyone up to date on the project.

EDIT: not relevant at all, but I've been wondering: When should i subclass object? Java does this for every class, but I've seen some python classes that subclass object. What is the purpose of it? Should my player, deck and card classes do it? Thanks.

not relevant at all, but I've been wondering: When should i subclass object? Java does this for every class, but I've seen some python classes that subclass object. What is the purpose of it? Should my player, deck and card classes do it? Thanks

Ok, I've cleaned up the code, thinned out the press enter to continue's, debugged it, added code to let you set up the game, improved the interface.
Now My goals are:
- Improve the computer players. Make them more intelligent.
- Allow more players by allowing multiple decks of cards
- the GUI
Its official name for now is Pythonic CHEAT! (version 2.2). I'll attach the file with txt extension (note - why can't you attach .py files?). Save it, rename with .py extension. Try it out, check out the code, suggestions, comments, constructive criticism are welcome.

The attachment preview is chopped off after the first 10 KB. Please download the entire file.

#!/usr/bin/env python
# Module "cheat.py"
# Pythonic CHEAT! version 2.0
# Created on 14-June-2009
# compiled with python 3.0.1 -> www.python.org
# edited with PyScripter -> http://pyscripter.googlepages.com
# by Mitchell Kember
# Copyright (c) 2009. All rights reserved.
"""
Created on 14-June-2009
Pythonic CHEAT! version 2.2
This is the card game, \"cheat!\", coded in python and uses
the command line for user interactions. I plan to make a
Graphical User Interface for the game, and to make computer
players more intelligent, such as realizing a player never cheats,
etc, and to allow multiple decks.
Easy and Medium difficulties are almost finished, but
Hard difficulty cannot be used yet.
@author: Mitchell Kember
"""
# Imports
from random import randint
from random import shuffle
from re import split
from time import sleep
__version__ = 2.2
class player:
"""A player in the cheat game."""
def __init__(self, name):
"""Creates a player with a name and a hand of cards (initially empty).
params: name - The name of the player."""
self.name = name
self.hand = []
def __str__(self):
"""The string representation of a player object, its name property."""
return self.name
class human(player):
"""A human in the cheat game, derived from class player"""
def __init__(self, name):
"""Creates a (human) player.
params: name - See player class"""
super(human, self).__init__(name)
class computer(player):
"""A computer player in the cheat game, derived from class player."""
def __init__(self, name, difficulty=randint(1, 3)):
"""Creates a (computer) player and initializes its difficulty.
params: name: See player class.
[difficulty = randint(1, 3)] - The difficulty of the computer player."""
super(computer, self).__init__(name)
self.difficulty = difficulty
class diff:
"""Enum class for a computer player's difficulty."""
unknown = 0
EASY = 1
MEDIUM = 2
HARD = 3
def get_name(difficulty):
"""Returns the name of the difficulty level."""
return ['easy', 'medium', 'hard'][difficulty]
class deck:
"""Deck of 52 card objects for the cheat game."""
def __init__(self, shuffled=True):
"""Creates a new deck of 52 regular playing cards.
params: [shuffled = true] - Whether deck will be shuffled or not."""
self.cards = []
for s in range(1, 5):
for v in range(1, 14):
self.cards.append(card(v, s))
if shuffled:
self.shuffle_deck()
def shuffle_deck(self):
"""Shuffles the deck."""
shuffle(self.cards)
def sort_hand(hand):
"""Sorts a player's hand of cards by value (ace through king).
params: hand - The list of card objects to sort."""
vals = []
for c in hand:
vals.append((c, c.val))
vals.sort(key=lambda a:a[1])
return [c[0] for c in vals]
class card:
"""A playing card that makes up a deck."""
def __init__(self, value, suit):
"""Creates a card with a value (ace through king) and
a suit (spades, clubs, hearts or diamonds).
params: value - The card's value. (see the value class)
suit - The card's suit. (see the suit class)"""
self.val = value
self.su = suit
def __str__(self):
"""Returns the name of the card. (Format: \"The [value] of [suit]\")"""
return "the " + value.get_name(self.val) + " of " + \
suit.get_name(self.su)
def __eq__(self, obj):
"""How to compare two card objects for equality."""
if not isinstance(obj, card):
return False
return self.val == obj.val and self.su == obj.su
def __ne__(self, obj):
"""How to compare two card objects for inequality."""
return not self.__eq__(obj)
def __gt__(self, obj):
"""How to compare two card objects for greatness."""
if not isinstance(obj, card):
raise TypeError
return self.val > obj.val
def __ge__(self, obj):
"""How to compare two card objects for greatness or equality."""
if not isinstance(obj, card):
raise TypeError
return self > obj or self.val == obj.val
class value:
"""Enum class for a card's value."""
unknown = 0
ACE = 1
TWO = 2
THREE = 3
FOUR = 4
FIVE = 5
SIX = 6
SEVEN = 7
EIGHT = 8
NINE = 9
TEN = 10
JACK = 11
QUEEN = 12
KING = 13
def get_name(value):
"""Returns the name of a value.
params: value - The value to get the name of."""
return ['unknown', 'ace', 'two', 'three', 'four', 'five', 'six',
'seven', 'eight', 'nine', 'ten', 'jack', 'queen', 'king'][value]
class suit:
"""Enum class for a card's suit."""
unknown = 0
SPADES = 1
CLUBS = 2
HEARTS = 3
DIAMONDS = 4
def get_name(suit):
"""Returns the name of a suit.
params: suit - The suit to get the name of."""
return ['unknown', 'spades', 'clubs', 'hearts', 'diamonds'][suit]
def get_colour(suit):
"""Returns the colour of a suit.
params: suit - The suit to get the colour of."""
if suit == 1 or suit == 2:
return 'black'
elif suit == 3 or suit == 4:
return 'red'
else:
return 'unknown'
class game:
"""Cheat cardgame. Instantiating game will start the game."""
# gameplay: The rules of cheat and how it is played.
gameplay = """ Cheat gameplay:
\tThe object of the game is to get rid of all your cards. The winner is the first
person to get rid of all their cards.
\tTo start the game, the entire deck of 52 cards is dealt evenly to everyone. Now,
the player with the ace of spades will start. On this first turn, he or she is
allowed to put down all of his or her aces. He or she will take the cards, place
them face-down on the pile of cards and say the number of cards they are putting
down and that turn's card (ex \"2 twos\", \"1 jack\"). The next player will put
down twos, the next three, etc. until king, then it goes back to aces.
\tOn each player's turn, they will have to cheat if they do not have
any of the correct card. This means they will put down cards other than the correct
ones. You are NOT allowed to put down your cards and say that you are putting down
a different number of cards (ex say \"1 king\" but actually put down two). So
you can put down an ace and an eight when you are supposed to put down kings
and say \"2 kings\". You can also cheat even if you don't have to, if you are
supposed to put down fours and you have 2 fours, you could put the fours down
and also put a queen and say \"3 fours\", or even put down a jack and say
\"1 four\", and not even put down the fours that you have at all!
\tAfter any player's turn, any other player can challenge them by accusing
\"Cheat!\". If the player cheated, they must take up the entire pile. If the
player hasn't cheated, the challenger must add the entire pile to their hand.
\tThis will continue until a player wins, and then the other players may
keep playing to get a 2nd place winner, and 3rd place winner, etc."""
# Ranks for the winners
ranks = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth',
'seventh', 'eighth']
def __init__(self, *players):
"""Creates a new game and begins it immediately.
params: *players - the players in this game."""
self.players = list(players) # (So that it is mutable)
# Make sure there are no more than eight players:
if len(self.players) > 8:
print("There cannot be more than 8 players.")
return
# Make sure all players are instances of the class player
for p in self.players:
if not isinstance(p, player):
print('Error: players are not player objects.')
raise TypeError
return
# self.c_player: The player whose turn it is.
# self.c_value: This turn's card value (ace through king).
self.winners = []
self.deck = deck()
self.pile = []
self.player_iter = iter(self.players)
self.c_player = None
self.value_iter = iter(range(1, 14))
self.c_value = 0
self.deal_cards()
# Move the player with the ace of spades to the front of self.players.
for ind, p in enumerate(self.players):
for c in p.hand:
if c == card(value.ACE, suit.SPADES):
self.players[0], self.players[ind] = \
self.players[ind], self.players[0]
# Begin the chain of turns.
self.next_turn()
def reset_player_iter(self):
"""Resets the player iterator by re-assigning it."""
self.player_iter = iter(self.players)
def reset_value_iter(self):
"""Resets the value iterator by re-assigning it."""
self.value_iter = iter(range(1, 14))
def deal_cards(self):
"""Deals the deck to each player."""
i = 0
for c in self.deck.cards:
if i == len(self.players):
i = 0
self.players[i].hand.append(c)
i += 1
# Delete self.deck, and use self.pile instead so to not have to use
# self.deck.cards.
del self.deck
def update_current(self):
"""Updates the current player and current value properties."""
while True:
# Go to the next player in the self.players list
try:
self.c_player = next(self.player_iter)
# If at the end of the list, go back to the start.
except StopIteration:
self.reset_player_iter()
self.c_player = next(self.player_iter

You should always subclass object, except when subclassing another class that subclasses object (which technically, is still subclassing object). Why? Because the difference between declaring an old style class and a new style class is that new style classes subclass object.

I'm going through all the code, changing the names after reading PEP 8, and making sure they are all new style (subclass object, unless already subclassing another class that I made which subclasses object). I read somewhere that even though it does nothing its important to do for example in class Player(object): in the __init__ method, to do super(Player, self).__init__() . I already did that with my human and computer classes, ex super(Human, self).__init__(name) . Is that right? I'm also using an Enumeration class to do the value, suit and difficulty enums. Do you have to have cls (or any name) as first argument in a class method? Because I've been not doing that and it works fine, but I read your suposed to (in PEP 8). Thanks.

scru, I'm pretty sure that now in python 3.0.1 all classes are new-style and you don't need to subclass object... Am I right?

EDIT: just saw your post. So now that classic style classes are removed, I don't need to bother subclassing object, right?

EDIT: I must be right because I tested class c: pass and then issubclass(c, object) and it returned True, so its already subclassing object without writing class c[B](object)[/B]: pass I'm still working on this and I'll post a new update of it soon. I'm almost done what could will be called version 2.3. Right now I'm going over all the docstrings.
This project has come a long way, and I've learnt a lot :). I think I won't start the GUI (which will be Tkinter unless wxpython releases a version for python 3.0.1 by then) until after I've perfected the command line version.

You can try pyQT which has a python 3 version, if tkinter's archaic UI doesn't suit you. Only, you'd have to gpl your code. If you don't mind that, then I suppose you wouldn't mind my offer of assistance? I've grown really fond of this program.

Ok Pythonic CHEAT! version 2.5 is finished! Pay particular close attention to the docstrings, I worked all day on the documentation, frequently checking PEP 257. I also made the computers a bit smarter.

The code is *much* nicer now. Okay, so where can I download this PyQt, and how do I gpl my code?

You can try pyQT which has a python 3 version, if tkinter's archaic UI doesn't suit you. Only, you'd have to gpl your code. If you don't mind that, then I suppose you wouldn't mind my offer of assistance? I've grown really fond of this program.

Thanks, what do you mean by assistance, like what would you do? Of course I'll accept any help :p.

Yeah, it is. The GPL is a strong copyleft: if you use code that is gpl, your code must be gpl too (pyQT is GPL). Two implications of using your pyQT:

1. You have to open source your code under gpl
2. People using your code have to gpl theirs as well.

the GPL is strong copyleft: What does copyleft mean? Nevermind, http://en.wikipedia.org/wiki/Copyleft told me.
I'll still get credit if anyone decides to distribute it since I made it, even if they change it a bit right?

And will the user have to install some PyQt thing along with Python to run the program?

Thanks for keeping up with me in this project :).

And here is Pythonic CHEAT! version 2.5! (If you can come up with a more original name let me now :o)

The attachment preview is chopped off after the first 10 KB. Please download the entire file.

#!/usr/bin/env python
# Python Module "cheat.py"
# Pythonic CHEAT! version 2.5
# Created on 14-June-2009
# compiled with python 3.0.1 -> www.python.org
# edited with PyScripter -> http://pyscripter.googlepages.com
# by Mitchell Kember
# Copyright (c) 2009. All rights reserved.
"""
Created on 14-June-2009
Pythonic CHEAT! version 2.5
This is the card game, \"Cheat!\", coded in python 3.0.1 and uses
the command line for user interaction. I plan to make a
Graphical User Interface for the game, and to make computer
players more intelligent, such as realizing a player never cheats,
etc, and to allow multiple decks. Easy and medium difficulties are almost
finished, but hard difficulty cannot be used yet.
Classes:
Enumeration
Player
Human(Player)
Computer(Player)
Deck
Card
Game
Enumeration Globals:
Difficulty
Value
Suit
@author: Mitchell Kember
"""
# Imports
from random import randint
from random import shuffle
from re import split
from time import sleep
# Enum-creating class
class Enumeration:
"""A simple Enumeration.
Example:
>>> Seasons = Enumeration("Spring", "Summer", "Autumn", "Winter")
>>> print(Season.Spring > Season.Winter)
False
>>> print(Season.Autumn)
3
Instantiating Enumeration assigns a numerical value
starting at one and incrementing by one to each
string argument.
Keyword Arguments:
*names -- a variable amount of str objects, which are the
reference names of the instance attributes created
"""
def __init__(self, *names):
super().__init__()
for number, name in enumerate(list(names)):
setattr(self, name, number + 1)
# Globals
version = 2.5
Difficulty = Enumeration('Easy', 'Medium', 'Hard')
Value = Enumeration('Ace', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven',
'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King')
Suit = Enumeration('Spades', 'Clubs', 'Hearts', 'Diamonds')
# Functions
def difficulty_name(difficulty):
"""Returns the name of the difficulty level."""
return ['unknown', 'easy', 'medium', 'hard'][difficulty]
def value_name(value):
"""Returns the name of the value."""
return ['unknown', 'ace', 'two', 'three', 'four', 'five', 'six',
'seven', 'eight', 'nine', 'ten', 'jack', 'queen', 'king'][value]
def suit_name(suit):
"""Returns the name of the suit."""
return ['unknown', 'spades', 'clubs', 'hearts', 'diamonds'][suit]
def suit_colour(suit):
"""Returns the colour of the suit."""
return ['unknown', 'black', 'black', 'red', 'red'][suit]
# Classes
class Player:
"""A player in the cheat game.
A player in the cheat game with a name and
a hand of cards. A player can be converted to
a string with str(instance_of_player).
Attributes:
self.name -- str
self.hand -- list
Keyword Arguments:
name -- the player's name
"""
def __init__(self, name):
super().__init__()
self.name = name
self.hand = []
def __str__(self):
"""The string representation of a Player object, the name attribute."""
return self.name
class Human(Player):
"""A human player, derived from Player.
A human player for the cheat game, derived from the
class PLayer. Currently, it is exactly the same as
its superclass, and is used only for the name Human.
The human player has a name and a hand of cards.
Inherited Attributes:
self.name -- str
self.hand -- list
Keyword Arguments:
name -- the human player's name
"""
def __init__(self, name):
super().__init__(name)
class Computer(Player):
"""A computer player, derived from Player.
A computer player for the cheat game, derived from the
class PLayer. It is a Player (which has a name and a hand
of cards) with a level of difficulty.
Inherited Attributes:
self.name -- str
self.hand -- list
New Attributes:
self.difficulty - Enumeration value (1, 2 or 3)
Keyword Arguments:
name -- the computer player's name
[difficulty] -- the computer player's level of difficulty,
Difficulty.Easy, Difficulty.Medium or Difficulty.Hard
Default: a random choice out of the three
"""
def __init__(self, name, difficulty=randint(1, 3)):
super().__init__(name)
self.difficulty = difficulty
class Deck:
"""Deck of 52 cards.
A deck of 52 regular playing cards for the cheat
game, each card being an instance of the Card class
(see the Card class documentation for more details).
Attributes:
self.cards -- list
Methods:
self.shuffle_deck -- returns None
cls.sort_hand -- returns list
Keyword Arguments:
[shuffled] -- shuffles the deck after creating if True
default: True
"""
def __init__(self, shuffled=True):
super().__init__()
self.cards = []
# Loop through the four suits and the 13 values
# And create each card (52)
for s in range(1, 5):
for v in range(1, 14):
self.cards.append(Card(v, s))
if shuffled:
self.shuffle_deck()
def shuffle_deck(self):
"""Shuffles the deck."""
shuffle(self.cards)
def sort_hand(cls, hand):
"""Sorts a Player's hand of cards by value (ace through king)."""
vals = []
for c in hand:
vals.append((c, c.val))
# Sort by the second element in each tuple (the value)
vals.sort(key=lambda a:a[1])
return [c[0] for c in vals]
class Card:
"""A regular playing card.
A regular playing Card, each with a value
(ace through king) and a suit (spades, clubs,
hearts or diamonds). 52 Card objects make up
a Deck object. Card objects can be compared
with ==, !=, <=, >=, > or < and can be converted
to a string with str(instance_of_Card).
Attributes:
value -- Enumeration value (numbers 1 - 13)
suit -- Enumeration value (numbers 1 - 4)
Keyword Arguments:
value -- the card's value, a number from 1 to 13 (inclusive)
use Value.Ace, Value.Two, etc. where Value is an
instance of Enumeration with the 13 values as values.
suit -- the card's suit, a number from 1 to 4 (inclusive)
use Suit.Spades, Suit.Hearts, etc. where Suit is an
instance of Enumeration with the four suits as values
"""
def __init__(self, value, suit):
super().__init__()
self.value = value
self.suit = suit
def __str__(self):
"""Returns the name of the Card. (Format: \"The [value] of [suit]\")"""
return "the " + value_name(self.value) + " of " + \
suit_name(self.suit)
def __eq__(self, obj):
"""How to compare two Card objects for equality."""
if not isinstance(obj, Card):
return False
return self.value == obj.value and self.suit == obj.suit
def __ne__(self, obj):
"""How to compare two Card objects for inequality."""
return not self.__eq__(obj)
def __gt__(self, obj):
"""How to compare two Card objects for greatness."""
if not isinstance(obj, Card):
raise TypeError
return self.value > obj.value
def __ge__(self, obj):
"""How to compare two Card objects for greatness or equality."""
if not isinstance(obj, Card):
raise TypeError
return self > obj or self.value == obj.value
class Game:
"""Cheat card game.
A Pythonic CHEAT! game. Instatiating Game will start
the game immediately. There can be a maximum of 8 players
in the game. The Game class controls the user interface.
Attributes:
cls.gameplay -- str
self.players -- list
self.winners -- list
self.deck -- Deck
self.pile -- list
self.player_iter -- iter()
self.c_player -- Player
self.value_iter -- iter()
self.c_value -- Enumeration value (numbers 1 through 13)
Methods:
self.reset_player_iter -- returns None
self.reset_value_iter -- returns None
self.deal_cards -- returns None
self.update_current -- returns None
self.next_turn -- returns None
self.human_turn -- returns None
self.computer_turn -- returns None
self.finish_turn -- returns None
self.get_challenges -- returns list
self.human_challenge -- returns list
self.computer_challenge -- returns list
Keyword Arguments:
*players -- a variable amount of Player objects (max: 8)
"""
# gameplay: The rules of cheat and how it is played.
gameplay = """ Cheat gameplay:
\tThe object of the game is to get rid of all your cards. The winner is the
first person to get rid of all their cards.
\tTo start the game, the entire deck of 52 cards is dealt evenly to everyone.
Now, the Player with the ace of spades will start. On this first turn, he or
she is allowed to put down all of his or her aces. He or she will take the
cards, place them face-down on the pile of cards and say the number of cards
they are putting down and that turn's card (ex \"2 twos\", \"1 jack\"). The
next Player will put down twos, the next three, etc. until king, then it goes
back to aces.
\tOn each Player's turn, they will have to cheat if they do not have
any of the correct card. This means they will put down cards other than the
correct ones. You are NOT allowed to put down your cards and say that you are
putting down a Difficultyerent number of cards (ex say \"1 king\" but actually
put down two). So you can put down an ace and an eight when you are supposed to
put down kings and say \"2 kings\". You can also cheat even if you don't have
to, if you are supposed to put down fours and you have 2 fours, you could put
the fours down and also put a queen and say \"3 fours\", or even put down a jack
and say \"1 four\", and not even put do

The attachment preview is chopped off after the first 10 KB. Please download the entire file.

#!/usr/bin/env python
# Python Module "cheat.py"
# Pythonic CHEAT! version 2.6
# Created on 14-June-2009
# compiled with python 3.0.1 -> www.python.org
# edited with PyScripter -> http://pyscripter.googlepages.com
# by Mitchell Kember
# Copyright (c) 2009. All rights reserved.
"""
Created on 14-June-2009
Pythonic CHEAT! version 2.6
This is the card game, \"Cheat!\", coded in python 3.0.1 and uses
the command line for user interaction. I plan to make a
Graphical User Interface for the game, and to make computer
players more intelligent, such as realizing a player never cheats,
etc, and to allow multiple decks. Easy and medium difficulties are almost
finished, but hard difficulty cannot be used yet.
Classes:
Enumeration
Player
Human(Player)
Computer(Player)
Deck
Card
Game
Enumeration Globals:
Difficulty
Value
Suit
@author: Mitchell Kember
"""
# Imports
from random import randint
from random import shuffle
from re import split
from time import sleep
# Enum-creating class
class Enumeration:
"""A simple Enumeration.
Example:
>>> Seasons = Enumeration("Spring", "Summer", "Autumn", "Winter")
>>> print(Season.Spring > Season.Winter)
False
>>> print(Season.Autumn)
3
Instantiating Enumeration assigns a numerical value
starting at one and incrementing by one to each
string argument.
Keyword Arguments:
*names -- a variable amount of str objects, which are the
reference names of the instance attributes created
"""
def __init__(self, *names):
super().__init__()
for number, name in enumerate(list(names)):
setattr(self, name, number + 1)
# Globals
version = 2.6
Difficulty = Enumeration('Easy', 'Medium', 'Hard')
Value = Enumeration('Ace', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven',
'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King')
Suit = Enumeration('Spades', 'Clubs', 'Hearts', 'Diamonds')
# Functions
def difficulty_name(difficulty):
"""Returns the name of the difficulty level."""
return ['unknown', 'easy', 'medium', 'hard'][difficulty]
def value_name(value):
"""Returns the name of the value."""
return ['unknown', 'ace', 'two', 'three', 'four', 'five', 'six',
'seven', 'eight', 'nine', 'ten', 'jack', 'queen', 'king'][value]
def suit_name(suit):
"""Returns the name of the suit."""
return ['unknown', 'spades', 'clubs', 'hearts', 'diamonds'][suit]
def suit_colour(suit):
"""Returns the colour of the suit."""
return ['unknown', 'black', 'black', 'red', 'red'][suit]
# Classes
class Player:
"""A player in the cheat game.
A player in the cheat game with a name and
a hand of cards. A player can be converted to
a string with str(instance_of_player).
Attributes:
self.name -- str
self.hand -- list
Keyword Arguments:
name -- the player's name
"""
def __init__(self, name):
super().__init__()
self.name = name
self.hand = []
def __str__(self):
"""The string representation of a Player object, the name attribute."""
return self.name
class Human(Player):
"""A human player, derived from Player.
A human player for the cheat game, derived from the
class PLayer. Currently, it is exactly the same as
its superclass, and is used only for the name Human.
The human player has a name and a hand of cards.
Inherited Attributes:
self.name -- str
self.hand -- list
Keyword Arguments:
name -- the human player's name
"""
def __init__(self, name):
super().__init__(name)
class Computer(Player):
"""A computer player, derived from Player.
A computer player for the cheat game, derived from the
class PLayer. It is a Player (which has a name and a hand
of cards) with a level of difficulty.
Inherited Attributes:
self.name -- str
self.hand -- list
New Attributes:
self.difficulty - Enumeration value (1, 2 or 3)
Keyword Arguments:
name -- the computer player's name
[difficulty] -- the computer player's level of difficulty,
Difficulty.Easy, Difficulty.Medium or Difficulty.Hard
Default: a random choice out of the three
"""
def __init__(self, name, difficulty=randint(1, 3)):
super().__init__(name)
self.difficulty = difficulty
class Deck:
"""Deck of 52 cards.
A deck of 52 regular playing cards for the cheat
game, each card being an instance of the Card class
(see the Card class documentation for more details).
Attributes:
self.cards -- list
Methods:
self.shuffle_deck -- returns None
cls.sort_hand -- returns list
Keyword Arguments:
[shuffled] -- shuffles the deck after creating if True
default: True
"""
def __init__(self, shuffled=True):
super().__init__()
self.cards = []
# Loop through the four suits and the 13 values
# And create each card (52)
for s in range(1, 5):
for v in range(1, 14):
self.cards.append(Card(v, s))
if shuffled:
self.shuffle_deck()
def shuffle_deck(self):
"""Shuffles the deck."""
shuffle(self.cards)
def sort_hand(cls, hand):
"""Sorts a Player's hand of cards by value (ace through king)."""
vals = []
for c in hand:
vals.append((c, c.value))
# Sort by the second element in each tuple (the value)
vals.sort(key=lambda a:a[1])
return [c[0] for c in vals]
sort_hand = classmethod(sort_hand)
class Card:
"""A regular playing card.
A regular playing Card, each with a value
(ace through king) and a suit (spades, clubs,
hearts or diamonds). 52 Card objects make up
a Deck object. Card objects can be compared
with ==, !=, <=, >=, > or < and can be converted
to a string with str(instance_of_Card).
Attributes:
value -- Enumeration value (numbers 1 - 13)
suit -- Enumeration value (numbers 1 - 4)
Keyword Arguments:
value -- the card's value, a number from 1 to 13 (inclusive)
use Value.Ace, Value.Two, etc. where Value is an
instance of Enumeration with the 13 values as values.
suit -- the card's suit, a number from 1 to 4 (inclusive)
use Suit.Spades, Suit.Hearts, etc. where Suit is an
instance of Enumeration with the four suits as values
"""
def __init__(self, value, suit):
super().__init__()
self.value = value
self.suit = suit
def __str__(self):
"""Returns the name of the Card. (Format: \"The [value] of [suit]\")"""
return "the " + value_name(self.value) + " of " + \
suit_name(self.suit)
def __eq__(self, obj):
"""How to compare two Card objects for equality."""
if not isinstance(obj, Card):
return False
return self.value == obj.value and self.suit == obj.suit
def __ne__(self, obj):
"""How to compare two Card objects for inequality."""
return not self.__eq__(obj)
def __gt__(self, obj):
"""How to compare two Card objects for greatness."""
if not isinstance(obj, Card):
raise TypeError
return self.value > obj.value
def __ge__(self, obj):
"""How to compare two Card objects for greatness or equality."""
if not isinstance(obj, Card):
raise TypeError
return self > obj or self.value == obj.value
class Game:
"""Cheat card game.
A Pythonic CHEAT! game. Instatiating Game will start
the game immediately. There can be a maximum of 8 players
in the game. The Game class controls the user interface.
Attributes:
cls.gameplay -- str
self.players -- list
self.winners -- list
self.deck -- Deck
self.pile -- list
self.player_iter -- iter()
self.c_player -- Player
self.value_iter -- iter()
self.c_value -- Enumeration value (numbers 1 through 13)
Methods:
self.reset_player_iter -- returns None
self.reset_value_iter -- returns None
self.deal_cards -- returns None
self.update_current -- returns None
self.next_turn -- returns None
self.human_turn -- returns None
self.computer_turn -- returns None
self.finish_turn -- returns None
self.get_challenges -- returns list
self.human_challenge -- returns list
self.computer_challenge -- returns list
Keyword Arguments:
*players -- a variable amount of Player objects (max: 8)
"""
# gameplay: The rules of cheat and how it is played.
gameplay = """ Cheat gameplay:
\tThe object of the game is to get rid of all your cards. The winner is the
first person to get rid of all their cards.
\tTo start the game, the entire deck of 52 cards is dealt evenly to everyone.
Now, the Player with the ace of spades will start. On this first turn, he or
she is allowed to put down all of his or her aces. He or she will take the
cards, place them face-down on the pile of cards and say the number of cards
they are putting down and that turn's card (ex \"2 twos\", \"1 jack\"). The
next Player will put down twos, the next three, etc. until king, then it goes
back to aces.
\tOn each Player's turn, they will have to cheat if they do not have
any of the correct card. This means they will put down cards other than the
correct ones. You are NOT allowed to put down your cards and say that you are
putting down a Difficultyerent number of cards (ex say \"1 king\" but actually
put down two). So you can put down an ace and an eight when you are supposed to
put down kings and say \"2 kings\". You can also cheat even if you don't have
to, if you are supposed to put down fours and you have 2 fours, you could put
the fours down and also put a queen and say \"3 fours\", or even put down a jac

This is not true. You can GPL your code if you want but it is not a requirement. Your code automatically comes under the GPL only when it modifies a program that is already GPL'd. You would have to provide a link to the GPL part of the code, i.e. the QT website (generally in the comments at the beginning of the program), but your code is your code. One of the mobile phone manufactures, I think it is Nokia but I'm not sure, uses QT but has had a closed operating system for years. If it is Nokia, they have recently open-sourced, but it was closed for years even though the QT tool kit was used.

This is not true. You can GPL your code if you want but it is not a requirement. Your code automatically comes under the GPL only when it modifies a program that is already GPL'd. You would have to provide a link to the GPL part of the code, i.e. the QT website (generally in the comments at the beginning of the program), but your code is your code. One of the mobile phone manufactures, I think it is Nokia but I'm not sure, uses QT but has had a closed operating system for years. If it is Nokia, they have recently open-sourced, but it was closed for years even though the QT tool kit was used.

I don't think you understand the GPL very well. Yes, he does have to GPL his code, just for using code that is gpled (whether he modifies it or not). That's why it's called a copyleft. Also note that pyQT's license is not the same as QT's, and the LGPL license for QT does not apply.

Ok Pythonic CHEAT! version 2.5 is finished! Pay particular close attention to the docstrings, I worked all day on the documentation, frequently checking PEP 257. I also made the computers a bit smarter.

The code is *much* nicer now. Okay, so where can I download this PyQt, and how do I gpl my code?

Thanks, what do you mean by assistance, like what would you do? Of course I'll accept any help :p.

the GPL is strong copyleft: What does copyleft mean? Nevermind, http://en.wikipedia.org/wiki/Copyleft told me.
I'll still get credit if anyone decides to distribute it since I made it, even if they change it a bit right?

And will the user have to install some PyQt thing along with Python to run the program?

Thanks for keeping up with me in this project :).

And here is Pythonic CHEAT! version 2.5! (If you can come up with a more original name let me now :o)

I'm not sure about how the credit works.

Yes the user would have to install pyQT.

I would help you with the GUI part of your program. If you decide to use pyQT, then I'll help you with that. If you decide not to, you still have options that I can also help with (I can go straight Win32 for you with ctypes), but my code would be BSD in such a case (allows you to license your code however you like, but my code must remain BSD).

Take a look at the GPL FAQ, especially the sections on modifing existing GPL programs vs. linking to GPL binaries. We are talking about an aggregate, specifically different programs with different licenses in the same package.

An “aggregate” consists of a number of separate programs, distributed together on the same CD-ROM or other media. The GPL permits you to create and distribute an aggregate, even when the licenses of the other software are non-free or GPL-incompatible. The only condition is that you cannot release the aggregate under a license that prohibits users from exercising rights that each program's individual license would grant them.

So they have certain rights for the GPL portion, which you can not prohit them from using, and different rights for any non-GPL code that you also can not prohibit in any way. The bottom line is that you own any program that you create (without copying from others). In most countries today, no one can force you to do anything do don't want to do with it

I think you may have mis-interpreted what is meant by "aggregate." Notice that quote mentions nothing about whether any software in the "aggregate" directly uses to a GPLed program (I'm telling you, you have to GPL in this case).

I went to the pyQT website in their licensing section. While woooee is wrong that GPLed code does not infect other software for simply using it, PyQT seems to allow software using it to be licensed under a restricted set of licenses as a special exception:

If you use the GPL version of PyQt then any code you develop with it must be distributed under a compatable license. Like the GPL version of Qt, PyQt grants an exception to the GPL that specifies the list of licenses that you may use. The full text of the exception can be found ... and a copy is included in the PyQt source package.

Make sure you read and understand the GPL (daunting, I know; I'm not really a big GPL fan myself).

EDIT:

I almost never use global names (I hate the term variable for Python) unless they are constants. I prefer that my functions never modify any names not belonging to its local namespace (I instead prefer to pass any "global" names to and from my functions). Global functions are okay, and I only ever use static methods when the routine directly relates to the class.

Because When I omit the staticdef = staticmethod(staticdef) , it still works exactly the same (but not if I try to do a class method that way).
And about the global name vs class attribute, I'm wondering if I should make it a global name again, not class attribute because its an instance of my Enumeration class, and it used to be a class by itself, without using Enumeration, and it looks just like a class when you're using it, so I don't think it should be in another class, but that the class should just use it, like I has before... I'm actually thinking I should get rid of the Enumeration class and just make them like I had before, that way the functions can go in there too.. I'll post the next version of this soon.

The first method of defining a class attribute is the correct one (nobody reply to this to bitch about "oh, there is no correct way to program" or I'll steal all your peanut butter). The second method only works because of Python's late binding; it's not the syntax.

When you omit staticdef = staticmethod(staticdef), it may still work, but you don't necessarily have a static method; I can for instance still call the method from an instance (and not the class). In this case it will raise an error because of your lack of arguments, but what about static methods which will have arguments? Use the correct syntax!

A shorthand way with decorators:

@staticmethod
def staticdef():
....

Try not to make assumptions about Python 3 and what it supports, what omissions it allows etc. beyond what is outlined in the documentation. In fact, one of the core principles of Python grammar is explicit is better than implicit. Always mark methods you intend to be used statically as static methods.

Finally, this is a judgment call. If doing so will result in code than is easier to read and maintain, it won't hurt*.

*I accept no liability for any unforeseen damages, physical or otherwise.

P.S. Python decorators are fun. Not only to use, but to create. If you want to have some good fun with Python, I suggest you take a look at descriptors and decorators (together), generators, list comprehensions, and the data model (customizing your types with __specialfunc__).

Here's version 2.8! I really improved a lot of the code, but I'm still isn't ready to make the gui yet. I almost have 1k lines of code now. More then half is documentation I'd say, I spent a lot of time on that. I'd appreciate if you took a look at it.

Oh, and I only need to gpl my code when I use PyQt if I distribute it, right? Like if it never leaves my computer, it won't matter anyway, right?

The attachment preview is chopped off after the first 10 KB. Please download the entire file.

#!/usr/bin/env python
# Python Module "cheat.py"
# Pythonic CHEAT! version 2.8
# Created on 14-June-2009
# compiled with python 3.0.1 -> www.python.org
# edited with PyScripter 1.9.9.7 -> http://pyscripter.googlepages.com
# by Mitchell Kember
# Copyright (c) 2009. All rights reserved.
"""
Created on 14-June-2009
Pythonic CHEAT! version 2.8
This module is a console based card game, called \"Pythonic CHEAT!\",
based on the real card game, \"Cheat!\". It is a sole executable script,
written in python 3.0.1.
State:
- all difficulties except hard can be used
- most things are finished except for
the computer players
Future Improvements:
- GUI
- more intelligent computer players
Classes:
Player
Human(Player)
Computer(Player)
Difficulty
Deck
Card
Value
Suit
Game
Functions:
game_setup
-- Documentation Help --
Words in the brackets are not part of documentation,
but are explaining it to you. \"classname\" is substitued
by the classes name, as are method_name and attribute_name.
\"return_type\" is substituted by the type returned, but
\"returns\", \"self\" and \"cls\" are literally that. Square
brackets indicate that the words inside are only present
if the class has a superclass which has methods/attributes
that the subclass inherits.
Class Docstring:
===============
Summary of documentation.
More elaborate documentation, spanning
several lines. .....................
...................................
.............................
[Inherited Attributes]: (only if the class subclasses another)
classname.attribute_name -- type (inherited class attribute)
self.attribute_name -- type (inherited instance attribute)
[New] Attributes: (\"New\" if there are also inherited attributes)
same as inherited attributes.
Inherited Methods: (only if the class subclasses another)
self.method_name -- returns return_type (inherited instance method)
class_name.method_name -- returns return_type (inherited staticmethod)
cls.method_name -- returns return_type (inherited classmethod)
[New] Methods: (\"New\" if there are also inherited methods)
same as inherited methods.
Keyword Arguments: (explains arguments for instantiating the class)
arg1 -- description - type
Function/Method Docstring:
=========================
Summary of documentation.
More elaborate documentation, spanning
several lines. .....................
...................................
.............................
Keyword Arguments: (explains the arguments for calling the method/function)
arg1 -- description - type
-----------------------------
@author: Mitchell Kember
"""
# Imports
from random import randint
from random import shuffle
from re import split
from time import sleep
# Global names
version = 2.8
# Functions
def game_setup():
"""Sets up a game with user input.
Sets up a game by asking the user how many players,
their names, difficulties, asks if they would like
to see the rules, etc.
"""
print("Pythonic CHEAT! version", version, " by Mitchell Kember")
# Get the amount of human players.
while True:
h = input("How many human players will there be?").strip()
try:
h = int(h)
except ValueError:
print("Please type a number this time.")
else:
break
# Get the amount of computer players.
while True:
c = input("How many computer players will there be?").strip()
try:
c = int(c)
except ValueError:
print("Please type a number this time.")
else:
break
# Get the names of the human players.
humans = []
for num in range(h):
while True:
name = input("Type the {0} human's name:".format(Game.ranks[num])) \
.strip()
if not (name.isspace() or not name):
break
humans.append(Human(name))
# Get the names and levels of difficulty of the computer players.
computers = []
for num in range(c):
while True:
name = input("Type the {0} computer player's name:".format(
Game.ranks[num])).strip()
if not (name.isspace() or not name):
break
while True:
d = input("Enter {0}'s difficulty (Easy = 1, Medium = 2, Hard = 3):"
.format(name)).strip()
try:
d = int(d)
except ValueError:
print("Please type a number this time.")
else:
break
computers.append(Computer(name, d))
players = humans + computers
# Ask if they want to see the rules.
if 'y' in input("Would you like to see the rules of Pythonic CHEAT! ? (Y/N):").lower():
print(Game.gameplay)
input("Press enter to start the game...")
# Begin the game
Game(*players)
# Classes
class Player:
"""A player in the game.
A player in the game with a name and
a hand of cards. A player can be converted to
a string with str(instance_of_player), which
returns their name attribute.
Attributes:
self.name -- str
self.hand -- list
Keyword Arguments:
name -- the player's name - str
"""
def __init__(self, name):
super().__init__()
self.name = name
self.hand = []
def __str__(self):
"""The string representation of a Player object, the name attribute."""
return self.name
class Human(Player):
"""A human player, derived from class Player.
A human player in the game, derived from the
class PLayer. Currently, it is exactly the same as
its superclass, and is used only for the name \"Human\".
A human player has a name and a hand of cards.
Inherited Attributes:
self.name -- str
self.hand -- list
Keyword Arguments:
name -- the human player's name - str
"""
def __init__(self, name):
super().__init__(name)
class Computer(Player):
"""A computer player, derived from class Player.
A computer player for the cheat game, derived from the
class PLayer. It is a Player (which has a name and a hand
of cards) with a level of difficulty.
Inherited Attributes:
self.name -- str
self.hand -- list
New Attributes:
self.difficulty - use class Difficulty (numbers 1 to 3)
Keyword Arguments:
name -- the computer player's name
[difficulty] -- the computer player's level of difficulty,
Difficulty.easy, Difficulty.medium or Difficulty.hard
Default: a random choice out of the three
"""
def __init__(self, name, difficulty=randint(1, 3)):
super().__init__(name)
if difficulty < 1 or difficulty > 3:
raise ValueError
self.difficulty = difficulty
class Difficulty:
"""An enum class for a computer player's difficulty.
An enum class to define a computer player's level
of difficulty, either 1 (Difficulty.easy), 2
(Difficulty.medium) or 3 (Difficulty.hard). Difficulty
is not to be instatiated.
Attributes:
Difficulty.unknown -- 0
Difficulty.easy -- 1
Difficulty.medium -- 2
Difficulty.hard -- 3
Methods:
Difficulty.name -- returns str
"""
unknown, easy, \
medium, hard = range(4)
@staticmethod
def name(difficulty):
"""Returns the name of the difficulty level."""
return ['unknown', 'easy', 'medium', 'hard'][difficulty]
class Deck:
"""A Deck of 52 cards.
A deck of 52 regular playing cards for the game, each
card being an instance of the Card class (see the Card
class documentation for more details).
Attributes:
self.cards -- list
Methods:
self.shuffle_deck -- returns None
Deck.sort_hand -- returns list
Keyword Arguments:
[shuffled] -- shuffles the deck after creating if True - bool
default: True
"""
def __init__(self, shuffled=True):
super().__init__()
self.cards = []
# Loop through the four suits and the 13 values
# And create each card (52)
for s in range(1, 5):
for v in range(1, 14):
self.cards.append(Card(v, s))
if shuffled:
self.shuffle_deck()
def shuffle_deck(self):
"""Shuffles the deck."""
shuffle(self.cards)
@staticmethod
def sort_hand(hand):
"""Sorts a Player's hand of cards by value (ace through king)."""
vals = []
for c in hand:
vals.append((c, c.value))
# Sort by the second element in each tuple (the value)
vals.sort(key=lambda a:a[1])
return [c[0] for c in vals]
class Card:
"""A regular playing card.
A regular playing Card, each with a value
(ace through king) and a suit (spades, clubs,
hearts or diamonds). 52 Card objects make up
a Deck object. Card objects can be compared
with ==, !=, <=, >=, > or < and can be converted
to a string with str(instance_of_Card).
Attributes:
self.value -- the card's value (ace, four, queen, etc.)
self.suit -- the card's suit (spades, diamonds, etc.)
Keyword Arguments:
value -- the card's value, a number from 1 to 13.
use Value.ace, Value.two, etc. Value is
a class with the 13 values
suit -- the card's suit, a number from 1 to 4.
use Suit.spades, Suit.hearts, etc. Suit is a
class with the 4 suits
"""
def __init__(self, value, suit):
super().__init__()
self.value = value
self.suit = suit
def __str__(self):
"""Returns the name of the Card. (Format: \"The [value] of [suit]\")"""
return "the " + Value.name(self.value) + " of " + \
Suit.name(self.suit)
def __eq

I have a 2d matrix with dimension (3, n) called A, I want to calculate the normalization and cross product of two arrays (b,z) (see the code please) for each column (for the first column, then the second one and so on).
the function that I created to find the ...

Write a C program that should create a 10 element array of random integers (0 to 9). The program should total all of the numbers in the odd positions of the array and compare them with the total of the numbers in the even positions of the array and indicate ...