斗地主小游戏
分析1
-
刚开始写,是不是没有思路?没关系!
-
你就结合实际生活来想啊!
-
比如,你有一天非常的郁闷,想要找你的两位好基友一起斗地主!
-
那么,第一步是不是要去超市或商店购买一副牌啊!
-
然后,第二步是不是洗牌啊!(洗牌)
-
之后,第三步是不是发牌啊!(发牌)
1、准、洗、发、看牌
扑克游戏类
package com.app.comprehensive12.doudizhu.entity;
import java.util.ArrayList;
import java.util.Collections;
/*
扑克游戏类
*/
public class PokerGame {
// 首先定义一个静态的集合,用于存储组合好的牌(牌盒)
static ArrayList<String> cards = new ArrayList<>();
// 定义4个集合,分别用于存储:底牌、玩家1、玩家2、玩家3的牌
// 底牌(地主牌)
ArrayList<String> lordCards = new ArrayList<>();
// 玩家1
ArrayList<String> player1 = new ArrayList<>();
// 玩家2
ArrayList<String> player2 = new ArrayList<>();
// 玩家3
ArrayList<String> player3 = new ArrayList<>();
/*
准备牌:
可以用静态代码块来写准备牌的逻辑代码
静态代码块是随着类的加载而加载的,而且只执行一次。
为什么用静态代码块?
答:你想啊!那你和两位基友斗地主的时候,每打完一局,是不是需要重新洗牌、发牌..
不可能说打完一局,再打一局的时候,再买一副牌吧?
所以,用静态代码块,只执行一次准备牌的程序。
花色:"♦", "♣", "♥", "♠"
牌号:"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"
*/
static {
// 1.定义两个数组,分别用于存储牌的花色、号码
String[] cardColor = {"♦", "♣", "♥", "♠"};
String[] cardNumber = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
// 2.组合牌:花色+号码
// 外循环:遍历牌花色的数组,依次获取每一种花色
for (String c : cardColor) {
// 内循环:遍历牌号码的数组,依次获取每一个号码
for (String n : cardNumber) {
// 组合牌:花色+号码
// ♦3 ♦4 ..
String card = c + n;
// 将每张组合好的牌放进牌盒中
cards.add(card);
}
}
// 3.将大小王放进牌盒中
Collections.addAll(cards, "小王", "大王");
}
public PokerGame() {
// 洗牌:打乱牌的顺序
Collections.shuffle(cards);
// 发牌
sendCards();
// 看牌:遍历
lookCards("底牌", lordCards);
lookCards("钢脑壳", player1);
lookCards("大帅比", player2);
lookCards("蛋筒", player3);
}
/**
* 看牌
* @param playerName 玩家昵称
* @param list 每个玩家的牌的集合
*/
public void lookCards(String playerName, ArrayList<String> list) {
System.out.print(playerName + "——> ");
// 遍历当前玩家的牌的集合,依次获取每张牌
for (String card : list) {
// 打印牌到控制台,每张牌之间用空格隔开
System.out.print(card + " ");
}
// 当前玩家的所有牌打印完毕后,打印个换行
System.out.println();
}
/**
* 发牌
*/
public void sendCards() {
// 2.遍历牌盒,依次获取每张牌
for (int i = 0; i < cards.size(); i++) {
// i: 索引(牌序)
// 获取当前这张牌
String card = cards.get(i);
// a.先将3张底牌拿出
// 判断i是否小于等于2
if (i <= 2) { // i: 0 1 2
// 是,则将当前这张牌放进底牌集合中
lordCards.add(card);
// 结束当次循环的执行,进入下一次循环
continue;
}
// b.轮流给三个玩家发牌(求余法)
// 判断i%3是否等于0
if (i % 3 == 0) {
// 是,则给玩家1发牌
player1.add(card);
} else if (i % 3 == 1) { // 判断i%3是否等于1
// 是,则给玩家2发牌
player2.add(card);
} else {
// 否,说明以上两种情况都不符合,则给玩家3发牌
player3.add(card);
}
}
}
}
程序启动入口类
package com.app.comprehensive12.doudizhu.start;
import com.app.comprehensive12.doudizhu.entity.PokerGame;
public class App {
public static void main(String[] args) {
// 程序启动入口
new PokerGame();
}
}
测试结果
底牌——> ♠K ♦6 ♠7
钢脑壳——> ♥5 小王 ♣4 ♥2 ♣9 ♠3 ♦J ♠Q ♣3 ♥3 ♥A ♠J ♦Q ♣K ♠5 ♥J ♥K
大帅比——> ♥10 ♣6 ♥9 ♠2 ♥4 ♠9 ♦A ♥Q ♦8 ♣5 ♣8 ♥8 ♠4 ♣Q ♦7 ♠10 ♦2
蛋筒——> ♠6 ♦10 ♦3 ♦9 ♣A ♦4 ♦5 ♣10 ♣J ♠A 大王 ♦K ♠8 ♣7 ♥6 ♥7 ♣2
Process finished with exit code 0
分析2
-
那很多人打牌都有一个习惯,那就是给自己的牌进行排序!
-
因此分析1中的做法,是不符合的,发完牌,底牌和每个玩家的牌都是乱的!
1、准、洗、发、看牌
方式一:利用序号进行排序
- 如果原始数据的规律非常复杂,我们可以先手动排序让每一个数据跟唯一的序号产生对应关系。
- 序号就是数字,规律非常简单,后续的所有操作,我们以序号为准。
- 当真正需要操作原始数据的时候,再通过序号找到原始数据即可。
扑克游戏类
package com.app.comprehensive12.doudizhu2.entity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;
/*
扑克游戏类
*/
public class PokerGame {
/*
首先定义一个静态的HashMap集合,用于存储组合好的扑克牌(牌盒)
键:序号,值:扑克牌
此时我们只要把扑克牌与序号产生对应(键值对)关系就可以了,不需要按照序号进行排序,所以用HashMap集合即可!
*/
static HashMap<Integer, String> pokerList = new HashMap<>();
// 定义一个静态的ArrayList集合,用于存储每张扑克牌的序号
static ArrayList<Integer> serialNumberList = new ArrayList<>();
/*
定义4个TreeSet集合,分别用于存储:底牌、玩家1、玩家2、玩家3的所有扑克牌的序号
TreeSet集合默认会将数据进行升序排列
*/
TreeSet<Integer> lordCards = new TreeSet<>();
TreeSet<Integer> player1 = new TreeSet<>();
TreeSet<Integer> player2 = new TreeSet<>();
TreeSet<Integer> player3 = new TreeSet<>();
/*
准备牌:
可以用静态代码块来写准备牌的逻辑代码
静态代码块是随着类的加载而加载的,而且只执行一次。
为什么用静态代码块?
答:你想啊!那你和两位基友斗地主的时候,每打完一局,是不是需要重新洗牌、发牌..
不可能说打完一局,再打一局的时候,再买一副牌吧?
所以,用静态代码块,只执行一次准备牌的程序。
花色:"♦", "♣", "♥", "♠"
牌号:"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"
*/
static {
// 1.定义两个数组,分别用于存储扑克牌的所有花色、号码
String[] pokerColor = {"♦", "♣", "♥", "♠"};
String[] pokerNumber = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
/*
2.组合扑克牌:花色+号码
细节:先遍历号码数组,再遍历花色数组
为什么?
举例:比如用外循环先遍历号码数组,此时遍历到数字3,
然后再用内循环遍历花色数组,此时遍历到♦,拼接时,就会得到 ♦3,
此时内循环再次循环,就会得到♣,拼接时,就会得到♣3,
此时内循环再次循环,就会得到♥,拼接时,就会得到♥3,
此时内循环再次循环,就会得到♠,拼接时,就会得到♠3,
此时内循环结束,依次得到了 ♦3 ♣3 ♥3 ♠3 这四张扑克牌
然后外循环再遍历下一个数字,再拼接花色,依次类推!
*/
// 扑克牌的序号,从1开始
int serialNumber = 1;
// 外循环:遍历号码数组,依次获取每一个数字
for (String n : pokerNumber) {
// 内循环:遍历花色数组,依次获取每一种花色
for (String c : pokerColor) {
// 按照键值对关系,将 序号=扑克牌,添加到扑克牌盒中
pokerList.put(serialNumber, c + n);
// 将当前这张扑克牌的序号添加到序号集合中
serialNumberList.add(serialNumber);
// 序号+1,表示下一张扑克牌的序号
serialNumber++;
}
}
// 3.循环结束!52张扑克牌已准备好!
// 按照键值对关系将小王放进扑克牌盒中
pokerList.put(serialNumber, "小王");
// 将小王的序号添加到序号集合中
serialNumberList.add(serialNumber);
// 序号+1,表示下一张扑克牌的序号
serialNumber++;
// 按照键值对关系将大王放进扑克牌盒中
pokerList.put(serialNumber, "大王");
// 将大王的序号添加到序号集合中
serialNumberList.add(serialNumber);
}
public PokerGame() {
// 洗牌:打乱扑克牌的所有序号
Collections.shuffle(serialNumberList);
// 发牌
sendCards();
// 看牌
lookCards("底牌", lordCards);
lookCards("钢脑壳", player1);
lookCards("大帅比", player2);
lookCards("蛋筒", player3);
}
/**
* 看牌
* @param playerName 玩家名字
* @param ts 每个玩家的扑克牌序号集合
*/
public void lookCards(String playerName, TreeSet<Integer> ts) {
System.out.print(playerName + ": ");
// 遍历当前玩家的扑克牌序号的集合,依次获取每个序号
for (int serialNumber : ts) {
// 根据当前的序号(键)获取到对应的扑克牌(值)
String poker = pokerList.get(serialNumber);
// 打印扑克牌到控制台,每张扑克牌之间用空格隔开
System.out.print(poker + " ");
}
// 当前玩家的所有扑克牌都打印完之后,打印个换行
System.out.println();
}
/**
* 发牌
*/
public void sendCards() {
// 1.遍历序号集合,依次获取每个序号
for (int i = 0; i < serialNumberList.size(); i++) {
// i: 索引
// serialNumberList.get(i): 扑克牌的序号
// 获取当前这张扑克牌的序号
int serialNumber = serialNumberList.get(i);
// a.先将3张底牌的序号拿出
// 判断i是否小于等于2
if (i <= 2) { // i: 0 1 2
// 是,则将当前这张扑克牌的序号放进底牌集合中
lordCards.add(serialNumber);
// 结束当次循环的执行,进入下一次循环
continue;
}
// b.轮流给三个玩家发扑克牌的序号(求余法)
// 判断i%3是否等于0
if (i % 3 == 0) {
// 是,则给玩家1发
player1.add(serialNumber);
} else if (i % 3 == 1) { // 判断i%3是否等于1
// 是,则给玩家2发
player2.add(serialNumber);
} else {
// 否,说明以上两种情况都不符合,则给玩家3发
player3.add(serialNumber);
}
}
}
}
程序启动入口类
package com.app.comprehensive12.doudizhu2.start;
import com.app.comprehensive12.doudizhu2.entity.PokerGame;
public class App {
public static void main(String[] args) {
// 程序启动入口
new PokerGame();
}
}
测试结果
底牌: ♥3 ♦8 ♦9
钢脑壳: ♠3 ♦4 ♣5 ♦7 ♣7 ♠7 ♣8 ♥8 ♣9 ♥9 ♦10 ♣10 ♦J ♣J ♦Q ♠2 大王
大帅比: ♦3 ♣3 ♣4 ♦5 ♠5 ♦6 ♣6 ♠6 ♠8 ♠10 ♣Q ♥Q ♦A ♣A ♥A ♥2 小王
蛋筒: ♥4 ♠4 ♥5 ♥6 ♥7 ♠9 ♥10 ♥J ♠J ♠Q ♦K ♣K ♥K ♠K ♠A ♦2 ♣2
Process finished with exit code 0
分析3
1、准、洗、发、看牌
方式二:给每一张牌计算价值
扑克游戏类
package com.app.comprehensive12.doudizhu3.entity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
/*
扑克游戏类
*/
public class PokerGame {
/*
键:扑克牌,值:价值
因此,需要定义Map集合来存储键值对关系的数据
扑克牌 = 价值
*/
static HashMap<String, Integer> pokerValueList = new HashMap<>();
// 扑克牌盒
static ArrayList<String> pokerList = new ArrayList<>();
// 定义4个ArrayList集合,分别用于存储:底牌、玩家1、玩家2、玩家3的所有扑克牌
ArrayList<String> lordPoker = new ArrayList<>();
ArrayList<String> player1 = new ArrayList<>();
ArrayList<String> player2 = new ArrayList<>();
ArrayList<String> player3 = new ArrayList<>();
// 准备扑克牌
static {
// 将扑克牌的花色和号码用数组存储起来
String[] pokerColor = {"♦", "♣", "♥", "♠"};
String[] pokerNumber = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
// 将花色+号码组合起来,得到的就是扑克牌
for (String n : pokerNumber) {
for (String c : pokerColor) {
pokerList.add(c + n);
}
}
// 将大小王放进扑克牌盒中
Collections.addAll(pokerList, "小王", "大王");
// 定义扑克牌的价值
// 数字3~10的价值直接使用数字本身就好了!
pokerValueList.put("J", 11);
pokerValueList.put("Q", 12);
pokerValueList.put("K", 13);
pokerValueList.put("A", 14);
pokerValueList.put("2", 15);
pokerValueList.put("小王", 50);
pokerValueList.put("大王", 100);
}
public PokerGame() {
// 洗牌:打乱
Collections.shuffle(pokerList);
// 发牌
sendPokers();
// 排序
order(lordPoker);
order(player1);
order(player2);
order(player3);
// 看牌
lookPokers("底牌", lordPoker);
lookPokers("钢脑壳", player1);
lookPokers("大帅比", player2);
lookPokers("蛋筒", player3);
}
/**
* 排序
*
* @param list 玩家的所有扑克牌的集合
*/
public void order(ArrayList<String> list) {
// 自定义比较规则
Collections.sort(list, (o1, o2) -> {
/*
o1:表示当前要插入到有序序列中的牌
o2:表示已经存在有序序列中的牌
负数:o1小,插入到前面
正数:o1大,插入到后面
0: o1和o2一样大,此时需要按照花色进行排序
*/
// 1.计算o1的花色和价值
String color1;
int value1;
// 判断o1是否为小王 或 大王
if (checkPoker(o1)) {
// 是,则直接将小王或大王赋值给color1
color1 = o1;
// 获取扑克牌的价值
value1 = getValue(o1);
} else {
// 否,则从0索引截取到1索引
// 例如:♦3,从0到1,截取到3的花色:♦
color1 = o1.substring(0, 1);
value1 = getValue(o1);
}
// 2.计算o2的花色和价值
String color2;
int value2;
// 判断o1是否为小王 或 大王
if (checkPoker(o2)) {
// 是,则直接将小王或大王赋值给color2
color2 = o2;
value2 = getValue(o2);
} else {
// 否,则从0索引截取到1索引
color2 = o2.substring(0, 1);
value2 = getValue(o2);
}
// 3.比较o1和o2的价值
int i = value1 - value2;
// 如果o1和o2的价值一样大,此时需要按照花色进行排序
return i == 0 ? color1.compareTo(color2) : i;
});
}
/**
* 获取牌的价值
*
* @param poker 扑克牌
* @return 存在,则返回poker的价值,否则返回poker转换后的本身
*/
public int getValue(String poker) {
String number;
// 判断poker是否为大小王
if (checkPoker(poker)) {
// 是大小王,直接赋值给number
number = poker;
} else {
// 否,则说明不是大小王,则从1索引开始截取到结束
number = poker.substring(1);
}
// 判断number是否存在于Map集合中
if (pokerValueList.containsKey(number)) {
// 是,说明存在,返回number的价值
return pokerValueList.get(number);
} else {
// 否,说明不存在,则转换类型
return Integer.parseInt(number);
}
}
/**
* 判断牌是否为大小王
*
* @param poker 牌
* @return 是大小王,返回true,否则返回false
*/
public boolean checkPoker(String poker) {
if (poker.equals("小王") || poker.equals("大王")) {
return true;
}
return false;
}
/**
* 看牌
*
* @param playerName 玩家名字
* @param list 玩家的所有扑克牌的集合
*/
public void lookPokers(String playerName, ArrayList<String> list) {
System.out.print(playerName + ": ");
for (String poker : list) {
System.out.print(poker + " ");
}
System.out.println();
}
/**
* 发牌
*/
public void sendPokers() {
// 遍历牌盒,依次获取每张牌
for (int i = 0; i < pokerList.size(); i++) {
// i: 索引
// pokerList.get(i): 每张扑克牌
String poker = pokerList.get(i);
// 将底牌拿出来
if (i <= 2) {
lordPoker.add(poker);
continue;
}
// 轮流给三个玩家发牌
if (i % 3 == 0) {
player1.add(poker);
} else if (i % 3 == 1) {
player2.add(poker);
} else {
player3.add(poker);
}
}
}
}
程序启动入口类
package com.app.comprehensive12.doudizhu3.start;
import com.app.comprehensive12.doudizhu3.entity.PokerGame;
public class App {
public static void main(String[] args) {
// 程序启动入口
new PokerGame();
}
}
测试结果
底牌: ♣5 ♦J ♦2
钢脑壳: ♠3 ♣3 ♦6 ♠8 ♦8 ♥10 ♦10 ♠J ♥J ♠Q ♣Q ♦Q ♥K ♣A ♦A ♠2 ♣2
大帅比: ♥3 ♣4 ♦4 ♣6 ♣7 ♥7 ♣8 ♠9 ♣9 ♥9 ♦9 ♠10 ♣10 ♣J ♥Q ♦K ♠A
蛋筒: ♦3 ♠4 ♥4 ♠5 ♥5 ♦5 ♠6 ♥6 ♠7 ♦7 ♥8 ♠K ♣K ♥A ♥2 小王 大王
Process finished with exit code 0