一、项目介绍
该项目的主要功能是实现扑克牌比大小,输入参与游戏的人数,各自选择相应的操作,有看牌、弃牌、下注等等,每一回合有相应的底注,结束时得出获胜玩家,并结算各个玩家剩余的金币总数。
二、项目框架与目的
目的:希望同学们在写项目的同时,对不同类之间的数据交互的过程中,更加深刻地掌握Java中类与对象的应用,同时去学习一个项目从无到有的实现过程,以及过程中出现的bug的调试技巧。
三、具体实现
1. 封装输出语句
输出样式:1. ********************
hello,Java!
********************
2. hello,Java!
3.********************
1.Java
2.Python
3.Swift
********************
import java.util.Scanner;
/**
*工具类
*/
public class Utils {
//如果不需要保存数据 没有成员变量
//提供静态方法 访问方便
/**
* 封装输出语句
* @param hasStar 是否需要****分割符
* @param LineBreak 是否需要换行
* @param contents 输出的内容
*/
public static void showText(boolean hasStar,boolean LineBreak,String...contents){
//判断是否需要显示分割线
System.out.print(hasStar?"************************\n":"");//三目运算
//判断输出的内容是一行还是多行
if (contents.length == 1){
System.out.print(contents[0]);
//有分割线的时候需要换行
System.out.print(hasStar?"\n":"");
}else {
//输出带编号的多行数据
for (int i = 0;i < contents.length;i++){
System.out.println((i+1)+". "+contents[i]);
}
}
System.out.println(hasStar?"************************\n":"");//三目运算
//判断是否需要换行
System.out.print(LineBreak?"\n":"");
}
}
2. 创建Poker类
-
创建Constant类管理一些常量
public class Constant {
//用数组来保存牌的点数
//常量一般使用大写
public static final String[] DOTS = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
}
-
定义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 picture;
private int id;
//外部可以调用
public PokerType(){}
//提供一个自定义的构造方法
//默认的构造方法就被屏蔽了
public PokerType(String picture,int id){
//this.setPicture(picture);
this.picture = picture;
this.id = id;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
-
定义Poker类
import java.util.Arrays;
public class Poker {
private String dot;
private PokerType type;
public Poker(){
}
public Poker(String dot,PokerType type){
this.dot = dot;
this.type = type;
}
//setter/getter方法
public void setDot(String dot){
this.dot = dot;
}
public String getDot(){
return dot;
}
public PokerType getType() {
return type;
}
public void setType(PokerType type) {
this.type = type;
}
}
-
创建PokerManager类管理牌的操作
-
生成一副牌
-
/**
* 管理牌的相关操作
* 生成一副牌 洗牌 发牌 牌的比较
*/
public class PokerManager {
//保存一副牌
private ArrayList<Poker> pokers = new ArrayList<Poker>();
//创建静态变量
public static final PokerManager manager = new PokerManager();
//私有化构造方法
private PokerManager(){
}
//定义一个方法生成一副牌
public void generate(){
//遍历整个数组的点数
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().getPicture()+" ");
}
System.out.println();
}
/**
* 给每个玩家发牌
* @param players 所有参与的玩家
*/
public void deal(ArrayList<Player> players){
for (int i = 0;i < players.size();i++){
Player player = players.get(i);
//将数组里面对应的扑克牌给对应的玩家
player.poker = pokers.get(i);
}
}
}
-
为Poker类和PokerType类提供自定义构造方法
//提供一个自定义的构造方法
//默认的构造方法就被屏蔽了
public PokerType(String picture,int id){
//this.setPicture(picture);
this.picture = picture;
this.id = id;
}
-
创建花色,在PokerType⾥面提供4个静态常量 对象
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);
-
在Constant⾥面提供数组保存这4个常量
//保存固定的几个花色
public static final PokerType[] TYPES = {PokerType.SPADES,PokerType.HEARTS,PokerType.CLUBS,PokerType.DIAMONDS};
-
实现功能
//定义一个方法生成一副牌
public void generate(){
//遍历整个数组的点数
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().getPicture()+" ");
}
System.out.println();
}
-
使用
// 生成一副牌
PokerManager.manager.generate();
//显示一副牌
PokerManager.manager.show();
-
创建玩家类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;
}
}
-
创建玩家管理器PlayerManager 管理玩家信息
-
Constant⾥面添加常量量 保存默认提供的姓名和 金币数
-
//保存默认的玩家姓名
public static final String[] DEFAULT_NAMES = {"周润发","周星驰","梁朝伟","陈冠希","张家辉"};
//设置默认的金币
public static final int MONEY = 1000;
//每局消耗的金币数 底注
public static final int BASE = 10;
-
初始化玩家信息
//初始化玩家
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);
}
}
-
实现toString⽅法 ⽅便打印
@Override
//当打印一个对象的时候 就会默认去调用对象的toString方法
//如果当前类里面没有实现这个方法 就会到父类里面去查找
// Object 里面的默认实现就是打印这个对象的首地址
public String toString(){
String pkString = "";
if (poker != null){
pkString = poker.getDot()+poker.getType().getPicture();
}
return id+"号玩家: "+name+" 筹码"+money + " "+getPokerString();
}
-
输出玩家信息
//输出玩家信息
public void show(){
for (Player player:players){
System.out.println(player);
}
}
-
游戏中心管理游戏
-
PlayerManager和PokerManager 提供单例对象
-
public static final PlayerManager manager = new PlayerManager();
private PlayerManager(){
}
public static final PokerManage = new PokerManage ();
private PokerManage (){
}
-
PlayerManager实现打底注的方法
/**
*打底注
* @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();
}
-
Player实现下注⽅法
/**
* 打底 & 下注
* @param count 下注金额
* @return -1 失败
* >0 成功
*/
public int bet(int count){
//判断自己的金币是否大于下注金额
if (money >= count){
money -= count;
return count;
}else {
return -1;
}
}
-
Gamecenter 开始游戏
public class GameCenter {
//记录这局的筹码
private int totalMoney;
//开始游戏
public void start(){
System.out.println("游戏开始,请打底:");
//扣除底注
PlayerManager.manager.betAll(Constant.BASE);
PlayerManager.manager.show();
}
}
-
开始发牌
-
在Player类⾥面添加Poker对象 每个⼈有一张牌
-
PokerManager类添加发牌⽅法
-
/**
* 给每个玩家发牌
* @param players 所有参与的玩家
*/
public void deal(ArrayList<Player> players){
for (int i = 0;i < players.size();i++){
Player player = players.get(i);
//将数组里面对应的扑克牌给对应的玩家
player.poker = pokers.get(i);
}
}
-
GameCenter的start⽅法调用发牌
//发牌
System.out.println("开始发牌");
PokerManager.manager.deal(PlayerManager.manager.players);
-
开始下注
-
获得当前下注玩家
-
/**
* 获取当前下注的玩家
* @return 玩家对象
*/
public Player currrentPlayer(){
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 == false && 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 == false && player.money > 0){
currentPlayerIndex = i;
return;
}
}
}
-
GameCenter实现
int time = 0; //记录如果是两个人的次数
boolean isFirst = true;
int betMoney = 0;
while (true){
//获取当前玩家
Player player = PlayerManager.manager.currrentPlayer();
//提示选择操作
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.print("余额不足 ");
} 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 = PlayerManager.manager.leftPlayerCount();
if (available == 1){
//本局结束
break;
}
if (available == 2){
time++;
if (time == 4){
//两个回合结束
break;
}
}
//切换到下一个人
PlayerManager.manager.changeNext();
PlayerManager.manager.show();
}
}
PlayerManager.manager.awardWinner(totalMoney);
}
-
奖励赢家
/**
* 奖励赢家
*/
public void awardWinner(int total){
Player winner;
int available = leftPlayerCount();
if (available == 1){
//只有一个玩家 这就是赢家
changeNext();
winner = currrentPlayer();
}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.biggerThan(w2.poker);
if (result){
winner = w1;
}else{
winner = w2;
}
}
System.out.println(winner.id+"号玩家赢得"+total+"金币");
winner.addMOney(total);
}
-
两张牌的比较
public boolean biggerThan(Poker poker){
int mIndex = Arrays.binarySearch(Constant.DOTS,this.dot);
int oIndex = Arrays.binarySearch(Constant.DOTS,poker.dot);
if (mIndex != oIndex) {
//点数不同 直接比较
return mIndex > oIndex;
}else{
//点数相同 比较花色
return this.type.getId() > poker.type.getId();
}
}
-
Player类实现赢钱 就加金币的方法
public void addMOney(int count){
money += count;
}
项目源码: