斗地主
简介:
***
本篇内容重在熟练正则判断,以及学习创作思路使用,摸鱼是开玩笑的。
一。准备工作
这里我们先创建项目,做一些基础工作,例如创建实体之类的
1.实体
(1)首先就是扑克牌实体
这段都比较好理解(废话)
name -> 牌的名字,可以是单张牌,也可以是组合牌,例如 3 ,3334
value -》牌的面值,用于比较大小
type -》 牌的种类,区分单排,对子,之类的,这个主要是个ai用的
j_value -》这个什么值来着的忘了,当时想扩展ai功能的,后来没做了给忘了
size -》牌的长度,实际就是name字段的长度
show -》是否展示,这里出了牌,并不是从集合中去掉,而是让他不展示,至于好处吗,忘了当时为啥选择这个
@Data
public class Poker {
private String name;
private Integer value;
private Integer type;
private String j_value;
private Integer size;
private Boolean show = true;
@Override
public String toString(){
return name;
}
}
(2)然后就是游戏结束返回类
@Data
public class GameOverBean {
/**
* 游戏结束是否继续
*/
private Boolean isContinue;
/**
* 胜利次数
*/
private Integer winNum;
/**
* 失败次数
*/
private Integer failNum;
/**
* 得分
*/
private Integer score;
}
(3)出牌类
场上最大牌,就是 A 出6,B 不要,6就是最大牌,A 就是最大牌玩家
@Data
@Builder
public class OutPokerVo {
/**
* 自己的手牌
*/
private String s;
/**
* 场上最大牌面的类型
*/
private Integer type;
/**
* 场上最大牌面
*/
private String max;
/**
* 场上最大牌的玩家
*/
private String maxPlayer;
}
(4)玩家类
优先级就是用来比较出牌顺序的
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Player {
private String name;
/**
* 队伍编号
* 0 地主
* 1 地主队伍
* 2 农民队伍
*/
private Integer troopsType;
/**
* 优先级
*/
private Integer priority;
public Integer getPriority(){
if (troopsType == 0){
return -1;
}
return priority;
}
}
(5)桌面信息类
这个主要是给ai用,可以让ai更强大
@Data
public class TableTopInformation {
/**
* 自己的牌
*/
private String s;
/**
* 当前最大牌面
*/
private String max;
/**
* 当前最大牌面 玩家
*/
private String maxPlayer;
/**
* 地主名称
*/
private String diZhu;
/**
* 出牌顺序
*/
private String shunXu;
/**
* 历史出牌
* key -> 出牌人
* value -> 所出牌,以逗号隔开,"-" 代表不出
*/
private Map<String, String> map;
/**
* 队伍map
* key -> 游戏人名称
* value -> 队伍序号 0 地主 1 地主队 2 农民队
*/
private Map<String, Integer> troopsMap;
/**
* 玩家手牌集合
* key 玩家名
* value 玩家对应的手牌
*/
private Map<String,List<Poker>> playerPokerMap;
/**
* 玩家集合
* 集合的顺序为出牌顺序
*/
private List<Player> playerList;
private List<Poker> poker;
private String wanJiaName;
/**
* key 玩家名
* value 是否显示该玩家的手牌
*/
private Map<String,Boolean> mapSB;
/**
* 地主牌
*/
private List<Poker> poker0;
/**
* 游戏玩家名称
*/
private LinkedHashSet<String> player;
/**
* key 玩家名
* value 玩家对应的出牌记录
*/
private Map<String,StringBuilder> mapCP;
/**
* key 玩家名
* value 玩家对于的电脑ai
*/
private Map<String,Ai> aiMap;
/**
* 游戏结束返回类
*/
private GameOverBean gameOverBean;
/**
* 获取下一个出牌的人
* @return
*/
public Player nextPlayer(String name){
int i = 0;
for (Player player : playerList) {
if (player.getName().equals(name)){
i = playerList.indexOf(player);
break;
}
}
if (i == playerList.size() - 1){
return playerList.get(0);
}else {
return playerList.get(i + 1);
}
}
}
(6) ai类
这里是一个抽象类,因为可以做迭代,一代ai一代强
主要就是两个动作,出牌,抢地主(这个动作没做,工作忙没空做了,也不影响摸鱼运行)
@Data
public abstract class Ai {
private Integer type;
private String name;
private TableTopInformation tableTopInformation;
public abstract String outPoker(OutPokerVo vo);
public abstract Boolean robDiZhu(String s);
}
2.主体与工具
这方面就有点多了,先来点基础的,逻辑我们下回再说
(1)刷屏方法
这里我们的界面就是idea控制台,所以需要一个清屏的方法
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);//延时
}
(2)静态字段(包括一些正则表达式)
首先是两个基础静态字段,玩家 和 扑克牌
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 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 String CANONICAL_NP = "[^2-9XJQKAWw\\-\\*]";
/**
* 正则单牌
*/
private static final String CANONICAL_X = "[2-9XJQKAWw\\*]";
/**
* 正则对子
*/
private static final String CANONICAL_XX = "([2-9XJQKAWw\\*])\\1{1}";
/**
* 正则至少N次重复
*/
private static final String CANONICAL_XX_N = "([2-9XJQKAWw\\*])\\1{N,}";
/**
* 正则三个
*/
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,}[3-9XJQKA]";
/**
* 连续 至少两次
*/
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,}";