2019-08-09|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|2019-08-09 Day10 单例设计模式以及扑克牌demo完善
文章图片
1.png 扑克牌游戏 设计游戏大致思路 2019-08-09|2019-08-09 Day10 单例设计模式以及扑克牌demo完善
文章图片
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 玩家对象 */ publicPlayer 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(); } }

心得体会 【2019-08-09|2019-08-09 Day10 单例设计模式以及扑克牌demo完善】今天是正式地学习第一个完整的demo,其中还有很多不懂的,需要不断看视频和学习,才能将她摸透

    推荐阅读