CSE231
Spring 2019
Updated 04/09/2019
Project 10: Basra A Fishing Card Game
This assignment is worth 55 points (5.5% of the course grade) and must be completed and turned in before 11:59pm on April 15, 2019.
Assignment Overview:
How to use a custom-built Python class. This project focuses on the design, implementation and testing of a Python program which uses an instructor-supplied module to play a card game, as described below.
Assignment Background
This game belongs to a category of card games called fishing cards games. It was played originally in
the Middle East. A fishing game is a card game using the following mechanism. Each player in turn
matches a card from their hand with one (or more) of those lying face-up on the table and then takes them.
If the card which the player played out does not match one of the existing cards, it stays on the table. Table
cards are picked up by the last player.
There can be 2 or 4 players, but here we consider only the 2-player scenario. A standard 52-card deck is
used. Initially, all cards are shuffled, then 4 cards are dealt to each player and another 4 cards are placed
on the table facing up. The game depends on comparing the cards in hand to the cards on the table. Players
take turns fishing, each using one card at a time as bait. If a player cannot fish any table card(s) using
any of his bait (cards in hand), the player places his bait of choice (one of his cards) on the table. By
placing one card on the table (a failed bait), this card becomes a table card (the bait turns to a fish). After
each round (4 fishing attempts by each player), both players run out of cards and each get another 4 cards
from the deck. Table cards carry over from one round to the next. The game continues until the deck is all
dealt (6 fishing rounds). The winner is the one who can fish the largest number of cards (ranks do not
matter in this count) and achieve the largest number of Basras (a Basra will be explained later).
Game Rules:
1- Two players play the game.
2- A bait (an in-hand card) can fish any table card of the same rank (regardless of their suits). In such
a case both cards are added to the players pile. For example, a 7 captures a 7, a queen captures a
queen, and so on.
3- A numeric bait (an in-hand card that is neither a jack, a queen or a king) can fish multiple table cards if their ranks add up to its rank. In such a case, all of them (including the bait) are added to the players pile.
4-
For example, if the table has 3, 4, 5 and 8 and the player has 9 in hand, the player
can capture the 5 and the 4 and add both of them along with his 9 to his pile. In Basra, Aces do not
receive any special treatment. An Ace is just a card whose rank is 1, nothing more.
Using the same card, a player can make more than one capture. For example, if the table has a 4,
6, 10 and 3 and the player has a 10 (his bait), the 10 and the 4 and the 6 from the table along with
the bait (the in-hand 10) will be added to the players pile. Or if after the initial deal the table
contains two kings, a player can capture both of them using one king as bait. You can only capture
pairs or singles, not combinations of more than two cards.
5- 6-
7-
8- We have 2 special cards: a.
b. 9-
Project Assignment:
Before you begin to write any code, play with the game at https://www.kongregate.com/games/mhdside/basra and look over the sample interaction below to be sure you understand the rules of the game and how you will simulate the game. We will have these lists to be used during playing the game (defined in the main function):
p1_cards: cards in hand of player1 p2_cards: cards in hand of player2 t_cards: cards on the table
p1_pile: captured cards of player 1 p2_pile: captured cards of player 2 basra_1: captured Basras of player 1 basra_2: captured Basras of player 2 You should write the following functions:
distribute_cards(deck, p1_cards, p2_cards, t_cards, round1)
The round1 is a Boolean that is True if this is the first round; False otherwise. If it is round1, each cards list will start empty and be filled by this function. This function does not return anything (lists are changed because they are mutable). This function deals each player four cards:
If a player plays a card (a bait) that does not match anything, it stays face up on the table, and is
available for capture in future turns.
Queens and kings have no numerical value. A queen can capture or be captured by a queen and a
king can capture or be captured by a king. The only other way to capture a queen or king is to play
a special card (jack or seven of diamonds explained later).
A Basra occurs if a player captures all the cards from the table, leaving it empty, using an ordinary
card or seven of diamonds. The card that is used to get the Basra is saved in a different place (Basra
list) and depending on the type of the card played it will have different score.
Jacks: If a jack is played when there are cards on the table, it captures all the cards from
the table, leaving it empty, but this does not count as a Basra (the jack and the cards are
added to the players pile though). If it is played when the table is empty, it does not capture
anything, but it remains on the table.
The seven of diamonds: has the same property as Jacks, it captures everything on the
table. If the cards on the table are all numerics, and their values add up to 10 or less, this
counts as a Basra. The card (seven of diamonds) is saved in the Basra list. The other cards
are added to the players main pile.
After the last card has been played, any cards that remain on the table are taken by the last player.
The cards are added to the players main pile (no Basras here).
1- If this is the first round, each player receives 4 cards and another 4 cards are placed on the table. The order of dealing is 4 cards to player 1, then four cards to player 2, and then 4 cards to the table. The deal() function from the Card class can be used to deal a card from the deck.
2- If this is not the first round, each player receives 4 cards. The order of dealing is the same: 4 cards to player 1 and then 4 cards to player 2 (no cards dealt to the table).
For example:
Starting Deck 10, 8, A, J, 9, J, 5, 4, 7, 9, K, 3, 7, 2, 3, A, 4, K, 9, 5, 10, 4, 6, Q, 7, 5, 8, 2, Q, 8, J, 9, 2, 3, 7, 6, Q, 5, 8, 4, 6, 3, Q, A, 10, A, K, 10, J, K, 2, 6
– Testing round1. –
player 1 hand: [6, 2, K, J]
player 2 hand: [10, K, A, 10]
table cards: [A, Q, 3, 6]
– Testing round2. –
Starting Deck: 10, 8, A, J, 9, J, 5, 4, 7, 9, K, 3, 7, 2, 3, A, 4, K, 9, 5, 10, 4, 6, Q, 7, 5, 8, 2, Q, 8, J, 9
player 1 hand: [4, 8, 5, Q]
player 2 hand: [6, 7, 3, 2]
table cards:[]
get_card_index(card,card_list) int
This function returns the index of the card in the list card_list if it exists, otherwise returns None, The __eq__() function from the Card class can be used here (which means that you are using ==), to compare the objects. You might find enumerate() useful; it works on lists.
For example:
Card:10
Card List:[6, 2, K, J, 10, K, A, 10, A, Q]
Card Index:7
– Testing card not in the list. –
Card:3
Card List:[6, 2, K, J, 10, K, A, 10, A, Q]
Card Index:None
get_matching_cards(card, t_cards) list
This function finds if there are any similar cards on the table to the playing card (card). The matching cards should have the same rank. It should return a list of the matching cards. If no matching cards on the table, return an empty list. The equal_value() function from the Card class can be used here.
For example:
– Testing only one card on the table. –
Card: 2
Table Card List: [6, 2, K, J, 10, K, A, 10, A, Q, 3, 6] Instructor matching Cards: [2]
Student matching Cards: [2]
– Testing more matching cards on the table – Card: 6
Table Card List: [6, 2, K, J, 10, K, A, 10, A, Q, 3, 6] Instructor matching Cards: [6, 6]
Student matching Cards:[6, 6]
numeric_card(card) Boolean
This function checks if the card is numeric card (rank is <= 10) not picture card, rank() function from the Card class can be used here. It will return True if the card is numeric, otherwise return False. A card is numeric if its rank is less than 11.For example:———- Testing if numeric. ———-Card:6Output:True———- Testing if not numeric ———-Card:KOutput:Falseremove_cards(cards_list,cards)This function removes a list of cards (cards) from another list of cards cards_list. This function doesnt return anythingit modifies cards_list. The get_card_index()function can be used here along with the remove() method of a list.This function will be called by almost all the functions in the project. For example, it will be used to remove cards from:1- Remove matching cards from a table list: remove_cards(t_cards, matching_cards)2- Remove one card from both players lists: remove_cards(player_list,[card])For example:———- Testing removing only one card. ———- Card: 2Starting Player Cards: [6, 2, K, J]Ending Player Cards: [6, K, J]———- Testing removing card not in the list. ———- Card: 2Starting Player Cards: [6, K, J]Ending Player Cards: [6, K, J]———- Testing removing many matching cards ———-Cards: [6, 6]Starting Table Cards: [6, 2, K, J, 10, K, A, 10, A, Q, 3, 6] Ending Table Cards: [2, K, J, 10, K, A, 10, A, Q, 3]———- Testing removing many cards not in the list———- Cards: [6, 6]Starting Table Cards: [2, K, J, 10, K, A, 10, A, Q, 3] Ending Table Cards: [2, K, J, 10, K, A, 10, A, Q, 3]get_sum_matching_cards(card,t_cards) listThis function is provided to you in the starter code. It finds pairs of cards (or singletons) on the table that add up to the value of card. The rank() function is used and compared to all summations of any two cards on the table. This function returns a list of cards that add up to cards rank. If the card is a Jack, Queen or King, the function returns an empty list.sum_rank(card_list) int (optional)This optional function computes the sum of cards values in the card_list. The rank() function shouldbe used. For example,Table Cards:[6, 2, K, J]Sum_rank = 6 + 2 + 13 + 11 = 32jack_play(card,player,pile,basra,t_cards)This function is called when the playing card (card) is a Jack. This function doesnt return anything.If the table (t_cards) is empty, the Jack card should be appended to the empty table list (t_cards)and removed from the player list (player). If the table is not empty,1. a Jack card captures all cards on the table (t_cards) and adds them to the players pile (pile).2. After completing step 1 we have to put the Jack card someplace:o if the starting table only had a Jack (or all Jacks), this card will be Basra, and should be added to players Basra list (basra).o else the Jack card should be added to the players pile3. The Jack card then should be removed from the player list (player).For example,———- Testing empty table. ———-Starting table cards: []Starting player hand: [6, 2, K, J]Starting player pile:[]Starting player Basra:[]Card to play:JEnding table cards:[J]Ending player hand:[6, 2, K]Ending player pile:[]Ending player Basra: []———- Testing with cards on table not all jacks. ———- Starting player hand: [6, 2, K, J]Starting table cards: [10, K, A, 10]Card to play: JEnding player hand: [6, 2, K]Ending player pile: [10, K, A, 10, J]Ending player Basra: []Ending table cards: []———- Testing with all jacks on table. ———- Starting player hand: [6, 2, K, J]Starting table cards: [J, J, J]Card to play: JEnding player hand:[6, 2, K]Ending player pile:[J, J, J]Ending player Basra:[J]Ending table cards:[]seven_diamond_play(card,player,pile,basra,t_cards)This function is called when the playing card (card) is 7D (seven of diamonds). This function doesnt return anything.If the table is empty, the 7D card should be appended to the table list (t_cards) and removed from the players hand line (player).If the table is not empty,1. the 7D card captures all cards on the table (t_cards) and adds them to the players pile (pile).2. If the values of the cards on the table add up to <=10:a. This 7D card will be Basra, and should be added to players Basra list (basra).b. else the 7D card should be added to the players pile (pile). .3. The card then should be removed from the players hand list (player).For example,———- Testing empty table. ———-Starting player hand: [J, 5, 4, 7]Card to play:7Ending player hand:[J, 5, 4]Ending player pile: []Ending player Basra: []Ending table cards: [7]———- Testing with cards on table not all numerics. ———- Starting player hand: [J, 5, 4, 7]Starting table cards: [6, 2, K, J]Card to play:7Ending player hand:[J, 5, 4]Ending player pile:[6, 2, K, J, 7]Ending player Basra:[]Ending table cards: []———- Testing with all numeric cars on table and sum>10 . – Starting player hand: [J, 5, 4, 7]
Starting table cards: [3, 7, 2, 3]
Card to play: 7
Ending player hand: [J, 5, 4]
Ending player pile: [3, 7, 2, 3, 7]
Ending player Basra: []
Ending table cards: []
– Testing with all numeric cars on table and sum<=10 . ———- Starting player hand: [J, 5, 4, 7]Starting table cards: [2, 3, A, 4]Card to play: 7Ending player hand:[J, 5, 4]Ending player pile:[2, 3, A, 4]Ending player Basra:[7]Ending table cards:[]play(card,player,pile,basra,t_cards)This function checks the value of the playing card with other cards on the table (t_cards). This function will be used by both players. This function doesnt return anything.1- If there are no cards on the table, the card will be added to the table list (t_cards) and remove card from player list (player)2- If the card is a Jack (rank is 11), the jack_play() function is called.3- If the card is 7D (seven of diamonds: rank is 7 and suit is 2), the functionseven_diamond_play() is called.4- If the card is a King or Queen (rank is > 11):
a. Find all matching cards on the table, the get_matching_cards()should be used. i. If no matching cards, the card should be appended to the table (t_cards).
ii. If there are matching cards, the matching cards will be removed from the table (t_cards) and moved to the players main pile (pile).
1. If the table becomes empty after removing them, this counts as Basra, and the bait (the in-hand card) is added to the Basra list of the player (basra).
2. If the table is not empty after deletion, then the card will be added to the players main pile (pile) as a regular capture.
b. and remove card from player list (player)
5- If the card is a numeric card, find the matching cards and the matching sum of cards.
get_matching_cards() and get_sum_matching_cards() should be used.
a. If there are matching cards, both lists of cards should be removed from the table and
added to players pile if they are not empty.
i. If the table became empty, this counts as Basra, and the bait should be added to
the Basra list (basra), otherwise, it will be added to players main pile (pile)
as a regular capture.
b. If both lists are empty, no matching or sums on the table, then the card is added to the
table for future use.
c. and remove card from player list (player)
For example,
– Testing empty table no jack no 7D. – Starting player hand: [J, 5, 4, 7]
Card to play: 5
Ending player hand: [J, 4, 7]
Ending player pile: []
Ending player Basra: []
Ending table cards: [5]
– Testing with cards on table and jack card played. – Starting player hand: [6, 2, K, J]
Starting table cards: [J, J]
Card to play:J
Ending player hand: [6, 2, K]
Ending player pile: [J, J]
Ending player Basra: [J]
Ending table cards: []
– Testing with cards on table and 7D played . – Starting player hand: [J, 5, 4, 7]
Starting table cards: [3, 7, 2, 3]
Card to play:7
Ending player hand:[J, 5, 4]
Ending player pile:[3, 7, 2, 3, 7]
Ending player Basra:[]
Ending table cards: []
Testing with picture card played and matching cards on table. Starting player hand: [6, 2, K, J]
Starting table cards: [K, K]
Card to play: K
Ending player hand: [6, 2, J]
Ending player pile: [K, K]
Ending player Basra: [K]
Ending table cards: []
Testing with numeric card played, with matching cards on table. Starting player hand: [8, 4]
Starting table cards: [7, A, 8, 4]
round 1
Card to play: 8
Ending player hand: [4]
Ending player pile: [8, 7, A, 8]
Ending player Basra: []
Ending table cards: [4]
round 2
Card to play: 4
Ending player hand: []
Ending player pile: [8, 7, A, 8, 4]
Ending player Basra: [4]
Ending table cards: []
compute_score(p1_pile,p2_pile,basra_1,basra_2) int,int This function takes the four lists as parameters and computes the score of each player. A tuple
(player1_score, player2_score) is returned.
1- 2- 3-
4- King or Queen Basras score 20.
5- Jack Basra scores 30.
For example,
– Testing draw game. –
Player 1 cards: 26 cards
Player 2 cards: 26 cards
Player 1 basra:[]
Player 2 basra:[]
Instructor scores: 0 and 0
Students scores: 0 and 0
The player that has the majority of the cards (27 or more) scores 30 points.
If both have exactly the same number of cards, both get 0.
Each numeric Basra scores 10.
– Testing p1 has more cards but no basras. – Player 1 cards: 27 cards
Player 2 cards: 25 cards
Player 1 basra: []
Player 2 basra: []
Instructor scores: 30 and 0
Students scores: 30 and 0
– Testing same # of cards, p1 with basras but not p2. – Player 1 cards: 26 cards
Player 2 cards: 26 cards
Player 1 basra: [K, J, 5]
Player 2 basra: []
Instructor scores: 60 and 0
Students scores: 60 and 0
– Testing same # of cards with both has basras. – Player 1 cards: 26 cards
Player 2 cards: 26 cards
Player 1 basra: [K]
Player 2 basra: [J, 5]
Instructor scores: 20 and 40
Students scores: 20 and 40
– Testing p1 cards are more with both has basras. – Player 1 cards: 32 cards
Player 2 cards: 10 cards
Player 1 basra: [K, J]
Player 2 basra: [3, K]
Instructor scores: 80 and 30
Students scores: 80 and 30
display_table(t_cards,p1_cards,p2_cards)
This function is provided to you. It displays the game table
main()
A game consists of six rounds where players alternate turns until their hands are empty (no cards). The first round begins with 4 cards dealt to each hand and 4 cards dealt to the table (i.e. 12 cards). Each subsequent round begins with 4 cards dealt to each hand (no cards dealt to the table, i.e. 8 cards). There will be 8 turns in each round (each player has 4 cards and each turn plays one card from their hand). After six rounds there are no more cards in the deck to be dealt so the game ends. (Hint: this is your basic control structure for the game.)
Your program must meet the following specifications.
The program begins by offering a welcome message and displays the rules of the game. Then, the player is asked to play or not. This control is provided in the starter code provided. Here is what you need to add:
1. Create an object of Deck class.
2. Initialize all player lists to all zeros.
3. Prompt the user if he wants to play or not. The only acceptable answers are n or y.
Capitalization does not matter. The program should keep asking the player for a valid input.
4. If the player wants to play, the deck is shuffled
5. Then, the game starts. You will need a while loop to play the game (this will be in addition to
the while loop in the provided code that is used to ask whether the user wants to play another
game). What Boolean expression should control this loop?
6. Cards dealt to the table and players for the first roundsubsequent rounds do not deal to table.
7. At the start of each round, the number of cards left in the deck and the game table are displayed. 8. For each players turn, the program should prompt the user for the index of the card he wants to
play. The index should be >= 0 and less than the length of the player list. The program should keep
asking the player for a valid card index. Then, the play() function is called.
9. Any player can quit the game at any point. To quit the game, the player should enter q when asked for a card index. When the player quits the game, the program should display a goodbye
message.
10. After each player takes a turn display the game.
11. For each round, each player should receive 4 cards each time until there is no cards left in the deck. 12. Play alternates between the two players. Use a variable to keep track of who is playing.
13. At the end of a round, if the table is not empty, the last player takes all the cards on the table.
Display the game to show that the table is now empty.
14. The game ends when the deck is empty. The player who has the highest score is the winner.
15. When the game has come to its conclusion, the program should output whether player1 or player2
won. It then should ask the user whether to play again.
16. If the user selects to play again, your program should. All the lists should be reinitialized and the
deck should be reset. The reset() function should be used.
17. If the user chooses not to play the game again, the program should display a goodbye message.
Assignment Deliverables
The deliverable for this assignment is the following file: Proj10.py the source code for your Python program
Be sure to use the specified file name and to submit it for grading via the Mimir system before the project deadline.
Assignment Notes
1. We provide a module called cards.py that contains a Card class and a Deck class. Your program must use this module (import cards). Do not modify this file! and do not upload it to Mimir!
2. Laboratory Exercise #10 demonstrates how to use the cards module. Understanding those programs should give you a good idea how you can use the module in your game.
3. We have provided a starter code named proj10.py to get you started.
Using this code is mandatory. It runs as is, but does nothing useful. Gradually replace the pass code (marked with comments) with your own code. (Delete the pass code.)
Test Cases: Test 1:
Test 2:
Test 3:
Test 4:
Grading Rubric
General Requirements:
4 pts Coding Standard 1-9
(descriptive comments, source code Headers, function headers, etc) Function Tests:
4 pts distribute_cards()
2 pts get_card_index()
5 pts get_matching_card()
2 pts numeric_card()
2 pts remove_cards()
5 pts jack_play()
5 pts seven_diamond_play()
5 pts play()
5 pts compute_score()
Program Tests
4 pts Test1
4 pts Test2
4 pts Test3
4 pts Test4
Reviews
There are no reviews yet.