Problem Statement and Description:
1 Structure of the bit fields
1.1 The card bit field
As explained above only six bits are really needed to describe a playing card. However a seventh bit has been added, this is only as a matter of convenience, as you will see below it makes the card 000000002 an invalid card and thus the standard C logic tests can be used to test if a card is valid or not. As only seven bits are required you can use one byte to store the value. A C type definition of:
1 Structure of the bit fields
1.1 The card bit field
As explained above only six bits are really needed to describe a playing card. However a seventh bit has been added, this is only as a matter of convenience, as you will see below it makes the card 000000002 an invalid card and thus the standard C logic tests can be used to test if a card is valid or not. As only seven bits are required you can use one byte to store the value. A C type definition of:
typedef unsigned char card ;
would be useful to describe this new data type, as we don’t treat it as a whole but as a bit set.
The byte will have the following format, bits 0 encodes the colour, bits 1, 2, 3, & 4 encode the value and bits 5 & 6 encode the suit. Bit 7 is unused. Each of these subsections has the values as depicted in Tables 2, 3 & 4.
Following this table the Ace of Hearts would be 00000012(1) and the King of Spades would be 011110002(120).
would be useful to describe this new data type, as we don’t treat it as a whole but as a bit set.
The byte will have the following format, bits 0 encodes the colour, bits 1, 2, 3, & 4 encode the value and bits 5 & 6 encode the suit. Bit 7 is unused. Each of these subsections has the values as depicted in Tables 2, 3 & 4.
Following this table the Ace of Hearts would be 00000012(1) and the King of Spades would be 011110002(120).
1.2 The pairs bit field
The second bit field is used to hold the number of pairs in a hand. It has the format that the four least significant bits (bits 0-3) contain the number of pairs contained in a hand and the four most significant bits (bits 4-7) hold the value of the card as detailed in Table 3. A C typedef of:
typedef unsigned char p a i r s ;
will be useful here.
static char ∗values []= {”Ace” ,”Two” ,”Three” ,”Four” , ”Five” ,”Six” ,”Seven” ,”Eight” , ”Nine” ,”Ten” ,”Jack” ,”Queen” , ”King”};
static char ∗colour []= {”Black” ,”Red”};
The second bit field is used to hold the number of pairs in a hand. It has the format that the four least significant bits (bits 0-3) contain the number of pairs contained in a hand and the four most significant bits (bits 4-7) hold the value of the card as detailed in Table 3. A C typedef of:
typedef unsigned char p a i r s ;
will be useful here.
2 Programming Tasks
You should begin by reading the example code carefully. It contains some hints and comments on where to fill in the blanks.
The first step will be writing a function that displays the card. You can use the various bit fields as an index to an array of strings once extracted. The arrays are:
static char ∗suits [] = {”Hearts”,”Diamonds”, ”Clubs” ,”Spades”};
You should begin by reading the example code carefully. It contains some hints and comments on where to fill in the blanks.
The first step will be writing a function that displays the card. You can use the various bit fields as an index to an array of strings once extracted. The arrays are:
static char ∗suits [] = {”Hearts”,”Diamonds”, ”Clubs” ,”Spades”};
static char ∗values []= {”Ace” ,”Two” ,”Three” ,”Four” , ”Five” ,”Six” ,”Seven” ,”Eight” , ”Nine” ,”Ten” ,”Jack” ,”Queen” , ”King”};
You should print the card as “Ace of Hearts, is Red”, with one card per
line. Test your function by creating cards individually and displaying them.
Once you can display cards you should then write a function that populates a deck (array of 52) with cards. The deck should be sorted in order by suit, that is Ace to King of hearts, then diamonds etc. With some clever arithmetic you can accomplish this in one pass of the deck. Print the deck once you have populated it.
Once you have a deck, develop a method for shuffling it. As a hint investigate the C standard library functions rand() and srand(). Shuffling involves mixing the cards up so that the order is random. Print the deck a second time and check that you have actually mixed up the deck.
Now that we have a working shuffling algorithm we are ready to play cards. To keep things reasonably simple we are going to simulate a simplified version of poker. In this game 5 hands of five cards are dealt. There is no swapping of cards and the winner is determined by who has the highest pair. A pair of cards are cards that have the same value e.g. the Ace of Hearts and the Ace of Spades are a pair. The number of pairs contained in a hand, three or four of a kinds have no bearing on the result. If none of the five hands contains a pair, or two hands contain the same highest pair, the game is considered drawn.
Once you can display cards you should then write a function that populates a deck (array of 52) with cards. The deck should be sorted in order by suit, that is Ace to King of hearts, then diamonds etc. With some clever arithmetic you can accomplish this in one pass of the deck. Print the deck once you have populated it.
Once you have a deck, develop a method for shuffling it. As a hint investigate the C standard library functions rand() and srand(). Shuffling involves mixing the cards up so that the order is random. Print the deck a second time and check that you have actually mixed up the deck.
Now that we have a working shuffling algorithm we are ready to play cards. To keep things reasonably simple we are going to simulate a simplified version of poker. In this game 5 hands of five cards are dealt. There is no swapping of cards and the winner is determined by who has the highest pair. A pair of cards are cards that have the same value e.g. the Ace of Hearts and the Ace of Spades are a pair. The number of pairs contained in a hand, three or four of a kinds have no bearing on the result. If none of the five hands contains a pair, or two hands contain the same highest pair, the game is considered drawn.
Although traditional poker has the Ace card being a turning point, that is it
can be the low card or the high card, the cards in this game have a fixed order,
as described in Table 3. This means that Aces are low and can be beaten by
any other pair.
You should develop a program that implements this game. Additionally you should print each of the hands sorted in order of value, print the number of pairs in each hand and if there is at least 1 pair print the value of the highest pair. Once all five hands have been printed you should indicate if there was a winner and the value of the pair that won. If there was no winner you should indicate that the game was drawn. See Figures 1 & 2 for some sample output.
Your hands should be stored in an array for ease of use and when sorting the hand you should investigate the C standard library function qsort(), which might make things easier for you.
Now, the Solution:
While working in bit fields, first thing you need to do is figure out all the ranges, manipulation and comparisons that you are going to make. After that coding would be as smooth as knife in butter. So, lets do that.
Ranges of each deck:
(0000 0001)2 - Ace of Hearts
(0001 1001)2 - King of Hearts
(0010 0001)2 - Ace of Diamonds
(0011 1001)2 - King of Diamonds
(0100 0000)2 - Ace of Clubs
(0101 1000)2 - King of Clubs
(0110 0000)2 - Ace of Spades
(0111 1000)2 - King of Spades
Now, let us take it easy assume that deck is already populated. Let's go to printing. We need to print three things - card value (as given in array value), card suit (as given in array suit) and colour (as given in array colour).
1. How to get card value from typedef card? -> Card value represented is represented by 1st, 2nd, 3rd and 4th byte (xxx0000x to xxx1100x). So, shift once to right, which removes the colour bit. Then bitwise & with 0x0F ( makes higher nibble zero). Now the values will be in range 0x00 to 0x0C. Take the values as index of card array. Here is how: values[ ( (card>>1) & 0x0F ) ].
2. How to get suit value from typedef card ? -> Deck value is represented by 5th and 6th byte. So, shift right by 5 bytes, then bitwise & with 0x03 (makes all other bits zero other than 0 and 1). Now the values will be 0x00 to 0x03. Use this values as index of suit array. Here is how: suits[ ( (c>>5) & 0x03 ) ]
3. How to get colour value from typedef card ? -> colour[ c & 0x01 ]
Now that we have some idea about these bitfields, lets populate the deck. Take a temporary variable 'a'. Incrementing it by one till 0x0C (0b00001100 - least significant nibble is value of king) will fill up the card values. To change the deck once 0x0C is reached, we just increment it by 3, so the result will be 0x10 (0b00010000 - the suit has been changed). o check the colour of card compare the deck values, that is bit 4 and 5 of temporary variable 'a', if value is 0x00 - Hearts, 0x10 - Diamonds. These two are colour red. So, LSB needs to be 1. So we shift 'a' left by one position and set the LSB. If the values are 0x20 - Clubs, 0x30 - Spades. These two are colour black. So we shift 'a' left by 1 position and reset LSB.
Code snippet:
You should develop a program that implements this game. Additionally you should print each of the hands sorted in order of value, print the number of pairs in each hand and if there is at least 1 pair print the value of the highest pair. Once all five hands have been printed you should indicate if there was a winner and the value of the pair that won. If there was no winner you should indicate that the game was drawn. See Figures 1 & 2 for some sample output.
Your hands should be stored in an array for ease of use and when sorting the hand you should investigate the C standard library function qsort(), which might make things easier for you.
Now, the Solution:
While working in bit fields, first thing you need to do is figure out all the ranges, manipulation and comparisons that you are going to make. After that coding would be as smooth as knife in butter. So, lets do that.
Ranges of each deck:
(0000 0001)2 - Ace of Hearts
(0001 1001)2 - King of Hearts
(0010 0001)2 - Ace of Diamonds
(0011 1001)2 - King of Diamonds
(0100 0000)2 - Ace of Clubs
(0101 1000)2 - King of Clubs
(0110 0000)2 - Ace of Spades
(0111 1000)2 - King of Spades
Now, let us take it easy assume that deck is already populated. Let's go to printing. We need to print three things - card value (as given in array value), card suit (as given in array suit) and colour (as given in array colour).
1. How to get card value from typedef card? -> Card value represented is represented by 1st, 2nd, 3rd and 4th byte (xxx0000x to xxx1100x). So, shift once to right, which removes the colour bit. Then bitwise & with 0x0F ( makes higher nibble zero). Now the values will be in range 0x00 to 0x0C. Take the values as index of card array. Here is how: values[ ( (card>>1) & 0x0F ) ].
2. How to get suit value from typedef card ? -> Deck value is represented by 5th and 6th byte. So, shift right by 5 bytes, then bitwise & with 0x03 (makes all other bits zero other than 0 and 1). Now the values will be 0x00 to 0x03. Use this values as index of suit array. Here is how: suits[ ( (c>>5) & 0x03 ) ]
3. How to get colour value from typedef card ? -> colour[ c & 0x01 ]
Now that we have some idea about these bitfields, lets populate the deck. Take a temporary variable 'a'. Incrementing it by one till 0x0C (0b00001100 - least significant nibble is value of king) will fill up the card values. To change the deck once 0x0C is reached, we just increment it by 3, so the result will be 0x10 (0b00010000 - the suit has been changed). o check the colour of card compare the deck values, that is bit 4 and 5 of temporary variable 'a', if value is 0x00 - Hearts, 0x10 - Diamonds. These two are colour red. So, LSB needs to be 1. So we shift 'a' left by one position and set the LSB. If the values are 0x20 - Clubs, 0x30 - Spades. These two are colour black. So we shift 'a' left by 1 position and reset LSB.
Code snippet:
char a = 0;
for (int i = 0; i<52 ; i++)
{
if ((a & 0x30) == 0x00 || (a & 0x30) == 0x10){
deck[i] = (a << 1) | 0x01;
}
if ((a & 0x30) == 0x20 || (a & 0x30) == 0x30){
deck[i] = (a << 1) & 0xFE;
}
a++;
if( (a & 0x0D) == 0x0D)
a = a+3;
}
}
Rest of the things: Shuffle, finding pairs, finding winning pair are pretty self explanatory.
Here is the link of code.
Comments are welcome. If there are any difficulties in understanding the code, comment. I will update the post.
This comment has been removed by the author.
ReplyDelete