一溅呢、項(xiàng)目介紹
該項(xiàng)目的主要功能是實(shí)現(xiàn)撲克牌比大小澡屡,輸入?yún)⑴c游戲的人數(shù)猿挚,各自選擇相應(yīng)的操作,有看牌驶鹉、棄牌绩蜻、下注等等,每一回合有相應(yīng)的底注室埋,結(jié)束時(shí)得出獲勝玩家办绝,并結(jié)算各個(gè)玩家剩余的金幣總數(shù)。
二姚淆、項(xiàng)目框架與目的
開發(fā)流程
目的:希望同學(xué)們?cè)趯戫?xiàng)目的同時(shí)孕蝉,對(duì)不同類之間的數(shù)據(jù)交互的過(guò)程中,更加深刻地掌握J(rèn)ava中類與對(duì)象的應(yīng)用肉盹,同時(shí)去學(xué)習(xí)一個(gè)項(xiàng)目從無(wú)到有的實(shí)現(xiàn)過(guò)程昔驱,以及過(guò)程中出現(xiàn)的bug的調(diào)試技巧。
三上忍、具體實(shí)現(xiàn)
1. 封裝輸出語(yǔ)句
輸出樣式:1. ********************
? ? ? ? ? ? ? ? ? hello,Java!
? ? ? ? ? ? ? ? ********************
? ? ? ? ? ? ? 2. hello,Java!
? ? ? ? ? ? ? 3.********************
? ? ? ? ? ? ? ??1.Java
? ? ? ? ? ? ? ??2.Python
? ? ? ? ? ? ? ??3.Swift
? ? ? ? ? ? ? ?********************
import java.util.Scanner;
/**
*工具類
*/
public class Utils {
//如果不需要保存數(shù)據(jù) 沒(méi)有成員變量
//提供靜態(tài)方法 訪問(wèn)方便
/**
* 封裝輸出語(yǔ)句
* @param hasStar 是否需要****分割符
* @param LineBreak 是否需要換行
* @param contents 輸出的內(nèi)容
*/
public static void showText(boolean hasStar,boolean LineBreak,String...contents){
//判斷是否需要顯示分割線
System.out.print(hasStar?"************************\n":"");//三目運(yùn)算
//判斷輸出的內(nèi)容是一行還是多行
if (contents.length == 1){
System.out.print(contents[0]);
//有分割線的時(shí)候需要換行
System.out.print(hasStar?"\n":"");
}else {
//輸出帶編號(hào)的多行數(shù)據(jù)
for (int i = 0;i < contents.length;i++){
System.out.println((i+1)+". "+contents[i]);
}
}
System.out.println(hasStar?"************************\n":"");//三目運(yùn)算
//判斷是否需要換行
System.out.print(LineBreak?"\n":"");
}
}
2. 創(chuàng)建Poker類
-
創(chuàng)建Constant類管理一些常量
public class Constant {
//用數(shù)組來(lái)保存牌的點(diǎn)數(shù)
//常量一般使用大寫
public static final String[] DOTS = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
}
-
定義PokerType類管理牌的花色和ID號(hào)
/**
* 管理牌的圖案和比較圖案的大小
*/
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;
//外部可以調(diào)用
public PokerType(){}
//提供一個(gè)自定義的構(gòu)造方法
//默認(rèn)的構(gòu)造方法就被屏蔽了
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;
}
}
-
創(chuàng)建PokerManager類管理牌的操作
-
生成一副牌
-
/**
* 管理牌的相關(guān)操作
* 生成一副牌 洗牌 發(fā)牌 牌的比較
*/
public class PokerManager {
//保存一副牌
private ArrayList<Poker> pokers = new ArrayList<Poker>();
//創(chuàng)建靜態(tài)變量
public static final PokerManager manager = new PokerManager();
//私有化構(gòu)造方法
private PokerManager(){
}
//定義一個(gè)方法生成一副牌
public void generate(){
//遍歷整個(gè)數(shù)組的點(diǎn)數(shù)
for (int i = 0;i < Constant.DOTS.length;i++){
//獲取對(duì)應(yīng)的點(diǎn)數(shù)
String dot = Constant.DOTS[i];
//生成四種花色
for (int j = 0;j < Constant.TYPES.length;j++){
//創(chuàng)建一張牌
Poker poker = new Poker(dot,Constant.TYPES[j]);
//將這張牌保存起來(lái)
pokers.add(poker);
}
}
//洗牌
Collections.shuffle(pokers);
}
//顯示一副牌
public void show(){
for (Poker poker:pokers){
System.out.print(poker.getDot()+poker.getType().getPicture()+" ");
}
System.out.println();
}
/**
* 給每個(gè)玩家發(fā)牌
* @param players 所有參與的玩家
*/
public void deal(ArrayList<Player> players){
for (int i = 0;i < players.size();i++){
Player player = players.get(i);
//將數(shù)組里面對(duì)應(yīng)的撲克牌給對(duì)應(yīng)的玩家
player.poker = pokers.get(i);
}
}
}
-
為Poker類和PokerType類提供自定義構(gòu)造方法
//提供一個(gè)自定義的構(gòu)造方法
//默認(rèn)的構(gòu)造方法就被屏蔽了
public PokerType(String picture,int id){
//this.setPicture(picture);
this.picture = picture;
this.id = id;
}
-
創(chuàng)建花色,在PokerType?面提供4個(gè)靜態(tài)常量 對(duì)象
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?面提供數(shù)組保存這4個(gè)常量
//保存固定的幾個(gè)花色
public static final PokerType[] TYPES = {PokerType.SPADES,PokerType.HEARTS,PokerType.CLUBS,PokerType.DIAMONDS};
-
實(shí)現(xiàn)功能
//定義一個(gè)方法生成一副牌
public void generate(){
//遍歷整個(gè)數(shù)組的點(diǎn)數(shù)
for (int i = 0;i < Constant.DOTS.length;i++){
//獲取對(duì)應(yīng)的點(diǎn)數(shù)
String dot = Constant.DOTS[i];
//生成四種花色
for (int j = 0;j < Constant.TYPES.length;j++){
//創(chuàng)建一張牌
Poker poker = new Poker(dot,Constant.TYPES[j]);
//將這張牌保存起來(lái)
pokers.add(poker);
}
}
//洗牌
Collections.shuffle(pokers);
}
-
提供一個(gè)方法輸出 這副牌 :拼接每張牌的輸出格式
//顯示一副牌
public void show(){
for (Poker poker:pokers){
System.out.print(poker.getDot()+poker.getType().getPicture()+" ");
}
System.out.println();
}
-
使用
// 生成一副牌
PokerManager.manager.generate();
//顯示一副牌
PokerManager.manager.show();
-
創(chuàng)建玩家類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;
}
}
-
創(chuàng)建玩家管理?PlayerManager 管理玩家信息
-
Constant?面添加常量量 保存默認(rèn)提供的姓名和 金幣數(shù)
-
//保存默認(rèn)的玩家姓名
public static final String[] DEFAULT_NAMES = {"周潤(rùn)發(fā)","周星馳","梁朝偉","陳冠希","張家輝"};
//設(shè)置默認(rèn)的金幣
public static final int MONEY = 1000;
//每局消耗的金幣數(shù) 底注
public static final int BASE = 10;
-
初始化玩家信息
//初始化玩家
public void initPlayer(int count){
for (int i = 0;i < count;i++){
//創(chuàng)建一個(gè)玩家
String name = Constant.DEFAULT_NAMES[i];
Player player = new Player(name,i+1,Constant.MONEY);
//保存玩家
players.add(player);
}
}
-
實(shí)現(xiàn)toString?法 ?便打印
@Override
//當(dāng)打印一個(gè)對(duì)象的時(shí)候 就會(huì)默認(rèn)去調(diào)用對(duì)象的toString方法
//如果當(dāng)前類里面沒(méi)有實(shí)現(xiàn)這個(gè)方法 就會(huì)到父類里面去查找
// Object 里面的默認(rèn)實(shí)現(xiàn)就是打印這個(gè)對(duì)象的首地址
public String toString(){
String pkString = "";
if (poker != null){
pkString = poker.getDot()+poker.getType().getPicture();
}
return id+"號(hào)玩家: "+name+" 籌碼"+money + " "+getPokerString();
}
-
輸出玩家信息
//輸出玩家信息
public void show(){
for (Player player:players){
System.out.println(player);
}
}
-
游戲中心管理游戲
-
PlayerManager和PokerManager 提供單例對(duì)象
-
public static final PlayerManager manager = new PlayerManager();
private PlayerManager(){
}
public static final PokerManage = new PokerManage ();
private PokerManage (){
}
-
PlayerManager實(shí)現(xiàn)打底注的方法
/**
*打底注
* @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實(shí)現(xiàn)下注?法
/**
* 打底 & 下注
* @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("游戲開始,請(qǐng)打底:");
//扣除底注
PlayerManager.manager.betAll(Constant.BASE);
PlayerManager.manager.show();
}
}
-
開始發(fā)牌
-
在Player類?面添加Poker對(duì)象 每個(gè)?有一張牌
-
PokerManager類添加發(fā)牌?法
-
/**
* 給每個(gè)玩家發(fā)牌
* @param players 所有參與的玩家
*/
public void deal(ArrayList<Player> players){
for (int i = 0;i < players.size();i++){
Player player = players.get(i);
//將數(shù)組里面對(duì)應(yīng)的撲克牌給對(duì)應(yīng)的玩家
player.poker = pokers.get(i);
}
}
-
GameCenter的start?法調(diào)用發(fā)牌
//發(fā)牌
System.out.println("開始發(fā)牌");
PokerManager.manager.deal(PlayerManager.manager.players);
-
開始下注
-
獲得當(dāng)前下注玩家
-
/**
* 獲取當(dāng)前下注的玩家
* @return 玩家對(duì)象
*/
public Player currrentPlayer(){
return players.get(currentPlayerIndex);
}
-
當(dāng)前剩余的玩家
/**
* 當(dāng)前剩余玩家數(shù)
* @return
*/
public int leftPlayerCount(){
int total = 0;
for (int i = 0;i < players.size();i++){
Player player = players.get(i);
//沒(méi)棄牌并且有錢
if (player.hasDiscard == false && player.money > 0){
total++;
}
}
return total;
}
-
查找下一個(gè)下注的玩家
/**
* 查找下一個(gè)下注的人
*/
public void changeNext(){
int i = currentPlayerIndex;
if (i == players.size()-1){
i = 0;
}else{
i++;
}
// 查找下一個(gè)可以參與的玩家
for (;i < players.size();i++){
Player player = players.get(i);
if (player.hasDiscard == false && player.money > 0){
currentPlayerIndex = i;
return;
}
}
}
-
GameCenter實(shí)現(xiàn)
int time = 0; //記錄如果是兩個(gè)人的次數(shù)
boolean isFirst = true;
int betMoney = 0;
while (true){
//獲取當(dāng)前玩家
Player player = PlayerManager.manager.currrentPlayer();
//提示選擇操作
System.out.println("請(qǐng)"+player.id+"號(hào)玩家選擇操作:");
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+"號(hào)玩家棄牌");
player.hasDiscard = true;
break;
default:
//下注
if (isFirst){
while (true) {
System.out.print("請(qǐng)輸入下注金額:");
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){
//計(jì)算當(dāng)前還有多少人參與
int available = PlayerManager.manager.leftPlayerCount();
if (available == 1){
//本局結(jié)束
break;
}
if (available == 2){
time++;
if (time == 4){
//兩個(gè)回合結(jié)束
break;
}
}
//切換到下一個(gè)人
PlayerManager.manager.changeNext();
PlayerManager.manager.show();
}
}
PlayerManager.manager.awardWinner(totalMoney);
}
-
獎(jiǎng)勵(lì)贏家
/**
* 獎(jiǎng)勵(lì)贏家
*/
public void awardWinner(int total){
Player winner;
int available = leftPlayerCount();
if (available == 1){
//只有一個(gè)玩家 這就是贏家
changeNext();
winner = currrentPlayer();
}else{
//需要比較這兩個(gè)玩家的牌
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+"號(hào)玩家贏得"+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) {
//點(diǎn)數(shù)不同 直接比較
return mIndex > oIndex;
}else{
//點(diǎn)數(shù)相同 比較花色
return this.type.getId() > poker.type.getId();
}
}
-
Player類實(shí)現(xiàn)贏錢 就加金幣的方法
public void addMOney(int count){
money += count;
}
項(xiàng)目源碼: