2019-08-09 Day10 单例设计模式以及扑克牌demo完善

目的

学习和了解单例设计模式,明白其作用和使用方法,完善Java知识基础学习;深入理解数组知识,学好Java基础知识中最重要的一部分;经过四天对Java基础的学习,已经对Java语言有一定了解,今天便做一个最基本的扑克牌demo,来将各类知识串联起来

单例设计模式

概念

java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种;单例模式有以下特点: 1、单例类只能有一个实例; 2、单例类必须自己自己创建自己的唯一实例;3、单例类必须给所有其他对象提供这一实例;
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例;在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例;这些应用都或多或少具有资源管理器的功能;每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中;每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用;总之,选择单例模式就是为了避免不一致状态,避免政出多头

关键词
1.整个程序都操作同一个对象
2.不允许用户创建这个类的一个对象,而将类的构造方法私有化
3.在自己的类里面提供创建对象的方法

两种形式

饿汉式

class Poker{
    //default sharedInstance manager
    //2.定义一个静态的成员变量  记录这个单例对象
    //饿汉式
    public static final Poker sharedInstance = new Poker();

    //1.默认构造函数
    private Poker(){

    }

    public void test(){

    }
}

懒汉式

class Player{
    public int count;

    //2.创建静态变量
    private static Player shared = null;

    //1.私有化构造方法
    private Player(){}

    //3.提供给外部一个访问的方法
    //懒汉式
    public static Player getInstance(){
        Object b = new Object();
        synchronized (b) {
            if (shared == null) {
                //如果没有创建 那么就创建一个
                shared = new Player();
            }
        }

        return shared;
    }
}

数组

Java数组里面保存的都是对象的引用(指针);改变数组里面对象的属性变量,原始对象的值也跟着改变,因为大家都是同一个内存空间

class Test2{
    public static void main(String[] args){
        //泛型
        ArrayList people = new ArrayList<>();

        //获取数组元素个数
        people.size();

        //添加数据
        Person xw = new Person();
        people.add(xw);

        Person zs = new Person();
        people.add(zs);

        //访问数据
        Person xw2 = people.get(0);
        xw2.name = "小王";

        System.out.println(xw2.name);
        System.out.println(xw.name);
    }
}

class Person{
    public String name;
}

情况演示

2019-08-09 Day10 单例设计模式以及扑克牌demo完善_第1张图片
1.png

扑克牌游戏

设计游戏大致思路

2019-08-09 Day10 单例设计模式以及扑克牌demo完善_第2张图片
2.png

封装输出语句

创建一个Untils类,专门封装输出语句

public class Utils {
    //如果不需要保存数据 没有成员变量
    //提供静态方法 访问方便
    public static void showText(boolean hasStar, boolean lineBreak, String... contents) {
        //判断是否需要显示分割线
        System.out.print(hasStar ? "*********************\n" : "");

        //判断输出的内容是多行还是一行
        if (contents.length == 1) {
            //有分隔线的时候需要换行
            System.out.print(contents[0] + (hasStar ? "\n" : ""));
        } else {
            //输出带编号的多行数据
            //1. 弃牌
            for (int i = 0; i < contents.length; i++) {
                System.out.println((i + 1) + ". " + contents[i]);
            }
        }

        System.out.print(hasStar ? "*********************\n" : "");

        //判断是否需要换行
        System.out.print(lineBreak ? "\n" : "");

    }
}

调用这个类创建欢迎界面

public class MyClass {
    public static void main(String[] args){
        //欢迎界面
        Utils.showText(true,true,new String[]{"欢迎使用扑克游戏"});
       }
}

创建Poker

创建Constant类,管理常量

下面代码为已完成状态

public class Constant {
    //用数组保存牌的点数
    public static final String[] dots = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};

    //保存固定的几个花色 黑红梅方
    public static final PokerType[] TYPES = {PokerType.SPADES,PokerType.HEARTS,PokerType.CLUBS,PokerType.DIAMONDS};

    //保存默认的玩家姓名
    public static final String[] DEFAULT_NAMES = {"刘德华","周润发","张家辉","周星驰"};

    //设置默认的金币
    public static final int MONEY = 1000;

    //底注
    public static final int BASE = 10;
}

定义PokerType类 管理牌的花色和id号

public class PokerType {
    public static final PokerType SPADES = new PokerType("♠",4);
    public static final PokerType HEARTS = new PokerType("♥",3);
    public static final PokerType CLUBS = new PokerType("♣",2);
    public static final PokerType DIAMONDS = new PokerType("♦",1);

    private String pic;
    private int id;

    public PokerType(){}

    //提供一个自定义的构造方法
    //默认的构造方法就被屏蔽了
    public PokerType(String pic, int id){
        this.pic = pic;
        this.id = id;
    }
    public String getPic() {
        return pic;
    }

    public void setPic(String pic) {
        this.pic = pic;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

}

创建PokerManager类 来管理牌的相关操作 比如发牌洗牌

import java.util.ArrayList;
import java.util.Collections;

/**
 * 管理牌的相关操作
 * 生成一副牌 洗牌 发牌 牌的比较
 */
public class PokerManager {
    //保存一副牌
    private ArrayList pokers = new ArrayList<>();

    //创建静态对象
    public static final PokerManager manager = new PokerManager();

    //私有化过程方法
    private PokerManager(){}

    //定义一个方法 生成一副牌
    public void deal(){
        //遍历整个点数的数组
        for (int i = 0; i  < Constant.dots.length; i++){
            //获取相应的点数
            String dot = Constant.dots[i];

            //生成四种花色
            for (int j = 0; j < Constant.TYPES.length; j++){
                //创建一张牌
                Poker poker = new Poker(dot, Constant.TYPES[j]);
                //将这张牌保存起来
                pokers.add(poker);
            }
        }
        //洗牌
        Collections.shuffle(pokers);
    }
    public void show() {
        for (Poker poker : pokers) {
            System.out.print(poker.getDot() + poker.getType().getPic() + " ");
        }
        System.out.println();
    }

    /**
     * 给每个玩家发牌
     * @param players 所有参与玩家
     */
    public void dealCards(ArrayList players){
        for (int i = 0; i < players.size(); i++){
            Player player = players.get(i);

            //将数组里面对应的扑克给对应的玩家
            player.poker = pokers.get(i);
        }
    }

}

创建Player类 用于管理玩家信息

public class Player {
    public String name;
    public int id;
    public int money;
    public Poker poker;
    public boolean hasDiscard;//是否弃牌

    public Player(){}

    public Player(String name, int id, int money){
        this.name = name;
        this.id = id;
        this.money = money;
    }

    @Override
    //当打印一个对象的时候 就会默认去调用对象的toString方法
    //如果当前类里面没有实现这个方法 就到父类里面去找
    //object里面默认实现就是打印对象的首地址
    public String toString(){
        //1号玩家:刘德华 金币1000
        return id+"号玩家:"+name+" 金币"+money+" "+getPokerString();
    }

    public String getPokerString(){
        String pkString = "";
        if (poker != null){
            pkString = poker.getDot() + poker.getType().getPic();
        }
        return pkString;
    }

    /**
     * 下底注&下注
     * @param count 下注金额
     * @return -1:失败  >0: 成功
     */
    public int bet(int count){
        //判断自己的金币是否大于下注金额
        if (money >= count){
            money -= count;

            return count;
        }else{
            return -1;
        }
    }
    public void add(int count){
        money += count;
 }
}

创建PlayerManager类 管理玩家的相关操作

import java.util.ArrayList;

public class PlayManager {
    //记录当前下注的玩家编号
    public int currentPlayerIndex = 0;

    //保存所有的玩家
    public ArrayList players = new ArrayList<>();

    public static final PlayManager manager = new PlayManager();

    private PlayManager(){}

    //初始化玩家
    public void initPlayer(int count){
        for (int i = 0; i < count; i++){
            //创建玩家
            String name = Constant.DEFAULT_NAMES[i];
            Player player = new Player(name,i+1,Constant.MONEY);

            //保存玩家
            players.add(player);
        }
    }

    //输出玩家信息
    public void shows(){
        for (Player player:players){
            System.out.println(player);
        }
    }

    /**
     * 全场下底注
     * @param count 每局消耗的金币
     * @return -1:失败  >0: 成功
     */
    public int betAll(int count){
        for (Player player:players){
            int result = player.bet(count);
            if (result == -1){
                return -1;
            }
        }
        //返回总共下注的金币
        return count * players.size();
    }

    /**
     * 获取当前下注玩家
     * @return 玩家对象
     */
    public  Player currentPlayer(){
        return players.get(currentPlayerIndex);
    }

    /**
     * 当前剩余玩家数
     * @return
     */
    public int leftPlayerCount(){
        int total = 0;
        for (int i = 0; i < players.size(); i++){
            Player player = players.get(i);
            if (player.hasDiscard == true && player.money > 0){
                total++;
            }
        }
        return total;
    }

    /**
     * 查找下一个下注的人
     */
    public void changeNext(){
        int i = currentPlayerIndex;
        if (i == players.size()-1){
            i = 0;
        }else{
            i++;
        }
        //查找下一个可以参与的玩家
        for (; i < players.size(); i++){
            Player player = players.get(i);
            if (player.hasDiscard == true && player.money > 0){
                currentPlayerIndex = i;
                return;
            }
        }
    }

    /**
     * 奖励赢家
     */
    public void awardWinner(int total){
        Player winner ;
        int available = leftPlayerCount();
        if (available == 1){
            //只有一个玩家 即为赢家
            changeNext();
            winner = currentPlayer();
        }else{
            //需要比较这两个玩家的牌
            Player w1 = null;
            Player w2 = null;
            for (int i = 0; i < players.size(); i++){
                Player player = players.get(i);
                if (player.hasDiscard == false){
                    if (w1 == null){
                        w1 = player;
                    }else{
                        w2 = player;
                    }
                }
            }

            boolean result = w1.poker.bigerThen(w2.poker);
            if (result){
                winner = w1;
            }else {
                winner = w2;
            }
        }
        System.out.println(winner.id+"号玩家胜利 获取"+total+"金币");
        winner.add(total);
    }
}

创建GameCenter类 管理游戏进行的相关操作

public class GameCenter {
    //记录这局的筹码
    private int totalMoney;

    //开始游戏
    public void start(){
        System.out.println("游戏开始 请下底注");
        PlayManager manager = PlayManager.manager;
        //扣除底注
        manager.betAll(Constant.BASE);

        manager.shows();

        //发牌
        System.out.println("开始发牌");
        PokerManager.manager.dealCards(manager.players);

        manager.shows();

        int time = 0;//记录如果是两个人的次数
        boolean isFirst = true;
        int betMoney = 0;
        while (true){
            //获取当前玩家信息
            Player player = manager.currentPlayer();

            //提示选择操作
            System.out.println("请"+player.id+"号玩家选择操作;");

            Utils.showText(true,true,new String[]{"看牌","弃牌", isFirst?"下注":"跟注"});
            int choice = Utils.getInput();

            boolean flag = false;
            switch (choice){
                case 1:
                    //看牌
                    System.out.println(player.getPokerString());
                    flag =true;
                    break;
                case 2:
                    //弃牌
                    System.out.println(player.id+"号玩家弃牌");
                    player.hasDiscard = true;
                    break;
                default:
                    //下注
                    if (isFirst){
                        while (true) {
                            System.out.print("请输入下注金额:");
                            betMoney = Utils.getInput();

                            int result = player.bet(betMoney);
                            if (result == -1) {
                                //下注不成功
                                System.out.println("余额不足 ");
                            }else{
                                //下注成功
                                isFirst = false;
                                totalMoney += betMoney;
                                break;
                            }
                        }
                    }else{
                        //跟注
                        int result = player.bet(betMoney);
                        if (result == -1){
                            player.hasDiscard = true;
                        }else{
                            System.out.println("下注成功");
                            totalMoney += betMoney;
                        }
                    }
                    break;
            }

            if (flag == false){
                //计算当前还有多少人可以参与
                int available = manager.leftPlayerCount();

                if (available > 1){
                    //本剧结束
                    manager.changeNext();
                    Player winner = manager.currentPlayer();
                    System.out.println(player.id+"号玩家获得胜利 获得金币:"+totalMoney);
                    break;
                }

                if (available == 2){
                    time++;
                    if (time == 4){
                        //两个回合结束 结束游戏
                        break;
                    }
                }

                //切换到下一个人
                manager.changeNext();

            }
        }
    }

整体逻辑

public class MyClass {
    public static void main(String[] args){
        //欢迎界面
        Utils.showText(true,true,new String[]{"欢迎使用扑克游戏"});

        //生成一副牌
        PokerManager.manager.deal();
        //显示一副牌
        PokerManager.manager.show();

        //显示玩家人数
        Utils.showText(false,false,new String[]{"请输入玩家人数:"});
        int count = Utils.getInput();

        //初始化玩家
        PlayManager.manager.initPlayer(count);
        //显示玩家信息
        //PlayManager.manager.shows();

        //开始游戏
        GameCenter center = new GameCenter();
        center.start();
    }
}

心得体会

今天是正式地学习第一个完整的demo,其中还有很多不懂的,需要不断看视频和学习,才能将她摸透

你可能感兴趣的:(2019-08-09 Day10 单例设计模式以及扑克牌demo完善)