[SOLVED] COMP30020 - Declarative Programming -  Project 1

35.00 $

Category:

Description

5/5 - (3 votes)

The objective of this project is to practice and assess your understanding of functional programming and Haskell. You will write code to implement a logical deduction game.

The Game

For this project, you will implement a two-player logical guessing game. Two players face each other, each with a complete standard deck of western playing cards (without jokers). One player will be the answerer and the other is the guesser. The answerer begins by selecting some number of cards from his or her deck without showing the guesser. These cards will form the answer for this game. The aim of the game is for the guesser to guess the answer.

Once the answerer has selected the answer, the guesser chooses the same number of cards from his or her deck to form the guess and shows them to the answerer. The answerer responds by telling the guesser these five numbers as feedback for the guess:

  1. How many of the cards in the answer are also in the guess (correct cards).
  2. How many cards in the answer have rank lower than the lowest rank in the guess (lower ranks). Ranks, in order from low to high, are 2–10, Jack, Queen, King, and Ace.
  3. How many of the cards in the answer have the same rank as a card in the guess (correct ranks). For this, each card in the guess is only counted once. That is, if the answer has two queens and the guess has one, the correct ranks number would be 1, not 2. Likewise if there is one queen in the answer and two in the guess.
  4. How many cards in the answer have rank higher than the highest rank in the guess

(higher ranks).

  1. How many of the cards in the answer have the same suit as a card in the guess, onlycounting a card in the guess once (correct suits). For example, if the answer has two clubs and the guess has one club, or vice versa, the correct suits number would be 1, not 2.

Note that the order of the cards in the answer and the guess is immaterial, and that, since they come from a single deck, cards cannot be repeated in either answer or guess.

The guesser then guesses again, and receives feedback for the new guess, repeating the process until the guesser guesses the answer correctly. The object of the game for the guesser is to guess the answer with the fewest possible guesses.

A few examples of the feedback for a given answer and guess:

Answer Guess Feedback Explanation
3♣,4♥ 4♥,3♣ 2,0,2,0,2 2 answer cards match guess cards, no answer cards less than a 3, 2 answer cards match guess ranks, no answer cards greater than a 4, 2 answer cards match guess suits.
3♣,4♥ 3♣,3♥ 1,0,1,1,2 1 exact match (3♣), no answer cards less than a 3, 1 answer card matches a guess rank, 1 answer card greater than a 3, 2 answer cards match guess suits.
3♦,3♥ 3♠,3♣ 0,0,2,0,0 No exact matches, no answer cards less than a 3, 2 answer cards match a guess rank, no answer cards greater than a 3, no answer cards match guess suits.
3♣,4♥ 2♥,3♥ 0,0,1,1,1 No exact matches, no answer cards less than a 2, 1 answer card matches a guess rank (the 3), 1 answer card greater than a 3, 1 answer card match a guess suit (♥).
A♣,2♣ 3♣,4♥ 0,1,0,1,1 No exact matches, 1 answer card less than a 3 (the 2; A is high), no answer card matches a guess rank, 1 answer card greater than a 4 (the A), 1 answer card match a guess suit (either ♣; you can only count 1 because there’s only 1 ♣ in the guess).

The Program

For this assignment, you will write Haskell code to implement code for both the answerer and guesser parts of the game. This will require you to write a function to evaluate a guess to produce feedback, one to provide an initial guess, and one to use the feedback from the previous guess to determine the next guess. The latter function will be called repeatedly until it produces the correct guess. You will find it useful to keep information between guesses; since Haskell is a purely functional language, you cannot use a global or static variable to store this. Therefore, your initial guess function must return this game state information, and your next guess function must take the game state as input and return the updated game state as output. You may put any information you like in the game state, but you must define a type GameState to hold this information.

I will supply a Card module providing the Card, Rank, and Suit types and their constructors. This implementation has a few enhancements from the types presented in lectures. First, all three types are in the Eq class. All are also in the Bounded and Enum class, which means, for example, that [minBound..maxBound]::[Card] is the list of all cards in order, from 2♣to A♠, and similarly [minBound..maxBound]::[Rank] is the list of ranks from 2 to Ace, and similarly for Suit. This also means that, for example, succ (Card Club R5) ==

(Card Club R6) and succ (Card Heart Ace) == (Card Spade R2). Read the documentation for Bounded and Enum classes for more things you can do with them.

The Rank and Suit types are also in the Ord class, so for example Ace > King and Heart < Spade. For convenience, all three types are also in the Show class so that ranks and suits are shown as a single character (10 is shown as T), and cards as two characters: rank followed by suit. All three are also in the Read class, which means that, for example, (read

“[2C,AH]”)::[Card] returns the list [Card Club R2, Card Heart Ace] (which would be printed as [2C,AH]).

You must define the following three functions, as well as the GameState type:

feedback :: [Card] [Card] (Int,Int,Int,Int,Int) takes a target and a guess (in that order), each represented as a list of Cards, and returns the five feedback numbers, as explained above, as a tuple.

initialGuess :: Int ([Card],GameState) takes the number of cards in the answer as input and returns a pair of an initial guess, which should be a list of the specified number of cards, and a game state. The number of cards specified will be 2 for most of the test, and 3 or 4 for the remaining tests, as explained below.

nextGuess :: ([Card],GameState) (Int,Int,Int,Int,Int) ([Card],GameState) takes as input a pair of the previous guess and game state, and the feedback to this guess as a quintuple of counts of correct cards, low ranks, correct ranks, high ranks, and correct suits, and returns a pair of the next guess and new game state.

You must call your source file Proj1.hs, and it must contain the module declaration:

module Proj1 (feedback, initialGuess, nextGuess, GameState) where

Please keep all your code in this one module.

I will also provide a test driver program called Proj1test.hs to allow you to conveniently test your Proj1 implementation. You can specify the cards of the answer on the command line, and the program will print out each guess and the corresponding feedback and report the number of guesses needed to find the answer. The Proj1test.hs is similar to the test driver I will use for testing your code. You can compile and link your code for testing using the command:

ghc -O2 –make Proj1test