[CC150v5] 8.1 Design a Generic Deck of Cards - Shuatiblog.com
ow to design Black Jack?
主题从player角度出发,core object有hand, board, deck, suit等,use cases有Initialization, Play, Checkout, Shuffle(喜欢考算法)。
https://tianrunhe.wordpress.com/2012/03/18/design-the-data-structure-of-a-deck-of-cards/
The structure is clear here: a deck contains four suits and a suit contains 13 card. Each card has a numerical value from 1 to 13. If you think about a card game, different games differ from ways of dealing cards and putting cards back in. So we can have a set of abstract methods inside the class ‘Deck’ to allow sub-class implements its own way of dealing.
https://epicfei.wordpress.com/2013/08/10/7-1-design-the-data-structures-for-a-generic-deck-of-cards-explain-how-you-would-sub-class-it-to-implement-particular-card-games/
https://xmruibi.gitbooks.io/interview-preparation-notes/content/OOD/DesignExamples/DeckOfCard.html
http://math.hws.edu/eck/cs124/javanotes6/c5/s4.html
http://www.mathcs.emory.edu/~cheung/Courses/170/Syllabus/10/deck-of-cards.html
Card, Hand, Deck
https://www.nowtoshare.com/zh/Article/Index/70566
Read full article from [CC150v5] 8.1 Design a Generic Deck of Cards - Shuatiblog.com
Design a Generic Deck of Cards
在职刷题 + System Design + 面试准备的路上
ow to design Black Jack?
主题从player角度出发,core object有hand, board, deck, suit等,use cases有Initialization, Play, Checkout, Shuffle(喜欢考算法)。
https://tianrunhe.wordpress.com/2012/03/18/design-the-data-structure-of-a-deck-of-cards/
The structure is clear here: a deck contains four suits and a suit contains 13 card. Each card has a numerical value from 1 to 13. If you think about a card game, different games differ from ways of dealing cards and putting cards back in. So we can have a set of abstract methods inside the class ‘Deck’ to allow sub-class implements its own way of dealing.
enum Suit {
HEART, DIAMOND, SPADES, CLUBS;
}
class Deck<T extends Card> {
List<Card> deck;
public void shuffle() {
};
}
abstract class Card {
boolean available;
Suit suit;
int num; //???
public boolean isAvailable() {
return available;
};
}
class Hand<T extends Card> {
List<Card> cards;
public int score() {
int score = 0;
for (Card c : cards) {
score += c.num;
}
return score;
}
public void addCard(T card) {
cards.add(card);
}
}
// Now use the above generic Data Structure to make a
// Blackjack Game
class Blackjack extends Hand<BlackJackCard> {
}
class BlackJackCard extends Card {
}
https://epicfei.wordpress.com/2013/08/10/7-1-design-the-data-structures-for-a-generic-deck-of-cards-explain-how-you-would-sub-class-it-to-implement-particular-card-games/
namespace
SUIT
{
enum
Enum
{
SPADE,
HEART,
CLUB,
DIAMOND
};
};
class
Card
{
private
:
SUIT::Enum s;
int
v;
public
:
virtual
SUIT::Enum suit()
const
{
return
s;
};
virtual
int
val()
const
{
return
v;
};
Card(
int
val, SUIT::Enum suit):s(suit), v(val){};
};
/*
Just remember and practise the paradigm of inheritance
*/
class
BlackJackCard :
public
Card
{
public
:
virtual
int
val()
{
int
v = Card::val();
if
(v < 10)
return
v;
return
10;
}
BlackJackCard(
int
val, SUIT::Enum suit):Card(val, suit){};
};
class
player
{
private
:
int
id;
int
bet;
set<
int
> points;
vector<BlackJackCard *> bjcs;
bool
addPoint(set<
int
>& points, BlackJackCard* card)
{
if
(points.empty())
{
points.insert(card->val());
if
(card->val() == 1)
points.insert(11);
}
else
{
/*
set elements are ALWAYS CONST, they can't be modified once inserted.
*/
set<
int
> tmp;
for
(set<
int
>::iterator it = points.begin(); it != points.end(); ++ it)
{
tmp.insert(*it + card->val());
if
(card->val() == 1)
tmp.insert(*it + 11);
}
points = tmp;
}
}
void
getPoints()
{
cout <<
"You All Possible Points : "
<< endl;
for
(set<
int
>::iterator it = points.begin(); it != points.end(); ++ it)
{
cout << *it << endl;
}
};
int
getMinPoints()
{
/*
set is implemented by commonly BST, so eles are in order!!!
learn to use lower_bound() and upper_bound()
"they allow the direct iteration on subsets based on their order."
which gives us another option to find min. preferable
*/
//return *(points.lower_bound(0));
return
*(points.begin());
};
void
printCards()
{
cout <<
"You Cards : "
<< endl;
for
(vector<BlackJackCard *>::iterator it = bjcs.begin(); it != bjcs.end(); ++ it)
{
cout << (*it)->val() << endl;
}
}
public
:
player(
int
i,
int
j):id(i),bet(j)
{
bjcs.push_back(
new
BlackJackCard(
rand
() % 13 + 1, SUIT::SPADE));
bjcs.push_back(
new
BlackJackCard(
rand
() % 13 + 1, SUIT::SPADE));
addPoint(points, bjcs[0]);
addPoint(points, bjcs[1]);
};
void
getAnotherCard()
{
for
(set<
int
>::iterator it = points.begin(); it != points.end(); ++ it)
{
/*
predefined strategy for the player
*/
if
(*it <= 21 && 21 - *it <= 4)
{
printCards();
getPoints();
cout <<
"Stand"
<< endl;
exit
(1);
}
}
bjcs.push_back(
new
BlackJackCard(
rand
() % 13 + 1, SUIT::SPADE));
addPoint(points, bjcs.back());
if
(getMinPoints() > 21)
{
printCards();
getPoints();
cout <<
"Busted"
<< endl;
exit
(2);
}
};
};
- enum 类型不支持 public 和 protected 修饰符的构造方法,因此构造函数一定要是 private 或 friendly 的。也正因为如此,所以枚举对象是无法在程序中通过直接调用其构造方法来初始化的。
- 定义 enum 类型时候,如果是简单类型 (No more constructor),那么最后一个枚举值后不用跟任何一个符号;但如果有定制方法,那么最后一个枚举值与后面代码要用分号';'隔开,不能用逗号或空格。
- 由于 enum 类型的值实际上是通过运行期构造出对象来表示的,所以在 cluster 环境下,每个虚拟机都会构造出一个同义的枚举对象。因而在做比较操作时候就需要注意,如果直接通过使用等号 ( ‘ == ’ ) 操作符,这些看似一样的枚举值一定不相等,因为这不是同一个对象实例。
class Card {
// Define the Suit by Enum type
public enum Suit {
CLUBS(1), SPADE(2), HEART(3), DIAMOND(4);
int value;
private Suit(int val) {
this.value = val;
}
}
// Card has suit and value, only two kind of data need to store
int val;
Suit suit;
public Card(int value, Suit suit) {
this.val = value;
this.suit = suit;
}
public int getVal(){
return this.val;
}
public Suit getSuit(){
return this.suit;
}
}
BlackJack
- Face cards (kings, queens, and jacks) are counted as ten points.
- Ace can be counted as 1 point or 11 points
- Other cards with value less than ten should be counted as what it values.
class BlackJack extends Card{
public BlackJack(int val, Suit suit) {
super(val, suit);
}
@Override
public int getVal(){
int value = super.getVal();
if(value < 10)
return value;
else if(value == 1)
return 11;
return 10;
}
public boolean isAce(){
return super.getVal() == 1;
}
}
http://fenghaolw.blogspot.com/2014/01/cc150-chapter-8-object-oriented-design.html?view=sidebarhttp://math.hws.edu/eck/cs124/javanotes6/c5/s4.html
http://www.mathcs.emory.edu/~cheung/Courses/170/Syllabus/10/deck-of-cards.html
public class DeckOfCards
{
public static final int NCARDS = 52;
private Card[] deckOfCards; // Contains all 52 cards
private int currentCard; // deal THIS card in deck
public DeckOfCards( ) // Constructor
{
deckOfCards = new Card[ NCARDS ];
int i = 0;
for ( int suit = Card.SPADE; suit <= Card.DIAMOND; suit++ )
for ( int rank = 1; rank <= 13; rank++ )
deckOfCards[i++] = new Card(suit, rank);
currentCard = 0;
}
/* ---------------------------------
shuffle(n): shuffle the deck
--------------------------------- */
public void shuffle(int n)
{
int i, j, k;
for ( k = 0; k < n; k++ )
{
i = (int) ( NCARDS * Math.random() ); // Pick 2 random cards
j = (int) ( NCARDS * Math.random() ); // in the deck
/* ---------------------------------
swap these randomly picked cards
--------------------------------- */
Card tmp = deckOfCards[i];
deckOfCards[i] = deckOfCards[j];
deckOfCards[j] = tmp;;
}
currentCard = 0; // Reset current card to deal
}
/* -------------------------------------------
deal(): deal deckOfCards[currentCard] out
------------------------------------------- */
public Card deal()
{
if ( currentCard < NCARDS )
{
return ( deckOfCards[ currentCard++ ] );
}
else
{
System.out.println("Out of cards error");
return ( null ); // Error;
}
}
public String toString()
{
String s = "";
int k;
k = 0;
for ( int i = 0; i < 4; i++ )
{
for ( int j = 1; j <= 13; j++ )
s += (deckOfCards[k++] + " ");
s += "\n";
}
return ( s );
}
}
|
Card, Hand, Deck
https://www.nowtoshare.com/zh/Article/Index/70566
Read full article from [CC150v5] 8.1 Design a Generic Deck of Cards - Shuatiblog.com