Difference between revisions of "Hearts Card Game Assignment"

From CSE425S Wiki
Jump to navigation Jump to search
 
(19 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[https://www.cse.wustl.edu/~cosgroved/courses/cse425s/spring20/studio_hearts.pdf Instructions]
+
=Code To Implement=
 +
{{SMLToImplement|hearts|is_card_valid<br/>are_all_cards_valid<br/>card_score<br/>total_score_of_card_list<br/>total_card_count_for_all_players<br/>is_correct_total_of_cards<br/>is_shenanigans_detected|hearts}}
  
 
Given these type definitions:
 
Given these type definitions:
  
<nowiki>datatype suit = Clubs | Diamonds | Hearts | Spades
+
<syntaxhighlight lang="sml">
 +
datatype suit = Clubs | Diamonds | Hearts | Spades
 
datatype rank = Jack | Queen | King | Ace | Num of int  
 
datatype rank = Jack | Queen | King | Ace | Num of int  
 
type card = suit * rank
 
type card = suit * rank
type player = card list</nowiki>
+
type player = card list
 
+
</syntaxhighlight>
 
==cards==
 
==cards==
 
===is_card_valid===
 
===is_card_valid===
Define a function is_card_valid which accepts a card parameter.
+
Define a function <code>is_card_valid</code> which accepts a <code>card</code> parameter.
is_card_valid should evaluate to false if the int value of the Num constructor is
+
 
 +
<code>is_card_valid</code> should evaluate to false if the int value of the <code>Num</code> constructor is
 
less than 2 or greater than 10. Otherwise, it should evaluate to true
 
less than 2 or greater than 10. Otherwise, it should evaluate to true
  
 
===are_all_cards_valid===
 
===are_all_cards_valid===
Define a function are_all_cards_valid which accepts a card list parameter.
+
Define a function <code>are_all_cards_valid</code> which accepts a <code>card list</code> parameter.
are_all_cards_valid should evaluate to false if any of the cards in the list are
+
 
 +
<code>are_all_cards_valid</code> should evaluate to false if any of the cards in the list are
 
invalid, and true otherwise. Note: the empty list is valid.
 
invalid, and true otherwise. Note: the empty list is valid.
 
are_all_cards_valid may be tail-recursive or not at your preference.
 
  
 
==hearts==
 
==hearts==
From here on you will no longer need to concern yourself with invalid cards.
+
'''NOTE: From here on you will no longer need to concern yourself with invalid cards. We will not test your functions from here on with invalid cards.'''
  
Hearts is an trick-taking card game. Further, Hearts is an "evasion-type" card game
+
Hearts is an trick-taking card game. Further, [https://en.wikipedia.org/wiki/Hearts_(card_game) Hearts is an "evasion-type" card game]
 
where the objective is to avoid taking positive penalty point cards. The Queen of
 
where the objective is to avoid taking positive penalty point cards. The Queen of
 
Spades as well as each and every Heart are positive penalty point cards. Therefore,
 
Spades as well as each and every Heart are positive penalty point cards. Therefore,
Line 35: Line 37:
 
turning in all of their penalty point cards.
 
turning in all of their penalty point cards.
  
Note: "shenanigans" are devious tricks used especially for an underhand purpose.
+
Note: "[https://www.merriam-webster.com/dictionary/shenanigan shenanigans]" are devious tricks used especially for an underhand purpose.
  
 
===card_score===
 
===card_score===
Define a function card_score which accepts a card parameter.
+
Define a function <code>card_score</code> which accepts a <code>card</code> parameter.
card_score should evaluate to the int point value of the card as specified below:
+
 
 +
<code>card_score</code> should evaluate to the integer point value of the card as specified below:
  
The Queen of Spades: 13 points
+
{| class="wikitable"
Each Heart: 1 point
+
|style="text-align:right;"|The Queen of Spades
The Jack of Diamonds: minus 10 points
+
|13 points
All other cards: 0 points
+
|-
 +
|style="text-align:right;"|Each Heart
 +
|1 point
 +
|-
 +
|style="text-align:right;"|The Jack of Diamonds
 +
|minus 10 points  
 +
|-
 +
|style="text-align:right;"|All other cards
 +
|0 points  
 +
|}
  
 
Recall: ~ is the unary minus operator in SML.
 
Recall: ~ is the unary minus operator in SML.
 +
 +
===total_score_of_card_list===
 +
Define a function <code>total_score_of_card_list</code> which accepts a <code>card list</code> parameter.
 +
 +
<code>total_score_of_card_list</code> should evaluate to the sum of the scores of the cards in
 +
the list.
 +
 +
Note: the empty list should evaluate to 0.
 +
 +
===total_score_of_player_list===
 +
Define a function <code>total_score_of_player_list</code> which accepts a <code>player list</code> parameter.
 +
 +
<code>total_score_of_player_list</code> should evaluate to the sum of the scores of the players
 +
in the list.
 +
 +
Note: the empty list should evaluate to 0.
 +
 +
Recall: <code>type player = card list</code>
 +
 +
===total_card_count_for_all_players===
 +
Define a function <code>total_card_count_for_all_players</code> which accepts a <code>player
 +
list</code> parameter.
 +
 +
<code>total_card_count_for_all_players</code> should evaluate to the total number of cards
 +
of all the players in the list.
 +
 +
Note: the empty list should evaluate to 0.
 +
 +
This function may use the [https://smlfamily.github.io/Basis/list.html#SIG:LIST.length:VAL length] function in the [https://smlfamily.github.io/Basis/list.html List] structure.
 +
 +
<!--
 +
Recall: many of the higher ordered functions in List are curried.
 +
 +
This function must appropriately use a higher order function from the [https://smlfamily.github.io/Basis/list.html List] structure
 +
 +
Tip: if you are struggling with type checking errors resulting from curried function calls, try wrapping the arguments in parentheses.
 +
-->
 +
 +
===is_correct_total_of_cards===
 +
Perhaps a player neglected to turn in all of his or her cards.
 +
 +
Define a function <code>is_correct_total_of_cards</code> which accepts a <code>player list</code> parameter. <code>is_correct_total_of_cards</code> should return true if the total number of
 +
cards of all the players in the list is 52. Otherwise, it should evaluate to false.
 +
 +
Recall the equality operator in SML is a single =.
 +
 +
===is_shenanigans_detected===
 +
Not turning in all of one’s cards could be an honest mistake. Neglecting to turn in point cards, however??? We will declare that "shenanigans!"
 +
 +
Define a function <code>is_shenanigans_detected</code> which accepts a <code>player list</code> parameter.
 +
 +
<code>is_shenanigans_detected</code> should evaluate to true if the total points of all the
 +
players in the list is not 16. Otherwise, it should evaluate to false.
 +
 +
Recall the not equality operator in SML is <>.
 +
 +
Note: there are far more sophisticated checks we could do. We will simply check for not 16.
 +
 +
=Type Summary=
 +
<syntaxhighlight lang="sml">
 +
val is_card_valid = fn : card -> bool
 +
val are_all_cards_valid = fn : card list -> bool
 +
val card_score = fn : card -> int
 +
val total_score_of_card_list = fn : card list -> int
 +
val total_score_of_player_list = fn : player list -> int
 +
val total_card_count_for_all_players = fn : player list -> int
 +
val is_correct_total_of_cards = fn : player list -> bool
 +
val is_shenanigans_detected = fn : player list -> bool
 +
</syntaxhighlight>
 +
 +
=Test=
 +
{{SMLUnitTesting|run_hearts_testing|hearts}}

Latest revision as of 18:52, 10 July 2023

Code To Implement

file: src/main/sml/hearts/hearts.sml Smlnj-logo.png
functions: is_card_valid
are_all_cards_valid
card_score
total_score_of_card_list
total_card_count_for_all_players
is_correct_total_of_cards
is_shenanigans_detected

Given these type definitions:

datatype suit = Clubs | Diamonds | Hearts | Spades
datatype rank = Jack | Queen | King | Ace | Num of int 
type card = suit * rank
type player = card list

cards

is_card_valid

Define a function is_card_valid which accepts a card parameter.

is_card_valid should evaluate to false if the int value of the Num constructor is less than 2 or greater than 10. Otherwise, it should evaluate to true

are_all_cards_valid

Define a function are_all_cards_valid which accepts a card list parameter.

are_all_cards_valid should evaluate to false if any of the cards in the list are invalid, and true otherwise. Note: the empty list is valid.

hearts

NOTE: From here on you will no longer need to concern yourself with invalid cards. We will not test your functions from here on with invalid cards.

Hearts is an trick-taking card game. Further, Hearts is an "evasion-type" card game where the objective is to avoid taking positive penalty point cards. The Queen of Spades as well as each and every Heart are positive penalty point cards. Therefore, players attempt to avoid taking those cards. The Jack of Diamonds is the one favorable card players strive to take (it is worth negative penalty points). For simplicity, we will ignore a common variation which involves a player "shooting the moon" by taking all of the positive penalty point cards.

For the remainder of this assignment you will write code to calculate scores, count the number of cards, as well as detect possible shenanigans of a player/players not turning in all of their penalty point cards.

Note: "shenanigans" are devious tricks used especially for an underhand purpose.

card_score

Define a function card_score which accepts a card parameter.

card_score should evaluate to the integer point value of the card as specified below:

The Queen of Spades 13 points
Each Heart 1 point
The Jack of Diamonds minus 10 points
All other cards 0 points

Recall: ~ is the unary minus operator in SML.

total_score_of_card_list

Define a function total_score_of_card_list which accepts a card list parameter.

total_score_of_card_list should evaluate to the sum of the scores of the cards in the list.

Note: the empty list should evaluate to 0.

total_score_of_player_list

Define a function total_score_of_player_list which accepts a player list parameter.

total_score_of_player_list should evaluate to the sum of the scores of the players in the list.

Note: the empty list should evaluate to 0.

Recall: type player = card list

total_card_count_for_all_players

Define a function total_card_count_for_all_players which accepts a player list parameter.

total_card_count_for_all_players should evaluate to the total number of cards of all the players in the list.

Note: the empty list should evaluate to 0.

This function may use the length function in the List structure.


is_correct_total_of_cards

Perhaps a player neglected to turn in all of his or her cards.

Define a function is_correct_total_of_cards which accepts a player list parameter. is_correct_total_of_cards should return true if the total number of cards of all the players in the list is 52. Otherwise, it should evaluate to false.

Recall the equality operator in SML is a single =.

is_shenanigans_detected

Not turning in all of one’s cards could be an honest mistake. Neglecting to turn in point cards, however??? We will declare that "shenanigans!"

Define a function is_shenanigans_detected which accepts a player list parameter.

is_shenanigans_detected should evaluate to true if the total points of all the players in the list is not 16. Otherwise, it should evaluate to false.

Recall the not equality operator in SML is <>.

Note: there are far more sophisticated checks we could do. We will simply check for not 16.

Type Summary

val is_card_valid = fn : card -> bool
val are_all_cards_valid = fn : card list -> bool
val card_score = fn : card -> int
val total_score_of_card_list = fn : card list -> int
val total_score_of_player_list = fn : player list -> int
val total_card_count_for_all_players = fn : player list -> int
val is_correct_total_of_cards = fn : player list -> bool
val is_shenanigans_detected = fn : player list -> bool

Test

source folder: src/test/sml/hearts
how to run with CM.make verbosity off: sml -Ccm.verbose=false run_hearts_testing.sml
how to run with CM.make verbosity on: sml run_hearts_testing.sml

note: ensure that you have removed all printing to receive credit for any assignment.

SML Error Messages