控制台版21点(BlackJack)源码(Java2游戏编程第4章练习参考答案)

来源:互联网 发布:hashmap java 编辑:程序博客网 时间:2024/05/22 19:26

/*
 * BlackJack.java
 *
 * 创建时间 2006年12月27日, 上午10:08
 *
 * 版本0.0.1
 * BlackJack(21点)游戏的主类,完全绝大部分游戏控制(控制台版)
 */

package blackjack;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;

/**
 *
 * @author mouyong1973
 */
public class BlackJack {
    private Player player,com;//玩家和电脑
    private Deck deck;//一副牌
    BufferedReader br;
    /**
     * 打印菜单
     * 完成所有功能调用
     */
    public BlackJack() {
        //初始化玩家,牌
        player=new Player();
        com=new Player();
        deck=new Deck();
        String str = null;
        br=new BufferedReader(new InputStreamReader(System.in));
       
        //打印菜单
        while(true){
            player.playAgain();
            com.playAgain();
            System.out.println("/t/t默  然  黑  杰  克/n");
            System.out.println("/t/t制作:默然说话工作室/n");
            System.out.println("/t/t    1.开始游戏/n");
            System.out.println("/t/t    2.查看比分/n");
            System.out.println("/t/t    3.结束游戏/n");
            System.out.println("/t请输入");
            try {
                str=br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            switch(Integer.parseInt(str)){
                case 1:
                    start();
                    break;
                case 2:
                    checkScore();
                    break;
                case 3:
                    System.exit(0);
                    break;
                default:
                    System.out.println("输入有误,请重新输入");
                    break;
                  
            }
        }
    }
   
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       new BlackJack();
    }
   
    //游戏开始,完成初始金额的投注及发第一张牌
    //然后用户选择是投注加倍金额,发下一张牌,还是PASS,或者开牌
    private void start() {
        //初始化金额为20货币单位
        int money=20;//投注金额
        int yourChoice;//用户选择
        System.out.println("请选择你要投注的金额(最低20货币单位):");
        //用户输入下注金额
        try {
            money=Integer.parseInt(br.readLine());
            if(money<20){
                money=20;
            }
        } catch (Exception e) {
            money=20;
            System.out.println("您的输入不正确,计算机自动将您的投注金额定为20货币单位");
        }
       
            System.out.println("下面开始发牌...");
            player.setHand(deck.getCard());
            com.setHand(deck.getCard());
        do{
            System.out.println("您得到的牌是:"+player.getHandList());
            do{
                System.out.println("您的选择:1.加倍;2.PASS;3.再要一张;4.开牌;5.退回上级菜单");
                try {
                    yourChoice=Integer.parseInt(br.readLine());
                    break;
                } catch (NumberFormatException ex) {
                    System.out.println("输入错误,请重新输入");
                } catch (IOException ex) {
                    System.out.println("输入错误,请重新输入");
                }
            }while(true);
       
            switch(yourChoice){
                case 1://加倍
                    yourDouble(money);
                    break;
                case 2://PASS
                    yourPass(money);
                    break;
                case 3://再要一张
                    getCardAgain(money);
                    break;
                case 4://开牌
                    winOrLose(money);
                    yourChoice=5;
                    break;
                case 5://退回上一级
                    break;
                default:
                    System.out.println("您的输入有误,请输入1-5");
            }
        }while(yourChoice!=5);
    }
   
    //查看玩家成绩
    private void checkScore() {
        System.out.println("您胜利了"+player.getWin()+"次");
        System.out.println("您失败了"+player.getLose()+"次");
        System.out.println("您还有"+player.getCash()+"货币单位");
    }
   
    //玩家加倍
    private void yourDouble(int money) {
        money*=2;//投注金额加倍
       
        //判断输赢
        this.winOrLose(money);
    }
   
    //点数计算
    private int computePoint(Player player){
        int playerPoint=0;//玩家的牌点
        int numberOfA=0;//A点拿到的张数
       
        //A点以外的分数累加
        for(int i=0;i<player.getHand().size();i++){
            Card c=(Card)player.getHand().get(i);
            if(c.getFace().charAt(0)>='2'&&c.getFace().charAt(0)<='9'){
                playerPoint+=Integer.parseInt(c.getFace());//牌点在2~9之间直接累加
            }else if(c.getFace().equals("J") ||
                    c.getFace().equals("Q")||
                    c.getFace().equals("K")||c.getFace().equals("10")){
                playerPoint+=10;//牌点是J Q K则累加10
            }else if(c.getFace().charAt(0)=='A'){
                numberOfA++;
            }
        }
       
        //A点的分数累加
        if(numberOfA==0){
           
        }else{
            if(playerPoint+(11*numberOfA)>21){
                playerPoint+=numberOfA;
            }else{
                playerPoint+=11;
            }
        }
       
        if(playerPoint<=21){
            return playerPoint;
        }else{
            return 0;//超过21点(爆分)
        }
    }
    private void yourPass(int money) {//PASS
        //判断输赢
        this.winOrLose(money);
    }

    private void getCardAgain(int money) {//再发一张
        player.setHand(deck.getCard());
    }

    private void winOrLose(int money) {//判断输赢
        int playerPoint=this.computePoint(player);//获得玩家点数
        int comPoint=comPlayer();//获得电脑点数
       
        if(comPoint==0){//点脑爆分
            System.out.println("爆分!你赢了。");
            player.setCash(player.getCash()+money);
            player.youWin();
        }else if(playerPoint==0){//玩家爆分
            System.out.println("爆分!你输了。");
            player.setCash(player.getCash()-money);
            player.youLose();
        }else if(comPoint<playerPoint||player.getSize()==5||playerPoint==21){
            System.out.println("电脑:"+comPoint+"你:"+playerPoint+"你赢了");
            player.setCash(player.getCash()+money);
            player.youWin();
        }else{
            System.out.println("电脑:"+comPoint+"你:"+playerPoint+"你输了");
            player.setCash(player.getCash()-money);
            player.youLose();
        }
    }

    private int comPlayer() {
        int comPoint=this.computePoint(com);
        System.out.println("电脑开始:"+com.getHandList());
        while(comPoint!=0&&comPoint<=18 && com.getSize()<5){//人工智能:如果电脑手上的点数小于18点就发牌
            com.setHand(deck.getCard());//再发一张牌给电脑
           
            System.out.println("再发一张,电脑手中:"+com.getHandList());
            comPoint=this.computePoint(com);//重新计算分数
        }
        return comPoint;      
    }
   
}//BlackJack
 

/*
 * Card.java
 *
 * 创建时间 2006年12月27日, 上午10:09
 *
 * 版本:0.0.1
 * 一个表示纸牌的类
 */

package blackjack;

/**
 *
 * @author mouyong1973
 */
class Card {
    //表示所有纸牌面值的数组
    public static final String[] FACES={"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
   
    //表示所有类型值的数组
    public static final String[] SUITS={"黑桃","梅花","方块","红心"};
   
    //纸牌总数
    public static final int MAX_CARDS=FACES.length*SUITS.length;
   
    //这张牌的点值
    protected int value;
   
    //用0点创建一个默认纸牌
    public Card(){
        value=0;
    }
   
    //创建第n张牌,非法n值将使程序终止。
    public Card(int n){
        if(n<0 || n>MAX_CARDS){
            System.out.println("错误:非法牌索引,程序退出");
            System.exit(0);           
        }else{
            value=n;
        }
    }
   
    //返回表示纸牌面值的字符串
    public String getFace(){
        return FACES[value%FACES.length];
    }
   
    //返回表示纸牌类型的String
    public String getSuit(){
        return SUITS[value%SUITS.length];
    }
   
    public String toString(){
        return getSuit()+getFace();
    }
}//Card

/*
 * Deck.java
 *
 * 创建时间:2006年12月27日, 下午9:32
 *
 * 版本:0.0.1
 * 表示一副牌的类
 */

package blackjack;
import java.util.*;
/**
 *
 * @author mouyong1973
 */
public class Deck {
    //Card对象的最大值
    public static final int MAX_SIZE=52;
    //Card对象的栈
    protected Stack cards;
   
    //所有已取出牌的集合
    protected List drawnCards;
   
    //在上面的列表中允许随机获取
    protected Random random;
   
    /**创建一个含52张牌的Deck */
    public Deck() {
        //把给定数目的牌压入栈中
        cards=new Stack();
       
        for (int i=1;i<=MAX_SIZE;i++) {
            cards.push(new Card(i));
        }
       
        //为已取出的牌创建一个池,并创建数字产生器
        drawnCards=new ArrayList();
        random=new Random();
       
        shuffle();
    }
   
    /**
     * 返回这幅牌剩余的数量
     */
    public int getSize(){
        return cards.size()+drawnCards.size();
    }
   
    //随机洗牌
    private void shuffle() {
        //清空栈
        while (!cards.isEmpty()){
                drawnCards.add(cards.pop());
        }
       
        //把取出的牌重新随机放回到栈中
        Object card=null;
        while (!drawnCards.isEmpty()){
            card=drawnCards.remove(Math.abs(random.nextInt()%drawnCards.size()));
            cards.push(card);
        }
    }
   
    /**
     * 发牌
     */
    public Card getCard(){
        if(getSize()==0){//牌已经发完了
           
            //重新生成一副牌
            for (int i=1;i<=MAX_SIZE;i++) {
            cards.push(new Card(i));
            }
           
            //重新洗牌
            shuffle();
        }
       
        return (Card)cards.pop();
    }
   
}//Deck

 

/*
 * Hand.java
 *
 * 创建时间: 2006年12月27日, 下午11:00
 *
 * 版本:0.0.1
 *保存玩家手中游戏纸牌的类
 */

package blackjack;

import java.util.ArrayList;

/**
 *
 * @author mouyong1973
 */
class Hand {
    private ArrayList cards;
    /** Creates a new instance of Hand */
    public Hand() {
        cards=new ArrayList();
    }
   
    /**
     *接受一张发牌
     */
    public void setCard(Object c){
        cards.add(c);
    }
    /**
     *清空玩家手中的牌
     */
    public void clear(){
        cards.clear();
    }
    /**
     *返回玩家手中的牌张数
     */
    public int getSize(){
        return cards.size();
    }
    //显示玩家手中的牌列表
    public String toString(){
        //int i = 0;
        String hand = "";
       
        //while (!cards.isEmpty()){
        hand=cards.toString();
            //i++;
        //}
        return hand;
    }
   
    public ArrayList getCards(){
        return cards;
    }
}//Hand

 

/*
 * Player.java
 *
 * 创建时间: 2006年12月27日, 下午11:19
 *
 * 版本:0.0.1
 *一个关于玩家的类
 */

package blackjack;

import java.util.List;

/**
 *
 * @author mouyong1973
 */
public class Player {
   
    private int winNumber;//记录胜利次数
    private int loseNumber;//记录失败次数
    private int cash;//玩家手中的现金
    private Hand hand;
    /**
     * 初始化玩家的相关参数
     *胜利次数:0
     *失败次数:0
     *纸牌数:0
     *现金数:10000
     */
    public Player() {
        winNumber=0;
        loseNumber=0;
        hand=new Hand();
        setCash(10000);
    }
   
    /**
     *获得胜利次数
     */
    public int getWin(){
        return winNumber;
    }
   
    /**
     *获得失败次数
     */
    public int getLose(){
        return loseNumber;
    }
   
    /**
     *获得玩家手中牌的列表
     */
    public String getHandList(){
        return hand.toString();
    }
   
    /**
     *获得玩家手中牌的张数
     */
    public int getSize(){
        return hand.getSize();
    }
   
    /**
     *接受发来的牌
     */
    public void setHand(Card c){
        hand.setCard(c);
    }
   
    /**
     *返回玩家手中牌列表
     *类型:List
     */
    public List getHand(){
        return hand.getCards();
    }
    /**
     *赢了一局
     */
    public void youWin(){
        winNumber++;
    }
   
    /**
     *清空玩家手中的牌
     */
    public void playAgain(){
        hand.clear();
    }
   
    /**
     *输了一局
     */
    public void youLose(){
        loseNumber++;
    }
   
    /**
     *得到当前现金
     */
    public int getCash() {
        return cash;
    }
   
    /**
     *重新设置当前现金
     */
    public void setCash(int cash) {
        this.cash = cash;
    }
}//Player

 

做了一个多星期,总算写完了,本来挺简单的,只是事情太多了。希望大家多提意见。


您好:
    当您在阅读和使用我所提供的各种内容的时候,我非常感谢,您的阅读已是对我最大的支持。
    我更希望您能给予我更多的支持。
    1.希望您帮助我宣传我的博客,让更多的人知道它,从中获益。
    2.希望您能多提出宝贵意见,包括我所提供的内容中的错误,建设性的意见,更希望获得哪些方面的帮助,您的经验之谈等等。
    3.更希望能得到您经济上的支持。
   
    我博客上面的内容均属于个人的经验,所有的内容均为开源内容,允许您用于任何用途,并不以付费为前提,如果您觉得在阅读和使用我所提供的各种内容的过程中,您得到了帮助,并能在经济上给予我支持,我将感激不尽。
   
    您可以通过银行转帐付款给我:
    招商银行一卡通:
    卡号:6225888712586894
    姓名:牟勇
   
    建行龙卡:
    卡号:4367423860500165563
    姓名:牟勇
   
    您也可以通过汇款的方式:
    通讯地址:云南省昆明市女子(28)中学人民中路如意巷1号
    收信人:陈谦转牟勇收
    邮编:650021
   
    无论您给予我怎么样的支持,我都衷心的再次感谢。
    欢迎光临我的博客:
    http://blog.csdn.net/mouyong
    http://blog.sina.com.cn/u/1259714872
原创粉丝点击