斗地主
简介:
本篇内容接上篇,主要介绍主题的运行逻辑,这里先一段一段写,最后附上整个主题类
下一篇介绍判断工具类
最后介绍ai的思维类
二。主题
1.游戏开始,生成桌面信息(生产扑克牌,生成玩家登)
(1)先是准备桌面信息
这里没逻辑,一堆new set
TableTopInformation tableTopInformation = new TableTopInformation();
Scanner sc = new Scanner(System.in);
// List<Poker> poker = getPoker();
// tableTopInformation.setPoker(poker);
/**
* key 玩家名称
* value 玩家对应的牌
*/
Map<String,List<Poker>> map = new HashMap<>(3);
tableTopInformation.setPlayerPokerMap(map);
/**
* key 玩家名
* value 是否显示该玩家的手牌
*/
Map<String,Boolean> mapSB = new HashMap<>(3);
tableTopInformation.setMapSB(mapSB);
/**
* key 玩家名
* value 玩家对于的电脑ai
*/
Map<String,Ai> aiMap = new HashMap<>();
tableTopInformation.setAiMap(aiMap);
List<Player> playerList = new ArrayList<>();
tableTopInformation.setPlayerList(playerList);
Map<String,Integer> troopsMap = new HashMap<>();
tableTopInformation.setTroopsMap(troopsMap);
LinkedHashSet<String> player = new LinkedHashSet<>();
String wanJiaName = "玩家";
tableTopInformation.setWanJiaName(wanJiaName);
player.add(wanJiaName);
//游戏次数 第几次的意思,不是只玩参数 数量的次数
int round = 1;
GameOverBean gameOverBean = new GameOverBean();
gameOverBean.setIsContinue(false);
gameOverBean.setWinNum(0);
gameOverBean.setFailNum(0);
gameOverBean.setScore(0);
tableTopInformation.setGameOverBean(gameOverBean);
Boolean isContinue = true;
(2)生成玩家
这里规定了玩家人数 3 ,并给 ai 装脑子(脑子就是后面我们继承ai抽象类的实体类,这里用的是3代脑子 Ai_3)
while (true){
int index = (int) (Math.random() * (game_player.size() - 1));
String s = game_player.get(index);
player.add(s);
if (player.size() == 3){
break;
}
}
for (String s : player) {
map.put(s,new ArrayList<>());
mapSB.put(s,wanJiaName.equals(s));
if (!wanJiaName.equals(s)){
Ai_3 ai = new Ai_3();
ai.setName(s);
ai.setTableTopInformation(tableTopInformation);
aiMap.put(s,ai);
}
}
tableTopInformation.setPlayer(player);
(3)生成一副扑克牌
这里我自己发明了一个混乱模式(可能17张都是一种牌)。。。。。。。。看看就好,普通模式的话就传0 就行了
/**
* 获取不同模式下的牌
* 0 普通模式 54 张牌
* 1 混乱模式 54*54 张牌里取 54 张
* @param type
* @return
*/
private static List<Poker> getPoker(Integer type){
List<Poker> pokers = new ArrayList<>();
switch (type){
case 0:
pokers = getPoker();
break;
case 1:
for (int i = 0; i < 54; i++) {
pokers.addAll(getPoker());
}
Collections.shuffle(pokers);
pokers = pokers.subList(0,54);
break;
default:
break;
}
return pokers;
}
2.游戏开始
这里play这个方法就是提出来的,后面一步一步介绍
while (isContinue){
GameOverBean play = play(tableTopInformation, sc);
isContinue = play.getIsContinue();
}
(1)先把桌面信息get出来,方便一点
//基础数据
List<Poker> poker = getPoker(0);
Map<String,List<Poker>> map = tableTopInformation.getPlayerPokerMap();
String wanJiaName = tableTopInformation.getWanJiaName();
Map<String,Boolean> mapSB = tableTopInformation.getMapSB();
LinkedHashSet<String> player = tableTopInformation.getPlayer();
Map<String,Integer> troopsMap = tableTopInformation.getTroopsMap();
List<Player> playerList = tableTopInformation.getPlayerList();
Map<String,Ai> aiMap = tableTopInformation.getAiMap();
GameOverBean gameOverBean = tableTopInformation.getGameOverBean();
Integer beiShu = 0;
/**
* key 玩家名
* value 玩家对应的出牌记录
*/
Map<String,StringBuilder> mapCP = new LinkedHashMap<>();
tableTopInformation.setMapCP(mapCP);
String maxPlayer = "";
String maxPoker = "";
(2)洗牌发牌,这里就是打乱顺序和拆分牌
//洗牌 打乱顺序 + 清空玩家手牌 + 清空 playerList
Collections.shuffle(poker);
for (List<Poker> value : map.values()) {
value.clear();
}
playerList.clear();
/**
* 分出地主牌
*/
List<Poker> poker0 = new ArrayList<>(poker.subList(0, 3));
// poker.removeAll(poker0);
poker = poker.subList(3,poker.size());
//发牌
licensing(map,poker);
//key 抢到地主的人
String key = wanJiaName;
//给地主发地主牌
panDuanDiZhu(map,key,poker0,mapSB,player);
/**
* 发牌
* @param map
* @param poker
*/
private static void licensing(Map<String,List<Poker>> map,List<Poker> poker){
int n = 0;
Map<Integer, String> map1 = new HashMap<>(3);
for (String s : map.keySet()) {
map1.put(n,s);
n++;
}
n = 0;
for (Poker p : poker) {
String put = map1.get(n);
List<Poker> pokers = map.get(put);
pokers.add(p);
if (n == 2){
n = 0;
}else {
n++;
}
}
}
private static void panDuanDiZhu(Map<String,List<Poker>> map,String key,List<Poker> poker0,Map<String,Boolean> mapSB,LinkedHashSet<String> player){
List<Poker> remove = map.remove(key);
remove.addAll(poker0);
map.put(key,remove);
}
(3)给玩家设置出牌顺序,在原有的基础上,地主先出,再排序
int priority = 1;
for (String s : player) {
Player p = new Player();
p.setName(s);
Integer troopsType = s.contains(key) ? 0 : 2;
troopsMap.put(s,troopsType);
p.setTroopsType(troopsType);
p.setPriority(priority);
playerList.add(p);
priority++;
}
//排序 优先级越小,排序越靠前
playerList = playerList.stream().sorted(Comparator.comparing(Player::getPriority)).collect(Collectors.toList());
(4)接下来就是循环出牌,直到一方手牌为0
【1】判断手牌数方法
private static Integer pokerSize(List<Poker> list){
Integer sum = list.stream().filter(item -> item.getShow()).collect(Collectors.toList()).size();
return sum;
}
【2】展示桌面信息方法
private static void showTableTop(Map<String,StringBuilder> mapCP,List<Poker> poker0,Map<String,List<Poker>> map,String maxPlayer,String maxPoker,String key){
String s0 = "";
if (!"".equals(maxPlayer)){
s0 = " 当前" + (key.equals(maxPlayer) ? "(地主):" : ":") + maxPlayer + "," + maxPoker;
}
System.out.println("地主牌:" + poker0.toString() + s0);
for (String s : mapCP.keySet()) {
System.out.println((key.equals(s) ? "(地主)" : "") + s + "("+pokerSize(map.get(s))+")" + ":" + mapCP.get(s).toString());
}
}
效果如下
【3】校验出牌是否符合逻辑方法
斗地主的出牌规则应该知道赛,这里就是按照规则判断的
/**
* 判断是否符合出牌规则
* x 单 1
* xx 对 2
* xxxy 三带一 3
* xxxx Ww 炸弹 4
* abcde...顺子 5
* aabbcc...连对 6
* aaabbb... xy... 飞机 7
* @param s
* @return null 格式错误 1 单牌 2 对子 3 三带一 4 炸弹 5 顺子 6 连对 7 飞机
*/
public static Integer panDuanGZ(String s){
Integer b = null;
String[] split = s.split("");
Pattern p;
Matcher matcher;
if (split.length == 0){
return b;
}
else if (split.length == 1){
p = Pattern.compile(CANONICAL_X);
matcher = p.matcher(s);
boolean b1 = matcher.find();
if (b1){
b = 1;
}
}
else if (split.length == 2){
if (s.equals("Ww") || s.equals("wW")){
b = 4;
}else{
p = Pattern.compile(CANONICAL_XX);
matcher = p.matcher(s);
Boolean b1 = matcher.find();
if (b1){
b = 2;
}
}
}
else if (split.length == 3){
return b;
}
else if (split.length == 4){
p = Pattern.compile(CANONICAL_XXXX);
matcher = p.matcher(s);
Boolean b1 = matcher.find();
p = Pattern.compile(CANONICAL_XXXY);
matcher = p.matcher(s);
Boolean b2 = matcher.find();
if (b1){
b = 4;
}else if (b2){
b = 3;
}
}
else if (split.length > 4){
//验证超级炸弹
p = Pattern.compile(CANONICAL_XXXX_Min);
matcher = p.matcher(s);
Boolean cjzd = matcher.find();
if (cjzd && matcher.group().length() == s.length()){
return 4;
}
String s1 = "";
int num = 0;
String newStr = "";
//先验证飞机
p = Pattern.compile(CANONICAL_XXX);
matcher = p.matcher(s);
while (matcher.find()){
String group = matcher.group();
num++;
s1 +=group;
newStr += group.split("")[0];
}
Boolean aBoolean1 = puanDuanLX(newStr, 2);
if (s.length() - s1.length() == num && aBoolean1){
return 7;
}
//验证连对
p = Pattern.compile(CANONICAL_XX);
matcher = p.matcher(s);
Boolean b6 = false;
while (matcher.find()){
b6 = true;
String group = matcher.group();
s1 +=group;
newStr += group.split("")[0];
}
if (b6){
Boolean aBoolean2 = puanDuanLX(newStr, 3);
if (aBoolean2){
return 6;
}
}
//验证顺子
Boolean aBoolean = puanDuanLX(s, 5);
if (aBoolean){
return 5;
}
}
return b;
}
【4】再比较牌的大小
/**
* 判断出牌是否能接上最大牌面
* 判断是否为炸弹,为炸弹直接比面值
* 不为炸弹先比较类型是否相同
* 相同类型比较 各自面值
* @param max
* @param next
* @return
*/
private static Boolean panDuanXT(String max,String next){
Pattern p;
Matcher matcher;
p = Pattern.compile(CANONICAL_NP);
matcher = p.matcher(next);
boolean b1 = matcher.find();
//包含非牌面符号为fales
if (b1){
return false;
}
//先手不出 为false
if ("".equals(max) && "-".equals(next)){
return false;
}
//后手不出为 true
if (!"".equals(max) && "-".equals(next)){
return true;
}
Boolean b = false;
try{
Integer maxI = panDuanGZ(max);
Integer nextI = panDuanGZ(next);
if (nextI == 4 || (maxI.equals(nextI) && max.length() == next.length()) ){
b = true;
}
Integer maxValue = PokerPanDuan.countValue(max, maxI);
Integer nextValue = PokerPanDuan.countValue(next, nextI);
if (b){
b = nextValue > maxValue;
}
}catch (Exception e){
b = false;
}finally {
return b;
}
}
【5】判断是否能出牌,也就是手牌有没有你输入的这些牌,再出牌,这里是将已经打出的牌让手牌不显示,并不是ai判断怎么出牌的逻辑,这个逻辑后面后讲
public static Boolean outPoker(List<Poker> pokers,String s){
Boolean b = true;
String[] split = s.split("");
List<Poker> updateList = new ArrayList<>();
for (String s1 : split) {
for (Poker poker : pokers) {
if (poker.getName().equals(s1) && poker.getShow()){
updateList.add(poker);
poker.setShow(false);
break;
}
}
}
if (!"-".equals(s) && updateList.size() != split.length){
b = false;
for (Poker poker : updateList) {
poker.setShow(true);
}
}
return b;
}
【6】判断剩余手牌数,手牌数为0,一轮游戏就结束了
private static Integer pokerSize(List<Poker> list){
Integer sum = list.stream().filter(item -> item.getShow()).collect(Collectors.toList()).size();
return sum;
}
3.以上就是该主体的基本代码块,下面直接附上整个代码
package com.fxp.linuxdemo.game.poker;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
import com.fxp.linuxdemo.domain.bean.Poker;
import com.fxp.linuxdemo.game.poker.ai.Ai_2;
import com.fxp.linuxdemo.game.poker.ai.Ai_3;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @Author: fxp
* @Date: 2023/3/14 14:56
* @Description
*/
public class DouDiZhu {
/**
* 测试
*/
private static final String CANONICAL_test = "(\\d)\\1{2}";
/**
* 正则单牌
*/
private static final String CANONICAL_NP = "[^2-9XJQKAWw\\-\\*]";
/**
* 正则单牌
*/
private static final String CANONICAL_X = "[2-9XJQKAWw\\*]";
/**
* 正则对子
*/
private static final String CANONICAL_XX = "([2-9XJQKAWw\\*])\\1{1}";
/**
* 正则三个
*/
private static final String CANONICAL_XXX = "([2-9XJQKAWw\\*])\\1{2}";
/**
* 正则炸弹
*/
private static final String CANONICAL_XXXX = "([2-9XJQKAWw\\*])\\1{3}";
/**
* 正则至少重复4次
*/
private static final String CANONICAL_XXXX_Min = "([2-9XJQKAWw\\*])\\1{4,}";
/**
* 正则三带一
*/
private static final String CANONICAL_XXXY = "([2-9XJQKAWw\\*])\\1{2}[2-9XJQKAWw\\*]";
/**
* 顺子
*/
private static final String CANONICAL_ABCDE = "(3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|9(?=X)|X(?=J)|J(?=Q)|Q(?=K)|K(?=A)){4,}";
/**
* 顺子
*/
private static final String CANONICAL_EDCBA = "((?<=3)4|(?<=4)5|(?<=5)6|(?<=6)7|(?<=7)8|(?<=8)9|(?<=9)X|(?<=X)J|(?<=J)Q|(?<=Q)K|(?<=K)A){4,}";
/**
* 连续 至少两次
*/
private static final String CANONICAL_ABCDE_N = "(3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|9(?=X)|X(?=J)|J(?=Q)|Q(?=K)|K(?=A)){N,}";
/**
* 连续 至少两次
*/
private static final String CANONICAL_EDCBA_N = "((?<=3)4|(?<=4)5|(?<=5)6|(?<=6)7|(?<=7)8|(?<=8)9|(?<=9)X|(?<=X)J|(?<=J)Q|(?<=Q)K|(?<=K)A){N,}";
private static final List<String> game_player = new ArrayList<String>(){
{
add("吊炸天");
add("拖拉机");
add("煤炭");
add("输不起");
add("再来");
add("你大爷");
add("二愣子");
add("最美富二代");
}
};
public static final Map<String, Integer> valueMap = new HashMap<String, Integer>(){
{
put("3",3);
put("4",4);
put("5",5);
put("6",6);
put("7",7);
put("8",8);
put("9",9);
put("X",10);
put("J",11);
put("Q",12);
put("K",13);
put("A",14);
put("2",15);
put("w",16);
put("W",17);
}
};
private static List<Poker> getPoker(){
List<Poker> pokers = new ArrayList<>();
for (int i = 1; i < 15; i++) {
if (i == 14){
for (int j = 4; j < 6; j++) {
Poker p = new Poker();
p.setName(j == 4 ? "w" : "W" );
p.setValue(12 + j);
pokers.add(p);
}
}else {
for (int j = 0; j < 4; j++) {
Poker p = new Poker();
switch (i){
case 1:
p.setName("A");
p.setValue(14);
break;
case 2:
p.setName("2");
p.setValue(15);
break;
case 10:
p.setName("X");
p.setValue(10);
break;
case 11:
p.setName("J");
p.setValue(11);
break;
case 12:
p.setName("Q");
p.setValue(12);
break;
case 13:
p.setName("K");
p.setValue(13);
break;
default:
p.setName(i + "");
p.setValue(i);
break;
}
p.setType(j);
pokers.add(p);
}
}
}
return pokers;
}
/**
* 获取不同模式下的牌
* 0 普通模式 54 张牌
* 1 混乱模式 54*54 张牌里取 54 张
* @param type
* @return
*/
private static List<Poker> getPoker(Integer type){
List<Poker> pokers = new ArrayList<>();
switch (type){
case 0:
pokers = getPoker();
break;
case 1:
for (int i = 0; i < 54; i++) {
pokers.addAll(getPoker());
}
Collections.shuffle(pokers);
pokers = pokers.subList(0,54);
break;
default:
break;
}
return pokers;
}
/**
* 发牌
* @param map
* @param poker
*/
private static void licensing(Map<String,List<Poker>> map,List<Poker> poker){
int n = 0;
Map<Integer, String> map1 = new HashMap<>(3);
for (String s : map.keySet()) {
map1.put(n,s);
n++;
}
n = 0;
for (Poker p : poker) {
String put = map1.get(n);
List<Poker> pokers = map.get(put);
pokers.add(p);
if (n == 2){
n = 0;
}else {
n++;
}
}
}
private static void panDuanDiZhu(Map<String,List<Poker>> map,String key,List<Poker> poker0,Map<String,Boolean> mapSB,LinkedHashSet<String> player){
List<Poker> remove = map.remove(key);
remove.addAll(poker0);
map.put(key,remove);
// Boolean b = mapSB.remove(key);
// mapSB.put("(地主)" + key,b);
//
// List<String> list = new ArrayList<>(player);
// list.remove(key);
// list.add(0,"(地主)" + key);
// player.clear();
// player.addAll(list);
}
public static void show(Map<String,List<Poker>> map,Map<String,Boolean> mapSB){
for (String s : map.keySet()) {
List<Poker> pokers = map.get(s);
if (mapSB.get(s)){
System.out.println(s + ":" + showPokers(pokers));
}else {
System.out.println(s + ":" + pokerSize(pokers) + "张");
}
}
}
public static void show(Map<String,List<Poker>> map,Map<String,Boolean> mapSB,String user){
for (String s : map.keySet()) {
List<Poker> pokers = map.get(s);
if (mapSB.get(s)){
System.out.println(s + ":" + showPokers(pokers));
}else {
System.out.println(s + ":" + pokerSize(pokers) + "张");
}
}
}
public static void show(List<Poker> list,Boolean b){
if (b){
System.out.println(":" + showPokers(list));
}else {
System.out.println(":" + pokerSize(list) + "张");
}
}
public static String showPokers(List<Poker> list){
list = list.stream().sorted(Comparator.comparing(Poker::getValue).reversed()).collect(Collectors.toList());
String s = "";
for (Poker poker : list) {
if (poker.getShow()){
s += poker.getName();
}
}
return s;
}
public static Boolean outPoker(List<Poker> pokers,String s){
Boolean b = true;
String[] split = s.split("");
List<Poker> updateList = new ArrayList<>();
for (String s1 : split) {
for (Poker poker : pokers) {
if (poker.getName().equals(s1) && poker.getShow()){
updateList.add(poker);
poker.setShow(false);
break;
}
}
}
if (!"-".equals(s) && updateList.size() != split.length){
b = false;
for (Poker poker : updateList) {
poker.setShow(true);
}
}
return b;
}
public static void clear() throws AWTException{
Robot ro = new Robot();
ro.delay(100);//延时
ro.mousePress(InputEvent.BUTTON3_MASK);//单机鼠标右键
ro.mouseRelease(InputEvent.BUTTON3_MASK);//松开右键
ro.keyPress(KeyEvent.VK_CONTROL);//按ctrl键
ro.keyPress(KeyEvent.VK_R);//按R
ro.keyRelease(KeyEvent.VK_R);//松开R
ro.keyRelease(KeyEvent.VK_CONTROL);//松开ctrl
ro.delay(100);//延时
}
public static void main(String[] args) throws AWTException, InterruptedException {
TableTopInformation tableTopInformation = new TableTopInformation();
Scanner sc = new Scanner(System.in);
List<Poker> poker = getPoker();
// tableTopInformation.setPoker(poker);
/**
* key 玩家名称
* value 玩家对应的牌
*/
Map<String,List<Poker>> map = new HashMap<>(3);
tableTopInformation.setPlayerPokerMap(map);
/**
* key 玩家名
* value 是否显示该玩家的手牌
*/
Map<String,Boolean> mapSB = new HashMap<>(3);
tableTopInformation.setMapSB(mapSB);
/**
* key 玩家名
* value 玩家对于的电脑ai
*/
Map<String,Ai> aiMap = new HashMap<>();
tableTopInformation.setAiMap(aiMap);
List<Player> playerList = new ArrayList<>();
tableTopInformation.setPlayerList(playerList);
Map<String,Integer> troopsMap = new HashMap<>();
tableTopInformation.setTroopsMap(troopsMap);
LinkedHashSet<String> player = new LinkedHashSet<>();
String wanJiaName = "玩家";
tableTopInformation.setWanJiaName(wanJiaName);
player.add(wanJiaName);
int num = 1;
while (true){
int index = (int) (Math.random() * (game_player.size() - 1));
String s = game_player.get(index);
player.add(s);
if (player.size() == 3){
break;
}
}
for (String s : player) {
map.put(s,new ArrayList<>());
mapSB.put(s,wanJiaName.equals(s));
if (!wanJiaName.equals(s)){
Ai_3 ai = new Ai_3();
ai.setName(s);
ai.setTableTopInformation(tableTopInformation);
aiMap.put(s,ai);
}
}
tableTopInformation.setPlayer(player);
//游戏次数
int round = 1;
GameOverBean gameOverBean = new GameOverBean();
gameOverBean.setIsContinue(false);
gameOverBean.setWinNum(0);
gameOverBean.setFailNum(0);
gameOverBean.setScore(0);
tableTopInformation.setGameOverBean(gameOverBean);
Boolean isContinue = true;
while (isContinue){
GameOverBean play = play(tableTopInformation, sc);
isContinue = play.getIsContinue();
}
sc.close();
System.out.println("gameOverBean = " + gameOverBean.toString());
}
private static GameOverBean play(TableTopInformation tableTopInformation,Scanner sc) throws AWTException, InterruptedException {
//基础数据
List<Poker> poker = getPoker(0);
Map<String,List<Poker>> map = tableTopInformation.getPlayerPokerMap();
String wanJiaName = tableTopInformation.getWanJiaName();
Map<String,Boolean> mapSB = tableTopInformation.getMapSB();
LinkedHashSet<String> player = tableTopInformation.getPlayer();
Map<String,Integer> troopsMap = tableTopInformation.getTroopsMap();
List<Player> playerList = tableTopInformation.getPlayerList();
Map<String,Ai> aiMap = tableTopInformation.getAiMap();
GameOverBean gameOverBean = tableTopInformation.getGameOverBean();
Integer beiShu = 0;
/**
* key 玩家名
* value 玩家对应的出牌记录
*/
Map<String,StringBuilder> mapCP = new LinkedHashMap<>();
tableTopInformation.setMapCP(mapCP);
String maxPlayer = "";
String maxPoker = "";
//洗牌 打乱顺序 + 清空玩家手牌 + 清空 playerList
Collections.shuffle(poker);
for (List<Poker> value : map.values()) {
value.clear();
}
playerList.clear();
/**
* 分出地主牌
*/
List<Poker> poker0 = new ArrayList<>(poker.subList(0, 3));
// poker.removeAll(poker0);
poker = poker.subList(3,poker.size());
//发牌
licensing(map,poker);
/**
* 下面方法,写抢地主时再打开
*/
//展示桌面,用来抢地主
// show(map,mapSB);
//key 抢到地主的人
String key = wanJiaName;
//给地主发地主牌
panDuanDiZhu(map,key,poker0,mapSB,player);
int priority = 1;
for (String s : player) {
Player p = new Player();
p.setName(s);
Integer troopsType = s.contains(key) ? 0 : 2;
troopsMap.put(s,troopsType);
p.setTroopsType(troopsType);
p.setPriority(priority);
playerList.add(p);
priority++;
}
//排序 优先级越小,排序越靠前
playerList = playerList.stream().sorted(Comparator.comparing(Player::getPriority)).collect(Collectors.toList());
for (Player s : playerList) {
mapCP.put(s.getName(),new StringBuilder(""));
}
// show(map,mapSB);
Boolean end = false;
while (!end){
for (Player p : playerList) {
//s 玩家名称
String s = p.getName();
boolean isDiZhu = key.equals(s);
boolean isWanJia = s.contains(wanJiaName);
if (s.equals(maxPlayer)){
maxPlayer = "";
maxPoker = "";
}
clear();
showTableTop(mapCP,poker0,map,maxPlayer,maxPoker,key);
List<Poker> pokers = map.get(s);
if (isWanJia){
System.out.print(s + ",请出牌");
}else {
System.out.print(s + ",出牌");
}
show(pokers,mapSB.get(s));
String next = "";
if (isWanJia){
next = sc.next();
}else {
Ai ai = aiMap.get(s);
String s1 = showPokers(pokers);
next = ai.outPoker(OutPokerVo.builder().s(s1).type(null).max(maxPoker).maxPlayer(maxPlayer).build());
//模拟思考 1 秒
Thread.sleep(500);
System.out.println(next);
//出牌后停3秒
Thread.sleep(500);
}
Boolean b = true;
//校验
//出牌规则是否正确
//是否大于最大排
while (true){
b = true;
if(!"".equals(maxPoker)){
b = panDuanXT(maxPoker, next);
}
if (b){
Integer integer = PokerPanDuan.panDuanGZ(next);
if (null == integer && !"-".equals(next)){
System.out.println("出牌不复合规则,请重新出牌");
next = sc.next();
continue;
}
b = outPoker(pokers, next);
if (b){
if (!"-".equals(next)){
maxPlayer = s;
maxPoker = next;
if (4 == integer){
beiShu++;
}
}
break;
}else {
System.out.println("出牌不复合规则,请重新出牌");
next = sc.next();
}
}else {
System.out.println("出牌不复合规则,请重新出牌");
next = sc.next();
}
}
Integer sy = pokerSize(pokers);
if ( sy == 0){
end = true;
break;
}
StringBuilder stringBuilder = mapCP.get(s);
if (!"".equals(stringBuilder.toString())){
stringBuilder.append(",");
}
stringBuilder.append(next);
mapCP.put(s,stringBuilder);
}
}
System.out.println("恭喜 " + maxPlayer + " 获胜,是否继续,1 继续");
String next = sc.next();
gameOverBean.setIsContinue("1".equals(next));
Integer integer = panDuanVictoryOrDefeat(troopsMap, maxPlayer, wanJiaName, beiShu);
gameOverBean.setScore(gameOverBean.getScore() + integer);
if (integer > 0){
gameOverBean.setWinNum(gameOverBean.getWinNum() + 1);
}else {
gameOverBean.setFailNum(gameOverBean.getFailNum() + 1);
}
return gameOverBean;
}
/**
* 判断胜负
* 返回得分
* @return
*/
private static Integer panDuanVictoryOrDefeat(Map<String,Integer> troopsMap,String maxPlayer,String wanJia,Integer beiShu){
Integer i = 0;
Integer deiFen = 1;
while (beiShu > 0){
deiFen *= 2;
beiShu--;
}
//玩家是地主时胜利 0 地主 1 地主队 2 农民队
int diZhuNum = 0;
int nongMingNum = 0;
for (Integer value : troopsMap.values()) {
if (1 == value || 0 == value){
diZhuNum++;
}else if (2 == value){
nongMingNum++;
}
}
Integer integer1 = troopsMap.get(maxPlayer);
Integer integer2 = troopsMap.get(wanJia);
if (null == integer2){
integer2 = troopsMap.get("(地主)" + wanJia);
}
Boolean shenLi = false;
if (maxPlayer.equals(wanJia)){
shenLi = true;
}else if (integer1.equals(integer2)){
shenLi = true;
}else if (integer1 == 0 && integer2 == 1){
shenLi = true;
}else if (integer1 == 1 && integer2 == 0){
shenLi = true;
}
if (shenLi){
//胜利
if (integer2 == 0 || integer2 == 1){
i = nongMingNum * deiFen / diZhuNum;
}else {
i = deiFen;
}
}else {
//失败
if (integer2 == 0 || integer2 == 1){
i = -1 * (nongMingNum * deiFen / diZhuNum);
}else {
i = -1 * deiFen;
}
}
return i;
}
private static void showTableTop(Map<String,StringBuilder> mapCP,List<Poker> poker0,Map<String,List<Poker>> map,String maxPlayer,String maxPoker,String key){
String s0 = "";
if (!"".equals(maxPlayer)){
s0 = " 当前" + (key.equals(maxPlayer) ? "(地主):" : ":") + maxPlayer + "," + maxPoker;
}
System.out.println("地主牌:" + poker0.toString() + s0);
for (String s : mapCP.keySet()) {
System.out.println((key.equals(s) ? "(地主)" : "") + s + "("+pokerSize(map.get(s))+")" + ":" + mapCP.get(s).toString());
}
}
// public static void main(String[] args) throws AWTException {
// // TODO Auto-generated method stub
// System.out.println("欢迎来到Narnat的水果店");
// System.out.println("请在控制台内单击 enter 以继续:");
// System.out.println("...................");
// Scanner sc = new Scanner(System.in);
// String s = sc.nextLine();
// clear();
// }
private static Integer pokerSize(List<Poker> list){
Integer sum = list.stream().filter(item -> item.getShow()).collect(Collectors.toList()).size();
return sum;
}
/**
* 计算牌面
* 最大面值 468
* @return
*/
private static Integer CalculateDeck(String s){
Integer i = 0;
String[] split = s.split("");
return i;
}
// public static void main(String[] args) {
// Boolean aBoolean = panDuanXT("6666", "55555");
// System.out.println("aBoolean = " + aBoolean);
// Integer integer = PokerPanDuan.panDuanGZ("55555");
// System.out.println("integer = " + integer);
// }
public static Boolean test(String s){
Pattern p;
Matcher matcher;
p = Pattern.compile(CANONICAL_test);
matcher = p.matcher(s);
Boolean b1 = matcher.find();
return b1;
}
/**
* 判断是否符合出牌规则
* x 单 1
* xx 对 2
* xxxy 三带一 3
* xxxx Ww 炸弹 4
* abcde...顺子 5
* aabbcc...连对 6
* aaabbb... xy... 飞机 7
* @param s
* @return null 格式错误 1 单牌 2 对子 3 三带一 4 炸弹 5 顺子 6 连对 7 飞机
*/
private static Integer panDuanGZ(String s){
Integer b = null;
String[] split = s.split("");
Pattern p;
Matcher matcher;
if (split.length == 0){
return b;
}
else if (split.length == 1){
p = Pattern.compile(CANONICAL_X);
matcher = p.matcher(s);
boolean b1 = matcher.find();
if (b1){
b = 1;
}
}
else if (split.length == 2){
if (s.equals("Ww") || s.equals("wW")){
b = 4;
}else{
p = Pattern.compile(CANONICAL_XX);
matcher = p.matcher(s);
Boolean b1 = matcher.find();
if (b1){
b = 2;
}
}
}
else if (split.length == 3){
return b;
}
else if (split.length == 4){
int num_W = 0;
int num_w = 0;
String[] split1 = s.split("");
for (String s1 : split1) {
if ("w".equals(s1)){
num_w++;
}else if ("W".equals(s1)){
num_W++;
}
}
if (num_w != 0 && num_W != 0 && num_w == num_W && num_w + num_W == split1.length){
b = 4;
return b;
}
p = Pattern.compile(CANONICAL_XXXX);
matcher = p.matcher(s);
Boolean b1 = matcher.find();
p = Pattern.compile(CANONICAL_XXXY);
matcher = p.matcher(s);
Boolean b2 = matcher.find();
if (b1){
b = 4;
}else if (b2){
b = 3;
}
}
else if (split.length > 4){
int num_W = 0;
int num_w = 0;
String[] split1 = s.split("");
for (String s1 : split1) {
if ("w".equals(s1)){
num_w++;
}else if ("W".equals(s1)){
num_W++;
}
}
if (num_w != 0 && num_W != 0 && num_w == num_W){
b = 4;
return b;
}
p = Pattern.compile(CANONICAL_XXXX_Min);
matcher = p.matcher(s);
Boolean b1 = matcher.find();
if (b1){
b = 4;
return b;
}
String s1 = "";
int num = 0;
String newStr = "";
//先验证飞机
p = Pattern.compile(CANONICAL_XXX);
matcher = p.matcher(s);
while (matcher.find()){
String group = matcher.group();
num++;
s1 +=group;
newStr += group.split("")[0];
}
Boolean aBoolean1 = puanDuanLX(newStr, 2);
if (s.length() - s1.length() == num && aBoolean1){
return 7;
}
//验证连对
p = Pattern.compile(CANONICAL_XX);
matcher = p.matcher(s);
while (matcher.find()){
String group = matcher.group();
s1 +=group;
newStr += group.split("")[0];
}
Boolean aBoolean2 = puanDuanLX(newStr, 3);
if (aBoolean2){
return 6;
}
//验证顺子
Boolean aBoolean = puanDuanLX(s, 5);
if (aBoolean){
return 5;
}
}
return b;
}
/**
* 判断连续
* @param s 需要判断的字符串
* @param num 至少连续的次数
* @return
*/
public static Boolean puanDuanLX(String s ,int num){
Boolean b = false;
Pattern p;
Matcher matcher;
//验证顺子
p = Pattern.compile(CANONICAL_ABCDE_N.replace("N",(num-1) + ""));
matcher = p.matcher(s);
boolean b1 = matcher.find();
String group1 = "";
if (b1){
group1 = matcher.group();
}
p = Pattern.compile(CANONICAL_EDCBA_N.replace("N",(num-1) + ""));
matcher = p.matcher(s);
boolean b2 = matcher.find();
String group2 = "";
if (b2){
group2 = matcher.group();
}
if (group1.length() + group2.length() == s.length() * 2 - 2){
b = true;
}
return b;
}
/**
* 计算面值
* 当为非炸弹时,面值为各值相加
* 当为炸弹时,面值为个值相加 + 一副牌总值
* 当为王炸时,面值为两副牌总值
* 一副牌总值 416 (除大小王)
* @return
*/
private static Integer countValue(String s,Integer type){
Integer value = 0;
if (4 == type){
value += 416;
if (2 == s.length()){
value += 416;
}
}
if (type == 3 || type == 7){
Pattern p = Pattern.compile(CANONICAL_XXX);
Matcher m = p.matcher(s);
while (m.find()){
String group = m.group();
value = simpleCountValue(group,value);
}
}else {
value = simpleCountValue(s,value);
}
return value;
}
private static Integer simpleCountValue(String s,Integer value){
if (null == value){
value = 0;
}
String[] split = s.split("");
for (String s1 : split) {
value += valueMap.get(s1);
}
return value;
}
/**
* 判断出牌是否能接上最大牌面
* 判断是否为炸弹,为炸弹直接比面值
* 不为炸弹先比较类型是否相同
* 相同类型比较 各自面值
* @param max
* @param next
* @return
*/
private static Boolean panDuanXT(String max,String next){
Pattern p;
Matcher matcher;
p = Pattern.compile(CANONICAL_NP);
matcher = p.matcher(next);
boolean b1 = matcher.find();
//包含非牌面符号为fales
if (b1){
return false;
}
//先手不出 为false
if ("".equals(max) && "-".equals(next)){
return false;
}
//后手不出为 true
if (!"".equals(max) && "-".equals(next)){
return true;
}
Boolean b = false;
try{
Integer maxI = panDuanGZ(max);
Integer nextI = panDuanGZ(next);
if (nextI == 4 || (maxI.equals(nextI) && max.length() == next.length()) ){
b = true;
}
Integer maxValue = PokerPanDuan.countValue(max, maxI);
Integer nextValue = PokerPanDuan.countValue(next, nextI);
if (b){
b = nextValue > maxValue;
}
}catch (Exception e){
b = false;
}finally {
return b;
}
}
}