How is my BlackJack game design?

up vote7down votefavorite

This is a command line BlackJack game created in Java as my final project for an advanced programming class.

  • What do you think about it?
  • Have I used OOP correctly?
  • What grade should I get for this? :D
  • Any concept in game that could be improved?

I used JRE 1.7. And to make Unicode characters work you must use Unicode in Eclipse.

This is my Class Diagram:

BlackJack.java

import java.io.*;public class BlackJack
{private static int BLACKJACK = 21;private static int DECKSIZE = 52;private static boolean isPlayerDone;public static void main(String[] args) throws IOException {Deck deck = null;Hand playersHand = null;Hand splitHand = null;Hand dealersHand = null;System.out.println("--------------------------------------------------------"); System.out.println("-               BLACK               JACK               -");System.out.println("--------------------------------------------------------\n"); boolean runGame = true;while(runGame)switch(options()){case "deal":dealersHand = new Hand("Dealer");playersHand = new Hand("Player");splitHand = null;isPlayerDone = false;deck = initialDraw(deck, playersHand, splitHand, dealersHand);if (playersHand.getHandTotal() == BLACKJACK){System.out.print("Player has BLACKJACK!\n\n");isPlayerDone = true;System.out.print("Dealer uncovers card...\n\n");showHands(playersHand, splitHand, dealersHand);System.out.print("Dealer's move...\n\n");deck = dealerDraw(deck, playersHand, splitHand, dealersHand);showHands(playersHand, splitHand, dealersHand);compareHands(playersHand, splitHand, dealersHand);} // end if()break; // end case "deal"case "hit":if(!isPlayerDone)deck = hit(deck, playersHand, splitHand, dealersHand);elseSystem.out.print("You must deal cards first!\n\n");break; // end case "hit"case "stand":if(!isPlayerDone){isPlayerDone = true;deck = stand(deck, playersHand, splitHand, dealersHand);} // end if()elseSystem.out.print("You must deal cards first!\n\n");break; // end case "stand"case "split":if(!isPlayerDone)splitHand = split(playersHand, splitHand, dealersHand);elseSystem.out.print("You must deal cards first!\n\n");break; // end case "split"case "exit":runGame = false;System.out.print("Game ended.\n\n");break; // end case "exit"default:System.out.print("Invalid entry\n\n");} // end switch()} // end main()private static Hand split(Hand player, Hand split, Hand dealer){if(player == null)System.out.print("You must deal cards first!\n\n");else if(player.getHandSize() == 2 && player.bothEqual()){split = new Hand("Player");split.insert(player.deleteFirst());showHands(player, split, dealer);compareHands(player, split, dealer);} // end else if()else if(!player.bothEqual())System.out.print("Both card values must be the same!\n\n");elseSystem.out.print("You must have no more than 2 cards to split!\n\n");return split;} // end split()private static Deck stand(Deck deck, Hand player, Hand split, Hand dealer){if(player == null)System.out.print("You must deal cards first!\n\n");else{   isPlayerDone = true;System.out.print("Dealer uncovers card...\n\n");showHands(player, split, dealer);System.out.print("Dealer's move...\n\n");deck = dealerDraw(deck, player, split, dealer);showHands(player, split, dealer);compareHands(player, split, dealer);} // end elsereturn deck;} // end stay()private static Deck hit(Deck deck, Hand player, Hand split, Hand dealer){if(player == null)System.out.print("You must deal cards first!\n\n");else{       deck = drawFromDeck(deck, player);System.out.print("\n");if(split != null){deck = drawFromDeck(deck, split);System.out.print("\n");} // end if()showHands(player, split, dealer);compareHands(player, split, dealer);if (player.getHandTotal() == BLACKJACK){System.out.print("Player has BLACKJACK!\n\n");isPlayerDone = true;System.out.print("Dealer uncovers card...\n\n");showHands(player, split, dealer);System.out.print("Dealer's move...\n\n");deck = dealerDraw(deck, player, split, dealer);showHands(player, split, dealer);compareHands(player, split, dealer);} // end if()else if(player.getHandTotal() > BLACKJACK){System.out.print("Player Busted!\n\n");isPlayerDone = true;System.out.print("Dealer uncovers card...\n\n");showHands(player, split, dealer);compareHands(player, split, dealer);}} // end elsereturn deck;} // end hit()private static Deck dealerDraw(Deck deck, Hand player, Hand split, Hand dealer){if(player.getHandTotal() <= BLACKJACK){// Dealer takes a precaution and only draws // if hand total is less than or equal to 16.while(dealer.getHandTotal() <= 16 && (dealer.getHandTotal() <= player.getHandTotal() || (split != null  && dealer.getHandTotal() <= split.getHandTotal())))deck = drawFromDeck(deck, dealer);// Player has reached BLACKJACK!// There's no or little chance to win, // dealer risks and draws even if total is high.if (player.getHandTotal() == BLACKJACK || (split != null  && split.getHandTotal() == BLACKJACK))while(dealer.getHandTotal() < BLACKJACK)deck = drawFromDeck(deck, dealer);} // end if()return deck;} // dealerDraw()private static Deck drawFromDeck(Deck deck, Hand hand){deck = checkDeck(deck);Card temp = new Card(deck.pop());if (hand.getName().equals("Dealer") && !isPlayerDone){if(hand.getHandSize() < 1)System.out.print("Drawing Dealer's card... X_X");elseSystem.out.print("Drawing Dealer's card... " + temp.toString());} // end if()else{if(hand.getName().equals("Dealer"))System.out.print("Drawing Dealer's card... " + temp.toString() + "\n");elseSystem.out.print("Drawing Player's card... " + temp.toString());} // end elseSystem.out.print("\n");hand.insert(temp);return deck;} // end drawFromDeck()private static void compareHands(Hand player, Hand split, Hand dealer){if (isPlayerDone){if(player.getHandTotal() > BLACKJACK || (split != null && split.getHandTotal() > BLACKJACK)){System.out.print("Player Busted!\n");if(dealer.getHandTotal() <= BLACKJACK)System.out.print("Dealer Wins!\n\n");} // end if()else if(dealer.getHandTotal() > BLACKJACK){System.out.print("Dealer Busted!\n");if(player.getHandTotal() <= BLACKJACK || (split != null && split.getHandTotal() <= BLACKJACK))System.out.print("Player Wins!\n\n");} // end else if()else if(dealer.getHandTotal() > BLACKJACK && (player.getHandTotal() > BLACKJACK || (split != null && split.getHandTotal() > BLACKJACK))){System.out.print("Both Busted!\n");} // end else if()else{if((player.getHandTotal() > dealer.getHandTotal() && player.getHandTotal() <= BLACKJACK) || (split != null && (split.getHandTotal() > dealer.getHandTotal() && player.getHandTotal() <= BLACKJACK)))System.out.print("Player Wins!\n\n");else if((player.getHandTotal() < dealer.getHandTotal() && dealer.getHandTotal() <= BLACKJACK) || (split != null && (split.getHandTotal() < dealer.getHandTotal() && dealer.getHandTotal() <= BLACKJACK)))System.out.print("Dealer Wins!\n\n");if(player.getHandTotal() == BLACKJACK || (split != null && split.getHandTotal() == BLACKJACK))System.out.print("Player has BLACKJACK!\n\n");if(dealer.getHandTotal() == BLACKJACK)System.out.print("Dealer has BLACKJACK!\n\n");} // end else} // end if()} // end compareHands()private static Deck checkDeck(Deck deck){if(deck == null)deck = createDeck();else if(deck.isEmpty()){System.out.print("\nDeck is empty! You must create and shuffle new deck of cards!\n\n");deck = createDeck();} // end else if()return deck;} // end checkDeck()private static Deck createDeck(){System.out.println("Creating deck...");Deck deck = new Deck(DECKSIZE);deck.createDeck();System.out.println("Shuffling deck...");deck.shuffleDeck();System.out.print("\n");return deck;} // end createDeck()private static Deck initialDraw(Deck deck, Hand player, Hand split, Hand dealer){deck = drawFromDeck(deck, player);deck = drawFromDeck(deck, dealer);deck = drawFromDeck(deck, player);deck = drawFromDeck(deck, dealer);System.out.print("\n");showHands(player, split, dealer);compareHands(player, split, dealer);return deck;} // end initialDraw()private static void showHands(Hand player, Hand split, Hand dealer){System.out.print("Dealers Hand:");if(!isPlayerDone){dealer.peek();System.out.print(" X_X = " + dealer.peekValue() + "\n");} // end if()else{dealer.displayHand();System.out.print(" = " + (dealer.getHandTotal() == BLACKJACK ? dealer.getHandTotal() + " : BLACKJACK!" : ((dealer.getHandTotal() > BLACKJACK) ? dealer.getHandTotal() + " : BUSTED!" : dealer.getHandTotal())) + "\n");} // end elseSystem.out.print("Players Hand:");player.displayHand();System.out.print(" = " + (player.getHandTotal() == BLACKJACK ? player.getHandTotal() + " : BLACKJACK!" : ((player.getHandTotal() > BLACKJACK) ? player.getHandTotal() + " : BUSTED!" : player.getHandTotal())) + "\n");if (split != null){System.out.print("Players Hand:");split.displayHand();System.out.print(" = " + (split.getHandTotal() == BLACKJACK ? split.getHandTotal() + " : BLACKJACK!" : ((split.getHandTotal() > BLACKJACK) ? split.getHandTotal() + " : BUSTED!" : split.getHandTotal())) + "\n\n");} // end if()elseSystem.out.print("\n");} // end showHands()private static String options() throws IOException{System.out.print("deal, hit, split, stand, exit: ");InputStreamReader isr = new InputStreamReader(System.in);BufferedReader br = new BufferedReader(isr);String s = br.readLine();System.out.print("\n"); return s;} // end options()
} // end BlackJack

Hand.java

class Hand
{private Card first;private int cardTotal;private String name;private int handSize;public Hand(String name){first = null;this.name = name;cardTotal = 0;handSize = 0;} // end Hand()public void insert(Card card){Card newLink = new Card(card);newLink.next = first;if (card.getRank() == 1 && cardTotal + card.getValue() > 21)cardTotal = cardTotal + (card.getValue() - 10);elsecardTotal = cardTotal + card.getValue();handSize = handSize + 1;first = newLink;} // end insert()public Card deleteFirst(){Card temp = first;first = first.next;cardTotal = cardTotal - temp.getValue();handSize = handSize - 1;return temp;} // end deleteFirst()public void displayHand(){Card current = first;while(current != null){current.showCard();current = current.next;} // end while()} // end displayHand()public boolean isEmpty(){return first == null;} // end isEmpty()public boolean bothEqual(){Card temp = first;return temp != null && (temp.getValue() == temp.next.getValue());} // end bothEqual()public void peek(){first.showCard();} // end peek()public int peekValue(){return first.getValue();} // end peekValue()public int getHandSize(){return handSize;} // end getHandSize()public String getName(){return name;} // end getName()public int getHandTotal(){return cardTotal;} // end getHandTotal()
} // end Hand

Deck.java

class Deck
{private int maxSize;private Card[] stackArray;private int top;public Deck(int s){maxSize = s;stackArray = new Card[maxSize];top = -1;} // end Deck()private void push(Card card){stackArray[++top] = new Card(card);} // end push()public Card pop(){return stackArray[top--];} // end pop()public boolean isEmpty(){return top == -1;} // end isEmpty()public void shuffleDeck(){Card swap;for (int i = 0; i < stackArray.length; i++) {int r = i + (int) (Math.random() * (stackArray.length - i));swap = stackArray[i];stackArray[i] = stackArray[r];stackArray[r] = swap;} // end for()} // end shuffleDeck()public void createDeck(){String[] suit = {"\u2663", "\u2666", "\u2665", "\u2660"};int[] rank = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};for (int i = 0; i < rank.length; i ++){for (int j = 0; j < suit.length; j++){push(new Card(suit[j], rank[i]));} // end for()} // end for()} // end createDeck()
} // end Deck

Card.java

class Card
{public Card next;private String suit;private int rank;Card(String suit, int rank){this.suit = suit;this.rank = rank;} // end Card()Card(Card card){suit = card.suit;rank = card.rank;} // end Card()private String getRankName(){if (rank == 1)return "A";else if (rank == 11)return "J";else if (rank == 12)return "Q";else if (rank == 13)return "K";elsereturn String.valueOf(rank);} // end getRankName()public int getValue(){if (rank == 1)return 11;else if (rank == 11 || rank == 12 || rank == 13)return 10;return rank;} // end getValue()public String getSuit(){return suit;} // end getSuit()public int getRank(){return rank;} // end getRank()public void showCard(){System.out.print(" " + getRankName() + "_" + suit);} // end showCard()@Overridepublic String toString(){return getRankName() + "_" + suit;} // end toString()
} // end Card

java oop game playing-cards
shareimprove this question
edited Jan 5 '14 at 22:08
Jamal♦

27.4k9102205

asked Dec 19 '12 at 0:55
HelpNeeder

391420

 
3  
If you ever have a class with only static methods, it is should only be a Utility class (such as for static operations, extracting variables etc). This class is not OO! – Tom Cammann Dec 19 '12 at 18:58
 
what happens if you draw an ace, then a 2, then a 10? (you are supposed to be at 13, but apparently your Hand.insert method puts you at 23, it does not appear to keep track of previous aces.) – njzk2Jan 21 '15 at 14:42
 
Njzk2, you are right. Never had a time to do this part. – HelpNeeder Jan 21 '15 at 16:22
 
I guess, we could solve this problem by checking the hands after each turn and do compare of the total with both upper and lower bound value of the aces. – HelpNeeder Jan 21 '15 at 16:24
add a comment

2 Answers

activeoldestvotes

up vote8down voteaccepted

+50

A few notes:

  1. I don't think you're utilizing OOP to its full potential in your BlackJack class; all its methods are static and you're passing around too many variables. A cleaner alternative would be to make deckplayersHandsplitHand, and dealersHand class-level variables, change the methods to be non-static, and then you won't have to pass them all around. So something like this:

    public class BlackJack {...private Deck deck;private Hand splitHand;private Hand playersHand;private Hand dealersHand;private boolean isPlayerDone;public static void main(String[] args) throws IOException {BlackJack blackjack = new BlackJack();blackjack.start();}public void start() {while(runGame) {switch(options()) {case "deal":deal();break;case "hit":hit();break;case "stand":stand();break;...}}}public void deal() {playersHand = new Hand("Player");dealersHand = new Hand("Dealer");splitHand = null;isPlayerDone = false;...}...}
  2. The Hand class doesn't really need a name because there are only 2 types of hands: dealer and player. So you can just pass in a boolean for drawFromDeck():

    private Deck drawFromDeck(boolean drawForPlayer) {Hand hand = drawForPlayer ? playersHand: dealersHand;...
    }
  3. You have several different places where you're checking for blackjack, and I can't easily follow the logic. compareHands() checks for blackjack, but there are a couple other places with some checks too. These might be necessary (I don't know the rules of Blackjack that well), but you should try to minimize duplicate logic as much as possible. For example, this block of code is in both main() and hit():

    if (player.getHandTotal() == BLACKJACK)
    {System.out.print("Player has BLACKJACK!\n\n");isPlayerDone = true;System.out.print("Dealer uncovers card...\n\n");showHands(player, split, dealer);System.out.print("Dealer's move...\n\n");deck = dealerDraw(deck, player, split, dealer);showHands(player, split, dealer);compareHands(player, split, dealer);
    } // end if()

I think fixing those (mostly points 1 & 3) would go a long way to making the code easier to read and maintain. I skimmed over your other classes and they seemed fine at a glance, having good separation of concerns.

shareimprove this answer
answered Dec 19 '12 at 4:32
seand

2,37711129

 
 
Thanks for yourr feedback. I was wondering with con/pros for global class variables but then decided to try to have as little global variables as possible. I know they would have reduced amount of variables. Overall I guess you are right with your comments. Thanks. – HelpNeeder Dec 19 '12 at 21:35
 
@HelpNeeder: is there anything else you wanted me to critique specifically or are you just looking for other opinions? – seand Dec 21 '12 at 15:19
add a comment
up vote3down vote

Some remarks:

  1. Your main method is HUGE, consider splitting it
  2. This code:

    deck = drawFromDeck(deck, player);
    deck = drawFromDeck(deck, dealer);
    deck = drawFromDeck(deck, player);
    deck = drawFromDeck(deck, dealer);

    can be reduced to this:

    for(int i = 0; i < 4; i++)deck = drawFromDeck(deck, dealer);
  3. This code:

    System.out.print(" = " + (player.getHandTotal() == BLACKJACK ? player.getHandTotal() + " : BLACKJACK!" : ((player.getHandTotal() > BLACKJACK) ? player.getHandTotal() + " : BUSTED!" : player.getHandTotal())) + "\n");

    is duplicated the lines below, you can create a method that accepts an Hand and does its calculations

  4. getRankName() in Card.java could be rewritten more cleanly with a switch
shareimprove this answer
answered Dec 25 '12 at 18:52
miniBill

32619

 
1  
#2, how would you rewrite this? I mean first we must draw player's card, then dealer's, then player's, then dealer's. The for loop does not do this... – HelpNeeder Dec 25 '12 at 22:33
2  
#2 could be done like so (typed without a compiler): for(hand : new Hand[]{player,dealer,player,dealer}) deck = drawFromDeck(deck,hand); . Not sure if that is actually better. – Brian Dec 26 '12 at 18:26 
 
@HelpNeeder oh, I'm sorry, I misread that code :| – miniBill Dec 26 '12 at 19:25
1  
@Brian, this is interesting. I never used an array within for loop like you did. Thanks. But I wouldn't do this, in this situation, like this because it's unnecessary to allocate more memory space for such array. – HelpNeeder Dec 26 '12 at 22:17 

OOD - blackjack design相关推荐

  1. java中OOA,OOT, OOP, OOD, OOSM,OOM英文表示的含义是什么?

    2019独角兽企业重金招聘Python工程师标准>>> OOA - Object-Oriented Analysis(面向对象分析) OOT - Object-Oriented Te ...

  2. java ooa和ood_OOA,OOD,OOP区别

    定义: OOA(Object-Oriented Analysis,面向对象分析方法) OOD(Object-Oriented Design,面向对象设计) OOP(Object Oriented Pr ...

  3. OOA、OOD、OOP详解

    oo(object-oriented):基于对象概念,以对象为中心,以类和继承为构造机制,来认识,理解,刻画客观世界和设计,构建相应的软件系统的一门方法;本意----模拟人类的思维方式,使开发,维护, ...

  4. 理清那么多个OO(面向对象)

    OOA - Object-Oriented Analysis(面向对象分析) OOT - Object-Oriented Testing (面向对象测试) OOP - Object-Oriented ...

  5. 我们是如何拿下Google和Facebook Offer的?

    http://posts.careerengine.us/p/57c3a1c1a09633ee7e57803c 大家好,我是小高,CMU CS Master,来Offer第一期学员,2014年初在孙老 ...

  6. activexobject对象不能创建_面向对象设计方法(Object oriented)

    1.面向对象 (1)OOA(Object-oriented Analysis) 面向对象分析--事物的分类.命名.描述. (2)OOD(Object-oriented Design) 面向对象设计-- ...

  7. python 继承的规则

    本文讲述python继承规则. 先来看一些概念: 面向对象的概念 简单地说 面向对象编程(Object Oriented Programming)简称OOP 就是使我们分析.设计 和实现一个系统的方法 ...

  8. 常见笔试面试问题点(转载)

    原文: java各种概念 Core Java总结 Base: OOA是什么?OOD是什么?OOP是什么?{ oo(object-oriented):基于对象概念,以对象为中心,以类和继承为构造机制,来 ...

  9. 设计模式:依赖倒置原则

    依赖倒置原则定义 依赖倒置原则(Dependence Inversion Principle ,DIP)定义如下: High level modules should not depend upon ...

最新文章

  1. 中国航发牵手阿里云共同打造:航空新引擎
  2. java jar log4j_java项目打包成可执行jar用log4j将日志写在jar所在目录操作
  3. No module named pycurl(无法使用yum和pip的情况下的解决方案)
  4. linux之在当前目录下删除不包含aa的文件
  5. C#获取文件夹及文件的大小与占用空间的方法
  6. 通过yum下载rpm包
  7. 申请一个公网ip多少钱_申请1个条形码多少钱?小作坊如何申请条形码?
  8. Vuex的API文档
  9. 专家系统是一种智能计算机软件系统,人工智能习题答案-第6篇-专家系统.pdf
  10. 电脑连接安卓手机摄像头的方法(含DroidCam安装包及简明使用教程)
  11. ZZNUOJ_C语言1007:鸡兔同笼(完整代码)
  12. java根据距离算经纬度_java 根据两点经纬度来算距离
  13. linux终端联网网速慢,解决ubuntu 上网速度慢的问题
  14. 陆正耀旗下宝沃汽车申请破产:无力清偿到期债务 资金链断裂
  15. 记录一款绿色便携的sqlist3数据库编辑工具SQLiteSpy
  16. Defcon - 2015 - 初赛 - r0pbaby writeup
  17. 一篇文章读懂NHTSA自动驾驶分级(转)
  18. 怎么压缩PDF文件大小?分享几个压缩文件的方法
  19. spyder 设置中文_Spyder代理设置
  20. rocketMQ 删除过期文件(磁盘空间不足导致mq消息发送不了)

热门文章

  1. [数据结构笔记] 最优二叉树
  2. go开发linux下桌面程序,使用FMXlinux 开发linux 桌面应用-Go语言中文社区
  3. java面试宝典备份
  4. 【转载】初学者进阶教程:闪讯实例介绍Cocoa多线程, 系统网络设置自定义
  5. 工行银企互联接入详解(2)--下载证书
  6. 一个收到微信小程序内测的号,竟然300万起拍卖
  7. 将32位4通道的tif遥感图片转化为8位4通道
  8. 音箱箱体的分类(二)
  9. 基于ssm的零食商城的设计与实现
  10. 35岁的前端开发工程师,未来路在何方?