assignment3. the card game : war due date: today!!! Pedagogical Goal : Refresher
ID: 3902427 • Letter: A
Question
assignment3. the card game : war
due date: today!!!
Pedagogical Goal: Refresher of Python and hands-on experience with algorithm coding, input validation, exceptions, file reading, Queues, and data structures with encapsulation.
Task 1 : Reading and Validating cards
You are given a text file of 52 shuffled cards, each card is in a line coded on two characters as described above. You need to prompt the user for the name of the file, open the file and read it. Make sure the file exists and make sure the cards in the file are correctly formatted as described above. If the cards are in lower case, it is not an error as you can simply transform them in upper case. You can assume the cards are shuffled but don't assume they are formatted as specified or that there are exactly 52, or even that they are not repeated. Make sure all the standard 52 cards are there in the shuffled deck. You are not asked to correct the cards, but your program must raise and catch an exception if card validation does not go through. The program should then display an appropriate error message and terminate the program in case there is an issue with the cards.
You are given a python program shuffleCards.py that generates the file shuffledDeck.txt as we described above with 52 lines constituting the shuffled deck. However, while this program generates a correct input to your program don't assume the input file is always correct. The assessment of your assignment may be made with a file that is incorrect.
Task 2: Distributing cards
Now that you have read the 52 cards from the file and you know you shuffled deck is complete and correct, distribute the cards to both players: the user and the computer. You may call them player1 and player2. You should give one card to each player repeatedly until all cards are distributed. You should start randomly with either player.
The players keep their cards in such a way that the first card served is the first that will be played. In other words, the containers of these cards should receive the cards on one end and use them from the other end. Use the circular queue we saw and implemented in class to represent the player's hand. The capacity should be set to 52 since you will never have more than 52 cards. The Circular Queue class should be inside assignment3 file that you submit.
Task 3: Asking user for data
Ask the user whether they would like to play a war with one, two, or three cards face-down. validate the input from the user and don't proceed until a valid input is given.
Example of a War with 3 cards down
Task 4: Comparing cards
You need a way to compare two cards. Write a function that given two correct cards returns 0 if the cards are of equal rank; 1 if the first card is of higher rank; and -1 if the second card is of higher rank. The ranks are explained above. Also, remember that the rank is the first character of the card and the cards are strings of two characters.
Task 5: class OnTable
We need to represent the cards on the table, the cards that are currently placed on the table by both players either face-up or face-down. Create an encapsulated class OnTable with the behaviour described below. We will use two simple lists: one list for the cards and one list to indicate whether they are face-up or face-down. The attributes of the class are: __cards which is a list that will contain the cards, and __faceUp with will have booleans to indicate if the __cards list in the same position in __cards is face-up or face-down. Cards put on the table by player 1 will be added on the left of self._cards. The cards put on the table by player 2 will be added on the right of self._cards. The interface of this class should include place(player, card, hidden), where player is either 1 or 2 for player 1 or player 2, card is the card being placed on the table, and hidden is False when the card is face-up and True when the card is face-down. This method should update the attributes of the class appropriately. The interface should also have the method cleanTable(). This method shuffles and then return a list of all cards on the table as stored in the attribute __cards and resets __cards and __faceUp. All cards returned this way are visible. Finally, also write the method __str__() that should allow the conversion of the cards on the table into a string to be displayed. We would like to display the cards as a list. However, cards that are face-down should be displayed as "XX". Moreover, player1 and player 2 cards should be separated by a vertical line.Please see sample output.
Task 6: The Game
Given the following algorithm and based on the previous tasks, implement the card game War. Obviously, there are details in the algorithm specific to the implementation in Python that are missing and it is up to you as an exercise to do the conversion from this pseudo-code to Python.
There are other practical details to add to the algorithm. At the end of the game, we need to display who was the winner (player1, the user, or player2 the computer). As indicated in the algorithm, on line 45 and 46, after each round of the game, 60 dashes are displayed and the program will wait for the user to press enter before displaying the next round.
please be follow the structures and please finish do by shortly
if you can't finish, partially finish the structures are okay.
1 Read file with shuffled deck 2 Validate cards 3 if cards are not valid catch exception and terminate program with appropriate message 5 else Distribute cards to player1 and player2 nbwarCards+correct input from user endGameFalse cardsOnTable new OnTable While not endGame do 10 12 13 14 15 16 faceUp1 get card from player1 place faceUp1 on cardsOnTable face-up faceup2get card from player2 place faceUp2 on cardsOnTable face-up display cardsOnTable display length of faceUp1 and length of faceUp2 if faceUp1 faceUp2 then player1 gets all cards in cardsOnTable in random order display player1 takes all cards on table else if faceUp1Explanation / Answer
import random
################################################################################
def main():
table = Table(['Matthew', 'Mark', 'Luke', 'John'])
table.deal_cards()
table.play_all()
def print_underline(string, line):
print(' {} {}'.format(string, line * len(string)))
################################################################################
class Table:
def __init__(self, players):
self.players = [Player(name, Hand()) for name in players]
self.deck = Deck()
self.rounds = 0
def deal_cards(self):
self.deck.shuffle()
self.deck.setup_hands(self.players)
for player in self.players:
player.show_hand()
def play_once(self, tied=None):
if tied is None:
self.count_round()
collection = Pot()
for player in (self.players if tied is None else tied):
player.drop_card(collection)
if tied:
player.drop_bonus(collection, 3)
winner = collection.winner
if winner is not None:
collection.reward(winner)
else:
winner = self.play_once(collection.tied)
collection.reward(winner)
return winner
def count_round(self):
self.rounds += 1
print_underline('Starting round {}'.format(self.rounds), '=')
def play_all(self):
while not self.finished:
self.play_once()
self.show_winner()
def show_winner(self):
for player in self.players:
if player.hand.has_cards:
print()
print(player.name, 'wins!')
break
@property
def finished(self):
return sum(bool(player.hand.cards) for player in self.players) == 1
################################################################################
class Player:
def __init__(self, name, hand):
self.name, self.hand = name, hand
def drop_card(self, collection):
if self.hand.has_cards:
collection.add_card(self.hand.take_top(), self)
def drop_bonus(self, collection, count):
collection.add_bonus(self.hand.cards[:count])
self.hand.cards = self.hand.cards[count:]
def give_cards(self, cards):
self.hand.add_all(cards)
def show_hand(self):
print(self.name, 'has', self.hand)
################################################################################
class Hand:
def __init__(self):
self.cards = []
def __str__(self):
return ', '.join(map(str, self.cards))
def add_card(self, card):
self.cards.append(card)
def take_top(self):
return self.cards.pop(0)
def add_all(self, cards):
self.cards.extend(cards)
@property
def has_cards(self):
return bool(self.cards)
################################################################################
class Deck:
def __init__(self):
self.cards = [Card(s, r) for s in Card.SUITE for r in Card.RANKS]
def shuffle(self):
random.shuffle(self.cards)
def setup_hands(self, players):
hands = [player.hand for player in players]
while len(self.cards) >= len(players):
for hand in hands:
hand.add_card(self.cards.pop())
return hands
################################################################################
class Card:
SUITE = 'H D S C'.split()
RANKS = '2 3 4 5 6 7 8 9 10 J Q K A'.split()
def __init__(self, suite, rank):
self.suite, self.rank = suite, rank
def __str__(self):
return '{}-{}'.format(self.rank, self.suite)
@property
def value(self):
return self.RANKS.index(self.rank)
################################################################################
class Pot:
def __init__(self):
self.cards = []
self.players = []
self.bonus = []
def add_card(self, card, player):
self.cards.append(card)
self.players.append(player)
def add_bonus(self, cards):
self.bonus.extend(cards)
@property
def winner(self):
self.show_pot()
values = [card.value for card in self.cards]
self.best = max(values)
if values.count(self.best) == 1:
return self.players[values.index(self.best)]
def show_pot(self):
for player, card in zip(self.players, self.cards):
print('{} laid down a {}.'.format(player.name, card))
def reward(self, player):
player.give_cards(self.cards)
player.give_cards(self.bonus)
@property
def tied(self):
for card, player in zip(self.cards, self.players):
if card.value == self.best:
yield player
################################################################################
if __name__ == '__main__':
main()
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.