美文网首页
实战:Java 扑克牌比较游戏

实战:Java 扑克牌比较游戏

作者: 小石头呢 | 来源:发表于2019-08-19 23:56 被阅读0次

    一.目的

    通过实现一个简单的扑克牌比大小的游戏,体会面向对象编程的思想。

    二.技术

    1.常量类

    2.类的创建,封装

    3.单例模式

    4.自定义异常类

    三.如何使用

    1.常量类

    对于程序运行过程中,一直不变的数据,我们将它们统一保存在一个类中,这个类的名字通常是Constants,常量数据要用public static final修饰。

    例如:

    public class Constants {
    
        //所有点数
        public static final String[] DOTS = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
    
        //所有的花色
        public static final String[] COLORS = {"♠","♥","♣","♦"};
    
        //默认的玩家姓名数组
        public static final String[] DEFAULT_NAMES ={"周润发","渣渣辉","陈小春","甄子丹"};
    
        //玩家默认的持有金币
        public static final int DEFAULT_MONEY = 1000;
    
        //玩家金币不足
        public static final int NOT_ENOUGH = -1;
    
        //玩家金币足够
        public static final int ENOUGH = 1;
    
        //底注金额
        public static final int BASE_WAGER = 100;
    }
    

    很明扑克牌的花色和点数是一直不变的,类似这样的数据我们就要写入常量类中,注意常量变量的名字一般大写。

    2.类的创建,封装

    明确这个任务中需要哪些类,这些类有什么功能

    对于一个扑克牌游戏,我们需要玩家类Player来抽象玩家,需要扑克牌类Poker来抽象扑克牌,一系列玩家的行为需要一个类来管理所以诞生了我们的玩家管理类PlayerManager,同理管理我们的扑克牌也需要一个管理类PokerManager。一局游戏需要一个类来管理赌注,到那个玩家选择,所以诞生了我们的中心类Center

    Poker类:有自己的点数和花色,重写String toString()是为了方便打印

    public class Poker {
    
        public String dot;
        public String color;
    
        public Poker(){}
        public Poker(String dot,String color){
            this.dot = dot;
            this.color = color;
        }
    
        @Override
        public String toString() {
            return "Poker[" +
                    "'" + dot + '\'' +
                    "'" + color + '\'' +
                    ']';
        }
    }
    

    PokerManager类,首先需要一个变量保存一副牌,接着要产生一副洗好的牌,展示牌,给每个人发牌。

    /**
     * 管理牌的相关操作
     */
    public class PokerManager {
    
        //单例模式
        private PokerManager() {}
        public static final PokerManager PokerDefault = new PokerManager();
    
        //成员变量:保存一副牌
        public static ArrayList<Poker> pokers = new ArrayList<>();
    
        /**
         * 展示一副牌
         */
        public void showPokers(){
            for (Poker poker : pokers) {
                System.out.print(poker+" ");
            }
            System.out.println("");
        }
    
        /**
         * 洗牌
         */
        public void shufflePokers(){
            //生成一副牌
            for (int i = 0; i < Constants.DOTS.length; i++) {
                for (int j = 0; j < Constants.COLORS.length; j++) {
                    Poker poker = new Poker(Constants.DOTS[i],Constants.COLORS[j]);
                    pokers.add(poker);
                }
            }
            //洗牌
            Collections.shuffle(pokers);
        }
    
        /**
         * 发牌
         */
        public void dealPokerToPlayers(){
            for (int i = 0; i < PlayerManager.PlayerDefault.players.size(); i++) {
                PlayerManager.PlayerDefault.players.get(i).poker = pokers.get(i);
            }
        }
    
    }
    

    3.单例模式

    恶汉式创建:私有化构造方法,利用构造方法创建一个不可变的静态常量。

    使用单利模式的目的是为了共享数据

    在这里PokerManager类就需要使用单例模式,我们需要用它来创建一副牌,一副牌在一局游戏中肯定只有一个。难道现实中玩牌是先这副牌发牌后另一副牌发牌?

    /**
     * 管理牌的相关操作
     */
    public class PokerManager {
    
        //单例模式
        private PokerManager() {}
        public static final PokerManager PokerDefault = new PokerManager();
    
    }
    

    4.自定义异常类

    两步走:自定义一个类继承Throwable类;创建构造方法,我建议创建有参的构造方法,便于传递异常信息。

    比如我们这里初始化玩家数量最多只能初始化4个;如果超过四个,那么我们就在对应位置抛出一个异常。

    public class XLWrongInputEXception extends Throwable {
    
        public XLWrongInputEXception(String desc){
            super(desc);
        }
    
    }
    

    四.具体使用

    工程结构图

    PlayerManager类

    package swu.xl.day4.MyPractise.Manager;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    
    import swu.xl.day4.MyPractise.Constants;
    import swu.xl.day4.MyPractise.Model.Player;
    import swu.xl.day4.MyPractise.Status;
    
    /**
     * 管理人的相关操作
     */
    public class PlayerManager {
    
        //单例模式
        private PlayerManager(){}
        public static final PlayerManager PlayerDefault = new PlayerManager();
    
        //成员变量:保存玩家
        public ArrayList<Player> players = new ArrayList<>();
    
        /**
         * 展示所有玩家信息
         */
        public void showPlayers(){
            for (Player player : players) {
                System.out.print(player+" ");
            }
            System.out.println("");
        }
    
        /**
         * 初始化游戏玩家
         * @param count 玩家的人数
         */
        public void initPlayers(int count){
            for (int i = 0; i < count; i++) {
                Player player = new Player(Constants.DEFAULT_NAMES[i],Constants.DEFAULT_MONEY);
                player.id = i+1;
                player.status = Status.StatusIn;
                players.add(player);
            }
        }
    
        /**
         * 所有游戏玩家下底注
         * @return 下的底注金额
         */
        public int betWagerOfPlayers(){
            for (Player player : players) {
                player.bet(Constants.BASE_WAGER);
            }
            return players.size()*Constants.BASE_WAGER;
        }
    
        /**
         * 当前玩家
         * @param index 当前玩家的索引值
         * @return
         */
        public Player getPlayerOfIndex(int index){
            return players.get(index);
        }
    
        /**
         * 比较两个玩家的扑克牌
         * @param p1 玩家1
         * @param p2 玩家2
         * @return 扑克牌牌面大的玩家
         */
        public Player compareTwoPlayer(Player p1,Player p2){
            //比较点数大小
            int index1 = Arrays.binarySearch(Constants.DOTS,p1.poker.dot);
            int index2 = Arrays.binarySearch(Constants.DOTS,p2.poker.dot);
            if (index1 != index2){
                //点数不同
                if (index1 > index2){
                    return p1;
                }else {
                    return p2;
                }
            }else {
                //点数相同
                index1 = Arrays.binarySearch(Constants.COLORS,p1.poker.color);
                index2 = Arrays.binarySearch(Constants.COLORS,p2.poker.color);
                if (index1 > index2){
                    return p1;
                }else {
                    return p2;
                }
            }
        }
    
    }
    

    PokerManager类

    package swu.xl.day4.MyPractise.Manager;
    
    import java.util.ArrayList;
    import java.util.Collections;
    
    import swu.xl.day4.MyPractise.Constants;
    import swu.xl.day4.MyPractise.Model.Poker;
    
    /**
     * 管理牌的相关操作
     */
    public class PokerManager {
    
        //单例模式
        private PokerManager() {}
        public static final PokerManager PokerDefault = new PokerManager();
    
        //成员变量:保存一副牌
        public static ArrayList<Poker> pokers = new ArrayList<>();
    
        /**
         * 展示一副牌
         */
        public void showPokers(){
            for (Poker poker : pokers) {
                System.out.print(poker+" ");
            }
            System.out.println("");
        }
    
        /**
         * 洗牌
         */
        public void shufflePokers(){
            //生成一副牌
            for (int i = 0; i < Constants.DOTS.length; i++) {
                for (int j = 0; j < Constants.COLORS.length; j++) {
                    Poker poker = new Poker(Constants.DOTS[i],Constants.COLORS[j]);
                    pokers.add(poker);
                }
            }
            //洗牌
            Collections.shuffle(pokers);
        }
    
        /**
         * 发牌
         */
        public void dealPokerToPlayers(){
            for (int i = 0; i < PlayerManager.PlayerDefault.players.size(); i++) {
                PlayerManager.PlayerDefault.players.get(i).poker = pokers.get(i);
            }
        }
    
    }
    
    

    Playerr类

    package swu.xl.day4.MyPractise.Model;
    
    import swu.xl.day4.MyPractise.Constants;
    import swu.xl.day4.MyPractise.Status;
    
    public class Player {
    
        public String name;
        public int money;
        public int id;
        public Poker poker;
        public Status status;
    
        public Player(){}
        public Player(String name,int money){
            this.name = name;
            this.money = money;
        }
    
        @Override
        public String toString() {
            return id+"号:'" + name + '\'' +
                    ":" + money + " " + poker;
        }
    
        /**
         * 玩家下注
         * @param betMoney 下注金额
         * @return ENOUGH 金额足够 NOT_ENOUGH金额不足
         */
        public int bet(int betMoney){
            if (money >= betMoney){
                money -= betMoney;
                return Constants.ENOUGH;
            }
    
            return Constants.NOT_ENOUGH;
        }
    }
    
    

    Poker类

    package swu.xl.day4.MyPractise.Model;
    
    public class Poker {
    
        public String dot;
        public String color;
    
        public Poker(){}
        public Poker(String dot,String color){
            this.dot = dot;
            this.color = color;
        }
    
        @Override
        public String toString() {
            return "Poker[" +
                    "'" + dot + '\'' +
                    "'" + color + '\'' +
                    ']';
        }
    }
    
    

    Center类

    package swu.xl.day4.MyPractise;
    
    import swu.xl.day4.MyPractise.Manager.PlayerManager;
    import swu.xl.day4.MyPractise.Manager.PokerManager;
    import swu.xl.day4.MyPractise.Model.Player;
    
    /**
     * 管理游戏
     */
    public class Center {
    
        //成员变量:记录下注的总金额
        public int wager;
    
        //成员变量:记录当前玩家
        int currentPlayerIndex;
    
        //开始游戏
        public void start(){
            //玩家下底注
            Utils.log(false,true,new String[]{"游戏中心---玩家开始下底注"+Constants.BASE_WAGER+":"});
            int temp = PlayerManager.PlayerDefault.betWagerOfPlayers();
            wager += temp;
            PlayerManager.PlayerDefault.showPlayers();
    
            //开始发牌
            Utils.log(false,true,new String[]{"游戏中心---开始发牌:"});
            PokerManager.PokerDefault.dealPokerToPlayers();
            PlayerManager.PlayerDefault.showPlayers();
    
            //第一个玩家
            currentPlayerIndex = 0;
    
            //是否有人下注
            boolean hasPlayerBet = false;
    
            //只有两个人,还允许各下注一次
            int betTime = 0;
    
            //临时的下注金额
            int tempWager = 0;
    
            //各个玩家做出选择
            while (true) {
                    System.out.println("");
                    //获得当前玩家
                    Player tempPlayer = PlayerManager.PlayerDefault.getPlayerOfIndex(currentPlayerIndex);
    
                    //判断是否需要切换到下一个
                    boolean needChangeNext = true;
    
                    //提示信息
                    Utils.log(false,true,new String[]{"游戏中心---请"+tempPlayer+"玩家选择操作"});
                    //提示哪一位玩家做出选择
                    Utils.log(true,false,new String[]{"看牌","弃牌",hasPlayerBet?"跟注":"下注"});
    
                    int count = Utils.getInput();
                    try {
                        if (count > 3){
                            throw new XLWrongInputEXception("异常:超出选择范围");
                        }
                    }catch (XLWrongInputEXception e){
                        System.out.println(e.getMessage());
                        System.exit(1);
                    }
                    //具体的选择操作
                    switch (count) {
                        case 1:
                            //看牌
                            Utils.log(false,true,new String[]{"你的扑克牌是:"+tempPlayer.poker});
                            //不需要比较人数
                            needChangeNext = false;
                            break;
                        case 2:
                            //弃牌
                            Utils.log(false,true,new String[]{"游戏中心---"+tempPlayer+"选择弃牌"});
                            tempPlayer.status = Status.StatusOut;
                            break;
                        case 3:
                            //下注
                            Utils.log(false,false,new String[]{"游戏中心---请输入"+(hasPlayerBet?"跟注":"下注")+"的金额:"});
                            //判断下注是否成功
                            while (true) {
                                //下注金额
                                tempWager = Utils.getInput();
                                //判断是否下注成功
                                if (tempPlayer.bet(tempWager) == Constants.NOT_ENOUGH){
                                    //不成功
                                    Utils.log(false,false,new String[]{"游戏中心---赌注不足,请重新输入"+(hasPlayerBet?"跟注":"下注")+"的金额:"});
                                }else {
                                    //成功
                                    //增加赌盘上的赌注
                                    wager += tempWager;
                                    //输出信息
                                    Utils.log(false,true,new String[]{tempPlayer.id+"号玩家"+(hasPlayerBet?"跟注":"下注")+tempWager+"成功"});
                                    //切换为已经有人下注
                                    hasPlayerBet = true;
                                    break;
                                }
                            }
                            break;
                        default:
                            break;
                    }
    
                    //根据玩家数量做出决定
                    if (needChangeNext) {
                    //临时变量保存当前的玩家数量
                    int remainingCount = getCountOfRemainingPlayers();
    
                    //如果只有一个人
                    if (remainingCount == 1){
                        //取得结果
                        //这种情况必定是两个人了,其中一个人做出了弃牌的选择
                        //此时指引玩家的索引还停留在该弃牌玩家上
    
                        //切换到下一个人
                        changePlayerToNext();
    
                        //得到胜利者
                        Player winner = PlayerManager.PlayerDefault.getPlayerOfIndex(currentPlayerIndex);
                        winner.money += wager;
    
                        //输出胜利者
                        Utils.log(false,true,new String[]{"游戏中心---"+winner.id+"号玩家赢得胜利,赢得金额"+wager});
    
                        break;
                    }
    
                    //如果只有两个人
                    if (remainingCount == 2){
                        betTime++;
                        if (betTime > 2){
                            //0 有人做出弃牌决定
                            //1 2
                            //只有两个人的时候,只可以再互相下注一次
                            //之后比较结果
    
                            //提示信息
                            System.out.println("");
                            Utils.log(false,true,new String[]{"游戏中心---下注次数用尽 进行比较"});
    
                            //进行比较
                            Player winner = getWinner();
                            winner.money += wager;
    
                            //输出胜利者
                            Utils.log(false,true,new String[]{"游戏中心---"+winner.id+"号玩家赢得胜利,赢得金额"+wager});
    
                            break;
                        }
                    }
    
                    //切换到下一个
                    changePlayerToNext();
                }
            }
    
            //跳出循环后结束游戏
            //PlayerManager.PlayerDefault.showPlayers();
        }
    
        /**
         * 获得目前还在游戏的玩家数量
         * @return 玩家数量
         */
        public int getCountOfRemainingPlayers(){
            int sum = 0;
            for (Player player : PlayerManager.PlayerDefault.players) {
                if (player.status == Status.StatusIn) {
                    sum++;
                }
            }
            return sum;
        }
    
        /**
         *找到下一个玩家
         */
        public void changePlayerToNext(){
            //获得玩家数量
            int size = PlayerManager.PlayerDefault.players.size();
            //找到下一个玩家
            //从下一个玩家开始currentPlayerIndex+1
            for (int i = (currentPlayerIndex+1) % size; ; i++) {
                Player player = PlayerManager.PlayerDefault.getPlayerOfIndex(i);
                if (player.status == Status.StatusIn){
                    currentPlayerIndex = i % size;
                    return;
                }
            }
        }
    
        /**
         * 比较最后剩余的两个玩家的扑克牌大小
         * @return 最后胜利的玩家
         */
        public Player getWinner(){
            //得到两个玩家
            Player p1 = null;
            Player p2 = null;
            for (Player player : PlayerManager.PlayerDefault.players) {
                if (player.status == Status.StatusIn){
                    if (p1 ==null){
                        p1 = player;
                    }else {
                        p2 = player;
                    }
                }
            }
            return PlayerManager.PlayerDefault.compareTwoPlayer(p1,p2);
        }
    }
    
    

    Constants类

    package swu.xl.day4.MyPractise;
    
    public class Constants {
    
        //所有点数
        public static final String[] DOTS = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
    
        //所有的花色
        public static final String[] COLORS = {"♠","♥","♣","♦"};
    
        //默认的玩家姓名数组
        public static final String[] DEFAULT_NAMES ={"周润发","渣渣辉","陈小春","甄子丹"};
    
        //玩家默认的持有金币
        public static final int DEFAULT_MONEY = 1000;
    
        //玩家金币不足
        public static final int NOT_ENOUGH = -1;
    
        //玩家金币足够
        public static final int ENOUGH = 1;
    
        //底注金额
        public static final int BASE_WAGER = 100;
    }
    
    

    Main类

    package swu.xl.day4.MyPractise;
    
    import swu.xl.day4.MyPractise.Manager.PlayerManager;
    import swu.xl.day4.MyPractise.Manager.PokerManager;
    
    public class Main {
    
        public static void main(String[] args){
    
            //欢迎
            Utils.log(false,true,new String[]{"游戏中心---欢迎来到扑克游戏"});
    
            //洗牌
            Utils.log(false,true,new String[]{"游戏中心---扑克牌已经洗好:"});
            PokerManager.PokerDefault.shufflePokers();
            PokerManager.PokerDefault.showPokers();
    
            //提示输入玩家
            Utils.log(false,false,new String[]{"游戏中心---请输入玩家人数:"});
    
            //生成玩家
            int count = Utils.getInput();
            try {
                if (count > Constants.DEFAULT_NAMES.length){
                    throw new XLWrongInputEXception("异常:系统最多加载4个玩家");
                }
            } catch (XLWrongInputEXception e) {
                System.out.println(e.getMessage());
                System.exit(1);
            }
            PlayerManager.PlayerDefault.initPlayers(count);
            PlayerManager.PlayerDefault.showPlayers();
    
            //开始游戏
            Center center = new Center();
            center.start();
        }
    }
    
    

    Status类

    package swu.xl.day4.MyPractise;
    
    public enum Status {
        StatusIn, //玩家未弃牌
        StatusOut //玩家弃牌
    }
    

    Utils类

    package swu.xl.day4.MyPractise;
    
    import java.util.Scanner;
    
    public class Utils {
    
        /**
         * 打印内容
         * @param separator 要不要***
         * @param lineBreak 要不要换行
         * @param content   输出的文本内容
         */
        public static void log(boolean separator,boolean lineBreak,String...content){
    
            //判断是否需要分割线
            System.out.print(separator?"**************\n":"");
    
            //判断输出的内容是单行还是多行
            if (content.length == 1) {
                System.out.print(content[0]+(separator?"\n":""));
            }else {
                //输出带编号的多行数据
                for (int i = 0; i < content.length; i++) {
                    System.out.println((i+1)+". "+content[i]);
                }
            }
    
            //判断是否需要分割线
            System.out.print(separator?"**************\n":"");
    
            //判断是或需要换行
            System.out.print(lineBreak?"\n":"");
        }
    
        /**
         * 接受用户输入
         * @return 用户输入
         */
        public static int getInput(){
    
            Scanner scanner = new Scanner(System.in);
    
            return scanner.nextInt();
        }
    }
    

    XLWrongInputEXception类

    package swu.xl.day4.MyPractise;
    
    public class XLWrongInputEXception extends Throwable {
    
        public XLWrongInputEXception(String desc){
            super(desc);
        }
    }
    
    

    运行结果:

    相关文章

      网友评论

          本文标题:实战:Java 扑克牌比较游戏

          本文链接:https://www.haomeiwen.com/subject/qpiejctx.html