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;
}
情况演示
文章图片
1.png 扑克牌游戏 设计游戏大致思路
文章图片
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,其中还有很多不懂的,需要不断看视频和学习,才能将她摸透
推荐阅读
- Day10_要想看起来毫不费力,必须付出超乎常人的努力
- GCD小总结
- #猫群写作营day10#为什么要给自己设限呢()
- 类的加载过程
- 2018.3.30#复盘#day100
- 【21天自律营】日更DAY10|【21天自律营】日更DAY10 自我反省+重拾心动
- SpringBean单例情况下解决循环依赖的原理
- 更完整的单例模式(java|更完整的单例模式(java, kotlin)
- 单例模式的三种实现方法
- DAY1006#教学反思#