目的
学习和了解单例设计模式,明白其作用和使用方法,完善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;
}
情况演示
扑克牌游戏
设计游戏大致思路
封装输出语句
创建一个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,其中还有很多不懂的,需要不断看视频和学习,才能将她摸透