删除代码冗余、优化重复调用、完善异常处理
parent
2bc803d031
commit
2cd88e9c74
|
|
@ -25,4 +25,26 @@ public class Config {
|
|||
*/
|
||||
public static final String JOIN_ROOM_CS = "1002";
|
||||
|
||||
/** Web组加入房间协议 */
|
||||
public static final String WEB_GROUP_JOIN_ROOM = "225";
|
||||
|
||||
/** Web组主动重连协议 */
|
||||
public static final String WEB_GROUP_ACTIVE_RECONNECT = "226";
|
||||
|
||||
//==================== 游戏服务器配置 ====================
|
||||
/** 游戏服务器主机地址 */
|
||||
public static final String GAME_SERVER_HOST = "127.0.0.1";
|
||||
|
||||
/** 游戏服务器端口 */
|
||||
public static final String GAME_SERVER_PORT = "6311";
|
||||
|
||||
/** 默认密码 */
|
||||
public static final String DEFAULT_PASSWORD = "123456";
|
||||
|
||||
/** 默认PID */
|
||||
public static final String DEFAULT_PID = "10";
|
||||
|
||||
/** 默认群组ID */
|
||||
public static final String DEFAULT_GROUP_ID = "762479";
|
||||
|
||||
}
|
||||
|
|
@ -219,7 +219,7 @@ public class EXGameController extends GameController {
|
|||
/**
|
||||
* 接收来自web_group的加入房间协议
|
||||
*/
|
||||
@ActionKey(value = "225", validate = GameInterceptor.NOT_PLAYER)
|
||||
@ActionKey(value = Config.WEB_GROUP_JOIN_ROOM, validate = GameInterceptor.NOT_PLAYER)
|
||||
public void webGroup(Session session, ITObject params, int gid) {
|
||||
int robotId = params.getInt("robotid");
|
||||
String roomId = params.getString("roomid");
|
||||
|
|
@ -245,7 +245,7 @@ public class EXGameController extends GameController {
|
|||
/**
|
||||
* 接收来自web_group的主动重连协议
|
||||
*/
|
||||
@ActionKey(value = "226", validate = GameInterceptor.NOT_PLAYER)
|
||||
@ActionKey(value = Config.WEB_GROUP_ACTIVE_RECONNECT, validate = GameInterceptor.NOT_PLAYER)
|
||||
public void webGroupActive(Session session, ITObject params, int gid) {
|
||||
int robotId = params.getInt("robotid");
|
||||
String roomId = params.getString("roomid");
|
||||
|
|
@ -363,11 +363,11 @@ public class EXGameController extends GameController {
|
|||
if (robotUser ==null) {
|
||||
RobotUser robotUserCopy = new RobotUser();
|
||||
robotUserCopy.setRobotId(robotId);
|
||||
robotUserCopy.setPassword("123456");
|
||||
robotUserCopy.setGameHost("127.0.0.1");
|
||||
robotUserCopy.setGamePort("6311");
|
||||
robotUserCopy.setRobotGroupid("330800");
|
||||
robotUserCopy.setRobotPid("10");
|
||||
robotUserCopy.setPassword(Config.DEFAULT_PASSWORD);
|
||||
robotUserCopy.setGameHost(Config.GAME_SERVER_HOST);
|
||||
robotUserCopy.setGamePort(Config.GAME_SERVER_PORT);
|
||||
robotUserCopy.setRobotGroupid(Config.DEFAULT_GROUP_ID);
|
||||
robotUserCopy.setRobotPid(Config.DEFAULT_PID);
|
||||
return robotUserCopy;
|
||||
}
|
||||
return robotRoomMapping.get(robotId);
|
||||
|
|
|
|||
|
|
@ -35,18 +35,18 @@ public class EXMainServer extends MainServer{
|
|||
//startConnectionCheckScheduler();
|
||||
//测试
|
||||
Jedis jedis2 = Redis.use("group1_db2").getJedis();
|
||||
String robotskey = "g{"+762479+"}:play:"+10;
|
||||
String robotskey = "g{"+Config.DEFAULT_GROUP_ID+"}:play:"+Config.DEFAULT_PID;
|
||||
Map<String, String> maprobot = jedis2.hgetAll(robotskey);
|
||||
for(Map.Entry<String, String> entry : maprobot.entrySet()) {
|
||||
System.out.println(entry.getKey() + ":" + entry.getValue());
|
||||
//是否创建
|
||||
RobotUser robotUser = new RobotUser();
|
||||
robotUser.setRobotId(entry.getKey());
|
||||
robotUser.setPassword("123456");
|
||||
robotUser.setGameHost("127.0.0.1");
|
||||
robotUser.setGamePort("6311");
|
||||
robotUser.setRobotGroupid("762479");
|
||||
robotUser.setRobotPid("10");
|
||||
robotUser.setPassword(Config.DEFAULT_PASSWORD);
|
||||
robotUser.setGameHost(Config.GAME_SERVER_HOST);
|
||||
robotUser.setGamePort(Config.GAME_SERVER_PORT);
|
||||
robotUser.setRobotGroupid(Config.DEFAULT_GROUP_ID);
|
||||
robotUser.setRobotPid(Config.DEFAULT_PID);
|
||||
|
||||
robotRoomMapping.put(entry.getKey(), robotUser);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ public class RobotConnectionManager {
|
|||
private static final Map<String, HuNanChangSha> huNanChangShaInstances = new ConcurrentHashMap<>();
|
||||
private final EXGameController exGameController;
|
||||
|
||||
private final String host="127.0.0.1";
|
||||
private final int port=6311;
|
||||
private final String host= Config.GAME_SERVER_HOST;
|
||||
private final int port= Integer.parseInt(Config.GAME_SERVER_PORT);
|
||||
|
||||
/*长沙麻将游戏算法相关 start*/
|
||||
private final Map<String, Map<Integer, List<Integer>>> playerOutcardsMapByConn = new ConcurrentHashMap<>();
|
||||
|
|
|
|||
|
|
@ -8,20 +8,28 @@ public class ChangshaWinSplitCard {
|
|||
public static int[][] countTiles(List<Integer> cardInHand) {
|
||||
int[][] counts = new int[5][10]; // 类型×值
|
||||
|
||||
//预计算牌型和牌值 避免重复计算
|
||||
for (Integer card : cardInHand) {
|
||||
if (card == 0) {
|
||||
continue;
|
||||
}
|
||||
counts[card / 100 - 1][card % 100]++;
|
||||
int suitIndex = card / 100 - 1; // 牌型索引
|
||||
int cardValue = card % 100; // 牌面值
|
||||
counts[suitIndex][cardValue]++;
|
||||
}
|
||||
return counts;
|
||||
}
|
||||
|
||||
// 检测不带精湖
|
||||
public static int checkNormalHu(List<Integer> cardInHand, Map<String, Object> map) {
|
||||
if (cardInHand == null || cardInHand.isEmpty()) {
|
||||
throw new IllegalArgumentException("手牌不能为空");
|
||||
}
|
||||
|
||||
String info = "";
|
||||
int[][] counts = countTiles(cardInHand);
|
||||
int group = 0;
|
||||
int handSizeDiv3 = cardInHand.size() / 3;//缓存计算结果 避免重复计算
|
||||
// 尝试找将牌
|
||||
for (int type = 0; type < 5; type++) {
|
||||
int max = 9;
|
||||
|
|
@ -29,14 +37,14 @@ public class ChangshaWinSplitCard {
|
|||
if (counts[type][value] >= 2 && (value == 2 || value == 5 || value == 8)) {
|
||||
// 找到可能的将牌
|
||||
counts[type][value] -= 2;
|
||||
group = checkMelds(counts, cardInHand.size() / 3, map);
|
||||
group = checkMelds(counts, handSizeDiv3, map);
|
||||
if (group == 0) { // 剩余12张牌需要组成4个顺子或刻子
|
||||
counts[type][value] += 2;
|
||||
return 0;
|
||||
}
|
||||
counts[type][value] += 2;
|
||||
} else {
|
||||
group = checkMelds(counts, (cardInHand.size() / 3) + 1, map);
|
||||
group = checkMelds(counts, handSizeDiv3 + 1, map);
|
||||
|
||||
if (group == 0) { // 剩余12张牌需要组成4个顺子或刻子
|
||||
counts[type][value] += 2;
|
||||
|
|
@ -47,13 +55,20 @@ public class ChangshaWinSplitCard {
|
|||
}
|
||||
|
||||
List<Integer> cardResiue = (List<Integer>) map.get("cardResiue");
|
||||
|
||||
for (int i = 0; i < cardResiue.size() - 1; i++) {
|
||||
if (cardResiue.get(i).equals(cardResiue.get(i + 1))
|
||||
&& (cardResiue.get(i) % 100 == 2 || cardResiue.get(i) % 100 == 5 || cardResiue.get(i) % 100 == 8)) {
|
||||
cardResiue.remove(i);
|
||||
cardResiue.remove(i);
|
||||
break;
|
||||
|
||||
//空指针检查
|
||||
if (cardResiue != null && cardResiue.size() > 1) {
|
||||
for (int i = 0; i < cardResiue.size() - 1; i++) {
|
||||
Integer currentCard = cardResiue.get(i);
|
||||
Integer nextCard = cardResiue.get(i + 1);
|
||||
|
||||
//缓存牌值计算结果
|
||||
int currentValue = currentCard % 100;
|
||||
if (currentCard.equals(nextCard) && (currentValue == 2 || currentValue == 5 || currentValue == 8)) {
|
||||
cardResiue.remove(i);
|
||||
cardResiue.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -77,11 +92,15 @@ public class ChangshaWinSplitCard {
|
|||
for (int value = 1; value <= max; value++) {
|
||||
if (counts[type][value] >= 3) {
|
||||
counts[type][value] -= 3;
|
||||
if (checkMelds(counts, remainingMelds - 1, map) == 0) {
|
||||
try {
|
||||
if (checkMelds(counts, remainingMelds - 1, map) == 0) {
|
||||
counts[type][value] += 3;
|
||||
return 0;
|
||||
}
|
||||
} finally {
|
||||
//确保状态回滚
|
||||
counts[type][value] += 3;
|
||||
return 0;
|
||||
}
|
||||
counts[type][value] += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -97,103 +116,83 @@ public class ChangshaWinSplitCard {
|
|||
counts[type][value + 1]--;
|
||||
counts[type][value + 2]--;
|
||||
|
||||
if (checkMelds(counts, remainingMelds - 1, map) == 0) {
|
||||
try {
|
||||
if (checkMelds(counts, remainingMelds - 1, map) == 0) {
|
||||
return 0;
|
||||
}
|
||||
} finally {
|
||||
//确保状态回滚
|
||||
counts[type][value]++;
|
||||
counts[type][value + 1]++;
|
||||
counts[type][value + 2]++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
counts[type][value]++;
|
||||
counts[type][value + 1]++;
|
||||
counts[type][value + 2]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 判断孤章
|
||||
List<Integer> cardResiue = convertCountToCards(counts);
|
||||
|
||||
// System.out.println("只差几手牌" + remainingMelds + "," + cardResiue);
|
||||
if (cardResiue.size() != 0) {
|
||||
if (!cardResiue.isEmpty()) {
|
||||
// 优先保留连续张
|
||||
removeConsecutivePairs1(cardResiue);
|
||||
}
|
||||
|
||||
if (cardResiue.size() != 0) {
|
||||
if (!cardResiue.isEmpty()) {
|
||||
// 第二优先保留对子
|
||||
removeConsecutivePairsTwo(cardResiue);
|
||||
}
|
||||
|
||||
// 最后保留坎张
|
||||
// 如果坎张,为空则取边张
|
||||
if (cardResiue.size() != 0) {
|
||||
List<Integer> tmp3 = new ArrayList<>();
|
||||
tmp3.addAll(cardResiue);
|
||||
if (!cardResiue.isEmpty()) {
|
||||
List<Integer> tmp3 = new ArrayList<>(cardResiue); //使用构造函数替代addAll
|
||||
removeConsecutivePairs2(cardResiue);
|
||||
if (cardResiue.size() == 0) {
|
||||
if (cardResiue.isEmpty()) {
|
||||
// 取边站
|
||||
cardResiue = qubianzhang(tmp3);
|
||||
}
|
||||
}
|
||||
|
||||
//合并重复的条件判断
|
||||
if (remainingMelds == 0) {
|
||||
map.put("remainingMelds", 0);
|
||||
map.put("cardResiue", "已经胡牌");
|
||||
|
||||
}
|
||||
if (map.get("remainingMelds") == null) {
|
||||
} else if (map.get("remainingMelds") == null) {
|
||||
map.put("remainingMelds", remainingMelds);
|
||||
|
||||
}
|
||||
if (map.get("cardResiue") == null) {
|
||||
map.put("cardResiue", cardResiue);
|
||||
}
|
||||
for (int i = 0; i < cardResiue.size() - 1; i++) {
|
||||
if (cardResiue.get(i).equals(cardResiue.get(i + 1))
|
||||
&& (cardResiue.get(i) % 100 == 2 || cardResiue.get(i) % 100 == 5 || cardResiue.get(i) % 100 == 8)) {
|
||||
cardResiue.remove(i);
|
||||
cardResiue.remove(i);
|
||||
if (remainingMelds >= 2) {
|
||||
remainingMelds--;
|
||||
//提取重复逻辑为私有方法 添加空指针检查
|
||||
if (cardResiue != null && cardResiue.size() > 1) {
|
||||
for (int i = 0; i < cardResiue.size() - 1; i++) {
|
||||
Integer currentCard = cardResiue.get(i);
|
||||
Integer nextCard = cardResiue.get(i + 1);
|
||||
|
||||
int currentValue = currentCard % 100;
|
||||
if (currentCard.equals(nextCard) && is258JiangValue(currentValue)) {
|
||||
cardResiue.remove(i);
|
||||
cardResiue.remove(i);
|
||||
if (remainingMelds >= 2) {
|
||||
remainingMelds--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Integer.parseInt(map.get("remainingMelds").toString()) >= remainingMelds && cardResiue.size() > 0) {
|
||||
//添加类型安全检查和空指针防护
|
||||
Object remainingMeldsObj = map.get("remainingMelds");
|
||||
if (remainingMeldsObj != null &&
|
||||
Integer.parseInt(remainingMeldsObj.toString()) >= remainingMelds &&
|
||||
!cardResiue.isEmpty()) {
|
||||
// 如果没有258做将则需要进入这里判断
|
||||
|
||||
if (remainingMelds == 1 && cardResiue.size() == 2) {
|
||||
for (int i = 0; i < cardResiue.size(); i++) {
|
||||
int diff = Math.abs(cardResiue.get(0) - cardResiue.get(1));
|
||||
if (diff > 1) {
|
||||
map.put("remainingMelds", remainingMelds + 1);// 删除符合258做将的牌
|
||||
if (cardResiue.size() > 1) {
|
||||
cardResiue.remove(i);
|
||||
}
|
||||
map.put("cardResiue", cardResiue);
|
||||
|
||||
} else {
|
||||
if (cardResiue.get(i) % 100 == 2 || cardResiue.get(i) % 100 == 5
|
||||
|| cardResiue.get(i) % 100 == 8) {
|
||||
// 删除符合258做将的牌
|
||||
if (cardResiue.size() > 1) {
|
||||
cardResiue.remove(i);
|
||||
}
|
||||
map.put("remainingMelds", remainingMelds);
|
||||
map.put("cardResiue", cardResiue);
|
||||
|
||||
} else {
|
||||
map.put("remainingMelds", remainingMelds);
|
||||
map.put("cardResiue", cardResiue);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processSpecialCase(cardResiue, remainingMelds, map);
|
||||
} else {
|
||||
map.put("remainingMelds", remainingMelds);
|
||||
map.put("cardResiue", cardResiue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return remainingMelds;
|
||||
|
|
@ -203,22 +202,20 @@ public class ChangshaWinSplitCard {
|
|||
if (cards == null || cards.size() < 2) {
|
||||
return;
|
||||
}
|
||||
// 先排序
|
||||
List<Integer> sorted = new ArrayList<>(cards);
|
||||
Collections.sort(sorted);
|
||||
|
||||
|
||||
//使用TreeSet自动排序并去重
|
||||
Set<Integer> uniqueCards = new TreeSet<>(cards);
|
||||
List<Integer> result = new ArrayList<>();
|
||||
int i = 0;
|
||||
|
||||
while (i < sorted.size()) {
|
||||
// boolean isleft = sorted.get(i) % 100 == 1 || sorted.get(i) % 100 == 8;
|
||||
if (i < sorted.size() - 1 && sorted.get(i + 1) - sorted.get(i) == 0) {
|
||||
// 跳过对子
|
||||
i += 2;
|
||||
} else {
|
||||
// 保留这张牌
|
||||
result.add(sorted.get(i));
|
||||
i++;
|
||||
|
||||
//过滤掉成对的牌
|
||||
Map<Integer, Integer> cardCount = new HashMap<>();
|
||||
for (Integer card : cards) {
|
||||
cardCount.put(card, cardCount.getOrDefault(card, 0) + 1);
|
||||
}
|
||||
|
||||
for (Integer card : uniqueCards) {
|
||||
if (cardCount.get(card) == 1) {
|
||||
result.add(card);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -232,16 +229,17 @@ public class ChangshaWinSplitCard {
|
|||
return;
|
||||
}
|
||||
|
||||
// 先排序
|
||||
List<Integer> sorted = new ArrayList<>(cards);
|
||||
Collections.sort(sorted);
|
||||
|
||||
//使用TreeSet自动排序
|
||||
List<Integer> sorted = new ArrayList<>(new TreeSet<>(cards));
|
||||
List<Integer> result = new ArrayList<>();
|
||||
int i = 0;
|
||||
|
||||
while (i < sorted.size()) {
|
||||
boolean isleft = sorted.get(i) % 100 == 1 || sorted.get(i) % 100 == 8;
|
||||
if (!isleft && i < sorted.size() - 1 && sorted.get(i + 1) - sorted.get(i) == 1) {
|
||||
//缓存计算结果
|
||||
int currentValue = sorted.get(i) % 100;
|
||||
boolean isEdgeCard = currentValue == 1 || currentValue == 8;
|
||||
|
||||
if (!isEdgeCard && i < sorted.size() - 1 && sorted.get(i + 1) - sorted.get(i) == 1) {
|
||||
// 跳过这对连续牌
|
||||
i += 2;
|
||||
} else {
|
||||
|
|
@ -256,10 +254,16 @@ public class ChangshaWinSplitCard {
|
|||
}
|
||||
|
||||
public static List<Integer> qubianzhang(List<Integer> cards) {
|
||||
if (cards == null || cards.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (int i = 0; i < cards.size(); i++) {
|
||||
if (cards.get(i) % 100 == 1 || cards.get(i) % 100 == 9) {
|
||||
result.add(cards.get(i));
|
||||
//使用增强for循环提高可读性
|
||||
for (Integer card : cards) {
|
||||
int value = card % 100;
|
||||
if (value == 1 || value == 9) {
|
||||
result.add(card);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
@ -270,49 +274,52 @@ public class ChangshaWinSplitCard {
|
|||
return;
|
||||
}
|
||||
|
||||
// 先排序
|
||||
List<Integer> sorted = new ArrayList<>(cards);
|
||||
Collections.sort(sorted);
|
||||
|
||||
// 使用布尔数组标记要删除的牌
|
||||
boolean[] toRemove = new boolean[sorted.size()];
|
||||
//使用TreeSet自动排序
|
||||
List<Integer> sorted = new ArrayList<>(new TreeSet<>(cards));
|
||||
|
||||
//使用Set替代布尔数组
|
||||
Set<Integer> cardsToRemove = new HashSet<>();
|
||||
|
||||
// 找出所有隔张(相差2的牌对,如1和3、2和4等)
|
||||
for (int i = 0; i < sorted.size(); i++) {
|
||||
if (!toRemove[i]) { // 如果这张牌还没被标记删除
|
||||
for (int j = i + 1; j < sorted.size(); j++) {
|
||||
if (!toRemove[j]) { // 如果这张牌还没被标记删除
|
||||
int diff = sorted.get(j) - sorted.get(i);
|
||||
Integer currentCard = sorted.get(i);
|
||||
if (cardsToRemove.contains(currentCard)) {
|
||||
continue; //如果这张牌已被标记删除 跳过
|
||||
}
|
||||
|
||||
for (int j = i + 1; j < sorted.size(); j++) {
|
||||
Integer nextCard = sorted.get(j);
|
||||
if (cardsToRemove.contains(nextCard)) {
|
||||
continue; //如果这张牌已被标记删除 跳过
|
||||
}
|
||||
|
||||
int diff = nextCard - currentCard;
|
||||
|
||||
if (diff == 2 && sorted.size() > 2) {
|
||||
//找到隔张 标记删除
|
||||
cardsToRemove.add(currentCard);
|
||||
cardsToRemove.add(nextCard);
|
||||
|
||||
if (diff == 2 && sorted.size() > 2) {
|
||||
// 找到隔张,标记删除
|
||||
toRemove[i] = true;
|
||||
toRemove[j] = true;
|
||||
|
||||
if (j + 1 < sorted.size()) {
|
||||
if (sorted.get(j + 1) % 100 == 2 || sorted.get(j + 1) % 100 == 5
|
||||
|| sorted.get(j + 1) % 100 == 6) {
|
||||
toRemove[i] = false;
|
||||
toRemove[j] = false;
|
||||
|
||||
}
|
||||
}
|
||||
break; // 找到一对就跳出内层循环
|
||||
|
||||
} else if (diff > 2) {
|
||||
// 由于已排序,差值只会越来越大
|
||||
break;
|
||||
//提前检查边界条件
|
||||
if (j + 1 < sorted.size()) {
|
||||
int nextNextValue = sorted.get(j + 1) % 100;
|
||||
if (nextNextValue == 2 || nextNextValue == 5 || nextNextValue == 6) {
|
||||
cardsToRemove.remove(currentCard);
|
||||
cardsToRemove.remove(nextCard);
|
||||
}
|
||||
}
|
||||
break;//找到一对就跳出内层循环
|
||||
} else if (diff > 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 构建结果列表(保留未标记删除的牌)
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (int i = 0; i < sorted.size(); i++) {
|
||||
if (!toRemove[i]) {
|
||||
result.add(sorted.get(i));
|
||||
for (Integer card : sorted) {
|
||||
if (!cardsToRemove.contains(card)) {
|
||||
result.add(card);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -321,21 +328,35 @@ public class ChangshaWinSplitCard {
|
|||
}
|
||||
|
||||
public static void haveBetween(List<Integer> cards, List<Integer> cardInHand) {
|
||||
if (cards.size() <= 1 || cardInHand.size() <= 1) {
|
||||
//添加空指针检查
|
||||
if (cards == null || cardInHand == null ||
|
||||
cards.size() <= 1 || cardInHand.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建要删除的牌列表
|
||||
Set<Integer> toRemove = new HashSet<>();
|
||||
|
||||
// 遍历手牌中的每一张牌
|
||||
//缓存手牌的牌型信息,避免重复计算
|
||||
Map<Integer, Integer> handCardTypes = new HashMap<>();
|
||||
for (int handCard : cardInHand) {
|
||||
// 检查cards中是否有与手牌形成靠章的牌
|
||||
for (int card : cards) {
|
||||
// 定义靠章规则:相同、相邻或隔一张
|
||||
int diff = Math.abs(card - handCard);
|
||||
if (diff == 1 || diff == 2) {
|
||||
toRemove.add(card);
|
||||
handCardTypes.put(handCard, handCard / 100);
|
||||
}
|
||||
|
||||
//遍历cards中的每一张牌
|
||||
for (int card : cards) {
|
||||
int cardType = card / 100;
|
||||
|
||||
//检查是否有与手牌形成靠章的牌
|
||||
for (int handCard : cardInHand) {
|
||||
//先检查牌型是否相同 再计算差值
|
||||
if (handCardTypes.get(handCard) == cardType) {
|
||||
//定义靠章规则:相同、相邻或隔一张
|
||||
int diff = Math.abs(card - handCard);
|
||||
if (diff == 1 || diff == 2) {
|
||||
toRemove.add(card);
|
||||
break;//找到一个匹配就可以跳出内层循环
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -343,33 +364,33 @@ public class ChangshaWinSplitCard {
|
|||
// 只有当cards中还有多于1张牌时才执行删除
|
||||
if (cards.size() - toRemove.size() > 0) {
|
||||
cards.removeAll(toRemove);
|
||||
|
||||
}
|
||||
|
||||
// 可选:打印信息
|
||||
if (!toRemove.isEmpty()) {
|
||||
System.out.println("删除的牌: " + toRemove);
|
||||
System.out.println("cards剩余: " + cards);
|
||||
}
|
||||
System.out.println("删除的牌: " + toRemove);
|
||||
System.out.println("cards剩余: " + cards);
|
||||
}
|
||||
|
||||
// 从二维数组counts还原到手牌列表
|
||||
private static List<Integer> convertCountToCards(int[][] counts) {
|
||||
if (counts == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<Integer> cardInHand = new ArrayList<>();
|
||||
|
||||
// counts数组结构:[类型索引][牌值]
|
||||
// 类型索引: 0=万, 1=筒, 2=条, 3=风, 4=箭 (根据您的编码规则)
|
||||
// 牌值: 1-9表示牌面值
|
||||
|
||||
for (int suitIdx = 0; suitIdx < counts.length; suitIdx++) {
|
||||
for (int suitIdx = 0; suitIdx < counts.length && suitIdx < 5; suitIdx++) {
|
||||
int suit = suitIdx + 1; // 还原百位数 (1,2,3,4,5)
|
||||
|
||||
for (int value = 1; value < counts[suitIdx].length; value++) {
|
||||
for (int value = 1; value < counts[suitIdx].length && value <= 9; value++) {
|
||||
int count = counts[suitIdx][value];
|
||||
|
||||
|
||||
int baseCard = suit * 100 + value;
|
||||
for (int i = 0; i < count; i++) {
|
||||
int card = suit * 100 + value;
|
||||
cardInHand.add(card);
|
||||
cardInHand.add(baseCard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -378,28 +399,31 @@ public class ChangshaWinSplitCard {
|
|||
}
|
||||
|
||||
public static List<Integer> checktingpai(List<Integer> cardhand) {
|
||||
//添加参数验证
|
||||
if (cardhand == null || cardhand.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<Integer> tpcards = new ArrayList<>();
|
||||
List<Integer> tmphc = cardhand;
|
||||
List<Integer> tmphc = new ArrayList<>(cardhand);
|
||||
|
||||
//缓存可能的胡牌列表
|
||||
List<Integer> candidateCards = new ArrayList<>();
|
||||
for (int j = 101; j <= 109; j++) candidateCards.add(j);
|
||||
for (int j = 201; j <= 209; j++) candidateCards.add(j);
|
||||
|
||||
for (int i = 0; i < cardhand.size(); i++) {
|
||||
|
||||
int tmpcard = tmphc.get(0);
|
||||
tmphc.remove(0);
|
||||
for (int j = 101; j <= 109; j++) {
|
||||
WinCard win = new WinCard(tmphc, j);
|
||||
if (win.tryWin()) {
|
||||
if (!tpcards.contains(tmpcard)) {
|
||||
tpcards.add(tmpcard);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j = 201; j <= 209; j++) {
|
||||
WinCard win = new WinCard(tmphc, j);
|
||||
if (win.tryWin()) {
|
||||
if (!tpcards.contains(tmpcard)) {
|
||||
tpcards.add(tmpcard);
|
||||
}
|
||||
Integer tmpcard = tmphc.remove(0); //使用泛型避免强制转换
|
||||
|
||||
//批量检查候选牌
|
||||
for (Integer candidate : candidateCards) {
|
||||
WinCard win = new WinCard(tmphc, candidate);
|
||||
if (win.tryWin() && !tpcards.contains(tmpcard)) {
|
||||
tpcards.add(tmpcard);
|
||||
break;//找到一个就可以跳出循环
|
||||
}
|
||||
}
|
||||
|
||||
tmphc.add(tmpcard);
|
||||
}
|
||||
return tpcards;
|
||||
|
|
@ -407,6 +431,9 @@ public class ChangshaWinSplitCard {
|
|||
|
||||
// 分析最优出牌
|
||||
public static List<Integer> analyzeBestDiscard(List<Integer> cardInHand) {
|
||||
if (cardInHand == null || cardInHand.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 听牌
|
||||
// 返回要打的牌,打后可以听牌
|
||||
|
|
@ -414,120 +441,36 @@ public class ChangshaWinSplitCard {
|
|||
System.out.println("打出这种牌后可以听牌 " + checktingpai);
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
Map<String, List<Integer>> jmap = new HashMap<>();// 对将map
|
||||
// 先定将,再做分析
|
||||
/*
|
||||
* int jiangnum = checkduijiang(cardInHand,jmap);
|
||||
* System.out.println(jmap.get("jiangcard").get(0)); if (jiangnum==1){ //如果只有一对将
|
||||
* //去将 后判断方案 List<Integer> tmphc = new ArrayList<>(); tmphc.addAll(cardInHand);
|
||||
* Util.removeCard(tmphc,jmap.get("jiangcard").get(0),2); Map<String, Object>
|
||||
* tmap = new HashMap<>(); checkNormalHu(tmphc, tmap);
|
||||
*
|
||||
* //不去将 判断
|
||||
*
|
||||
* Map<String, Object> tmap2 = new HashMap<>(); System.out.println(cardInHand);
|
||||
* checkNormalHu(cardInHand, tmap2); System.out.println(tmap2);
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* }else if(jiangnum>1){
|
||||
*
|
||||
* }else{
|
||||
*
|
||||
* }
|
||||
*/
|
||||
|
||||
checkNormalHu(cardInHand, map);
|
||||
|
||||
List<Integer> suggested = (List<Integer>) map.get("cardResiue");
|
||||
|
||||
if (suggested == null) {
|
||||
suggested = new ArrayList<>();
|
||||
}
|
||||
|
||||
// 返回要打的牌,打后可以听牌
|
||||
List<Integer> zuizhongchupai = new ArrayList<>();
|
||||
// 如果打出然后可以听牌,跟递归判断出来的牌一样,优先打出这张
|
||||
if (checktingpai.size() > 0) {
|
||||
for (Integer integer : checktingpai) {
|
||||
for (Integer integer1 : suggested) {
|
||||
if (integer.equals(integer1)) {
|
||||
zuizhongchupai.add(integer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//提取交集逻辑为独立方法
|
||||
findIntersectionCards(checktingpai, suggested, zuizhongchupai);
|
||||
|
||||
// 推荐打几个牌都能听牌,需要判断打哪个听的牌更多
|
||||
if (checktingpai.size() > 1 && zuizhongchupai.size() == 0) {
|
||||
if (checktingpai.size() > 1 && zuizhongchupai.isEmpty()) {
|
||||
zuizhongchupai.addAll(checktingpai);
|
||||
}
|
||||
|
||||
// 如果判断听牌和递归出来的牌不一样 优先以听牌为准
|
||||
if (zuizhongchupai.size() == 0) {
|
||||
if (zuizhongchupai.isEmpty()) {
|
||||
zuizhongchupai.addAll(checktingpai);
|
||||
}
|
||||
|
||||
// 如果判断最后打出牌还未听牌,就用递归判断的牌
|
||||
if (zuizhongchupai.size() == 0) {
|
||||
if (zuizhongchupai.isEmpty()) {
|
||||
zuizhongchupai.addAll(suggested);
|
||||
}
|
||||
System.out.println("zuizhongchupai" + zuizhongchupai);
|
||||
if (zuizhongchupai.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// //牌桌上出过的牌 未实现 这里听牌zuizhongchupai 对比 牌桌上出过的牌
|
||||
// ChangShaSuanFaTest changShaSuanFaTest = new ChangShaSuanFaTest();
|
||||
// List<Integer> chuguodepai = changShaSuanFaTest.chuguodepai();
|
||||
// if (chuguodepai.size() > 0 && checktingpai.size() > 0) {
|
||||
// System.out.println("递归内牌桌上出过的牌 ============ ===============" + chuguodepai);
|
||||
// Map<Integer, Integer> tinCardCountMap = new HashMap<>();
|
||||
//
|
||||
// // 初始化听牌组中所有牌的出现次数为0
|
||||
// for (Integer card : checktingpai) {
|
||||
// tinCardCountMap.put(card, 0);
|
||||
// }
|
||||
//
|
||||
// // 统计听牌组中每张牌在牌桌上的实际出现次数
|
||||
// for (Integer card : checktingpai) {
|
||||
// if (tinCardCountMap.containsKey(card)) {
|
||||
// tinCardCountMap.put(card, tinCardCountMap.get(card) + 1);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 找到最大的出现次数
|
||||
// Integer maxCount = tinCardCountMap.values().stream()
|
||||
// .max(Integer::compareTo)
|
||||
// .orElse(0);
|
||||
//
|
||||
// // 判断所有听牌是否都大于等于3次
|
||||
// boolean allGreaterOrEqualThree = !tinCardCountMap.isEmpty() &&
|
||||
// tinCardCountMap.values().stream().allMatch(count -> count >= 3);
|
||||
//
|
||||
// if (allGreaterOrEqualThree) {
|
||||
// List<Integer> result = new ArrayList<>();
|
||||
// // 如果所有听牌都出现大于等于3次,则随机出一张听牌
|
||||
// Integer randomCard = checktingpai.get(new Random().nextInt(checktingpai.size()));
|
||||
// System.out.println("递归内 -----所有听牌出现次数都>=3,随机出牌: " + randomCard);
|
||||
// result.add(randomCard);
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// if (maxCount > 0 && maxCount < 3) {
|
||||
// // 出现次数大于0但小于3,也直接出次数最多的牌
|
||||
// List<Integer> maxCards = tinCardCountMap.entrySet().stream()
|
||||
// .filter(entry -> entry.getValue().equals(maxCount))
|
||||
// .map(Map.Entry::getKey)
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// if (!maxCards.isEmpty()) {
|
||||
// List<Integer> result = new ArrayList<>();
|
||||
// Integer maxCard = Collections.max(maxCards);
|
||||
// result.add(maxCard);
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
return zuizhongchupai;
|
||||
return zuizhongchupai.isEmpty() ? new ArrayList<>() : zuizhongchupai;
|
||||
}
|
||||
|
||||
public static Integer selectBestCardRemove258(List<Integer> cards) {
|
||||
|
|
@ -557,14 +500,12 @@ public class ChangshaWinSplitCard {
|
|||
System.out.println("非258牌: " + non258Cards);
|
||||
//判断是否手牌有其他对将
|
||||
|
||||
|
||||
// 优先从非258牌中选
|
||||
if (!non258Cards.isEmpty()) {
|
||||
return selectBestSingleCard(non258Cards);
|
||||
}
|
||||
|
||||
// 如果没有非258牌,从258牌中选
|
||||
|
||||
if (!is258Cards.isEmpty()) {
|
||||
return selectBestSingleCard(is258Cards);
|
||||
}
|
||||
|
|
@ -587,31 +528,67 @@ public class ChangshaWinSplitCard {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//提取258将值判断逻辑
|
||||
private static boolean is258JiangValue(int value) {
|
||||
return value == 2 || value == 5 || value == 8;
|
||||
}
|
||||
|
||||
//提取特殊处理逻辑
|
||||
private static void processSpecialCase(List<Integer> cardResiue, int remainingMelds, Map<String, Object> map) {
|
||||
int diff = Math.abs(cardResiue.get(0) - cardResiue.get(1));
|
||||
if (diff > 1) {
|
||||
map.put("remainingMelds", remainingMelds + 1);
|
||||
if (cardResiue.size() > 1) {
|
||||
cardResiue.remove(0);
|
||||
}
|
||||
map.put("cardResiue", cardResiue);
|
||||
} else {
|
||||
int cardValue = cardResiue.get(0) % 100;
|
||||
if (is258JiangValue(cardValue)) {
|
||||
//删除符合258做将的牌
|
||||
if (cardResiue.size() > 1) {
|
||||
cardResiue.remove(0);
|
||||
}
|
||||
map.put("remainingMelds", remainingMelds);
|
||||
} else {
|
||||
map.put("remainingMelds", remainingMelds);
|
||||
}
|
||||
map.put("cardResiue", cardResiue);
|
||||
}
|
||||
}
|
||||
|
||||
//提取交集查找逻辑
|
||||
private static void findIntersectionCards(List<Integer> checktingpai, List<Integer> suggested, List<Integer> result) {
|
||||
if (checktingpai.isEmpty()) return;
|
||||
|
||||
for (Integer card : checktingpai) {
|
||||
if (suggested.contains(card)) {
|
||||
result.add(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 从候选牌中选出最优的一张牌(优先边张1或9)
|
||||
public static Integer selectBestSingleCard(List<Integer> cards) {
|
||||
if (cards == null || cards.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 优先找边张(1或9)
|
||||
for (Integer card : cards) {
|
||||
int value = card % 100;
|
||||
if (value == 1 || value == 9) {
|
||||
return card;
|
||||
}
|
||||
}
|
||||
|
||||
// 没有边张,找靠近边张的牌(2或8)- 注意这里2是258将牌,但我们已经去除了258
|
||||
for (Integer card : cards) {
|
||||
int value = card % 100;
|
||||
if (value == 2 || value == 8) {
|
||||
return card;
|
||||
}
|
||||
}
|
||||
|
||||
// 都没有,返回第一张
|
||||
return cards.get(0);
|
||||
|
||||
//使用Stream API简化查找逻辑
|
||||
return cards.stream()
|
||||
.filter(card -> {
|
||||
int value = card % 100;
|
||||
return value == 1 || value == 9;
|
||||
})
|
||||
.findFirst()
|
||||
.orElseGet(() -> cards.stream()
|
||||
.filter(card -> {
|
||||
int value = card % 100;
|
||||
return value == 2 || value == 8;
|
||||
})
|
||||
.findFirst()
|
||||
.orElse(cards.get(0)));
|
||||
}
|
||||
|
||||
// 主方法
|
||||
|
|
|
|||
|
|
@ -5,14 +5,15 @@ import java.util.*;
|
|||
public class TingPaiChecker {
|
||||
|
||||
// 长沙麻将特殊规则:二五八将
|
||||
private static final Set<Integer> JIANG_PAIS;
|
||||
|
||||
static {
|
||||
private static final Set<Integer> JIANG_PAIS = createJiangPaisSet();
|
||||
|
||||
//提取静态初始化逻辑
|
||||
private static Set<Integer> createJiangPaisSet() {
|
||||
Set<Integer> jiangSet = new HashSet<>();
|
||||
jiangSet.add(2);
|
||||
jiangSet.add(5);
|
||||
jiangSet.add(8);
|
||||
JIANG_PAIS = Collections.unmodifiableSet(jiangSet);
|
||||
return Collections.unmodifiableSet(jiangSet);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -20,9 +21,6 @@ public class TingPaiChecker {
|
|||
* @param handCards 手牌列表(13张或14张)
|
||||
* @return TingResult 听牌结果对象
|
||||
*/
|
||||
/**
|
||||
* 判断手牌是否听牌(主要入口方法)
|
||||
*/
|
||||
public static TingResult checkTingPai(List<Integer> handCards) {
|
||||
TingResult result = new TingResult();
|
||||
|
||||
|
|
@ -36,22 +34,13 @@ public class TingPaiChecker {
|
|||
System.out.println("手牌: " + convertToReadable(handCards));
|
||||
|
||||
// === 新增:处理四张相同牌的情况 ===
|
||||
// 统计每种牌的数量
|
||||
Map<Integer, Integer> countMap = new HashMap<>();
|
||||
for (int card : handCards) {
|
||||
countMap.put(card, countMap.getOrDefault(card, 0) + 1);
|
||||
}
|
||||
//提取统计逻辑为独立方法
|
||||
Map<Integer, Integer> countMap = countCards(handCards);
|
||||
|
||||
// 找出所有四张相同的牌
|
||||
List<Integer> cardsWithFour = new ArrayList<>();
|
||||
for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
|
||||
if (entry.getValue() == 4) {
|
||||
cardsWithFour.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
List<Integer> cardsWithFour = findCardsWithCount(countMap, 4);
|
||||
|
||||
|
||||
// 如果有四张相同的牌,去掉一张(选择其中一种处理)
|
||||
// 如果有四张相同的牌,去掉一张(选择其中一种处理)
|
||||
List<Integer> processedHandCards = new ArrayList<>(handCards);
|
||||
if (!cardsWithFour.isEmpty()) {
|
||||
// 只处理第一种四张相同的牌(如果有多个,实际麻将中不会出现这种情况)
|
||||
|
|
@ -95,30 +84,51 @@ public class TingPaiChecker {
|
|||
System.out.println("听牌数: " + tingCards.size() + "张");
|
||||
|
||||
// 按胡牌类型分组显示
|
||||
Map<String, List<TingCardInfo>> groupedByType = new HashMap<>();
|
||||
for (TingCardInfo info : tingCards) {
|
||||
groupedByType.computeIfAbsent(info.huType, k -> new ArrayList<>()).add(info);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, List<TingCardInfo>> entry : groupedByType.entrySet()) {
|
||||
System.out.print(" " + entry.getKey() + "听牌: ");
|
||||
List<String> cardStrs = new ArrayList<>();
|
||||
for (TingCardInfo info : entry.getValue()) {
|
||||
cardStrs.add(formatCard(info.card));
|
||||
}
|
||||
System.out.println(String.join(" ", cardStrs));
|
||||
}
|
||||
displayTingCardsByType(tingCards);
|
||||
} else {
|
||||
result.setTingPai(false);
|
||||
result.setMessage("未听牌");
|
||||
|
||||
System.out.println("✗ 未听牌");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* 检查所有胡牌类型
|
||||
*/
|
||||
|
||||
private static Map<Integer, Integer> countCards(List<Integer> handCards) {
|
||||
Map<Integer, Integer> countMap = new HashMap<>();
|
||||
for (int card : handCards) {
|
||||
countMap.put(card, countMap.getOrDefault(card, 0) + 1);
|
||||
}
|
||||
return countMap;
|
||||
}
|
||||
|
||||
private static List<Integer> findCardsWithCount(Map<Integer, Integer> countMap, int targetCount) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
|
||||
if (entry.getValue() == targetCount) {
|
||||
result.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void displayTingCardsByType(List<TingCardInfo> tingCards) {
|
||||
Map<String, List<TingCardInfo>> groupedByType = new HashMap<>();
|
||||
for (TingCardInfo info : tingCards) {
|
||||
groupedByType.computeIfAbsent(info.huType, k -> new ArrayList<>()).add(info);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, List<TingCardInfo>> entry : groupedByType.entrySet()) {
|
||||
System.out.print(" " + entry.getKey() + "听牌: ");
|
||||
List<String> cardStrs = new ArrayList<>();
|
||||
for (TingCardInfo info : entry.getValue()) {
|
||||
cardStrs.add(formatCard(info.card));
|
||||
}
|
||||
System.out.println(String.join(" ", cardStrs));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查所有胡牌类型
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package taurus.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
|
@ -34,7 +35,8 @@ public class WinCard {
|
|||
}
|
||||
|
||||
private boolean tryShunzi(int card) {
|
||||
if (card % 100 > 7) {
|
||||
int cardValue = card % 100;
|
||||
if (cardValue > 7) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -42,10 +44,7 @@ public class WinCard {
|
|||
Util.removeCard(this.cardList, card, 1);
|
||||
Util.removeCard(this.cardList, card + 1, 1);
|
||||
Util.removeCard(this.cardList, card + 2, 1);
|
||||
List<Integer> cardGroup = new ArrayList<Integer>();
|
||||
cardGroup.add(card);
|
||||
cardGroup.add(card + 1);
|
||||
cardGroup.add(card + 2);
|
||||
List<Integer> cardGroup = Arrays.asList(card, card + 1, card + 2);
|
||||
this.push(cardGroup);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -54,11 +53,7 @@ public class WinCard {
|
|||
|
||||
private boolean tryKezi(int card) {
|
||||
if (Util.checkCardAndRomve(card, this.cardList, 3)) {
|
||||
// CardUtil.removeCard(this.cardList, card, 3);
|
||||
List<Integer> cardGroup = new ArrayList<Integer>();
|
||||
cardGroup.add(card);
|
||||
cardGroup.add(card);
|
||||
cardGroup.add(card);
|
||||
List<Integer> cardGroup = Arrays.asList(card, card, card);
|
||||
this.push(cardGroup);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -69,16 +64,14 @@ public class WinCard {
|
|||
if (this.pair_count > 0) {
|
||||
return false;
|
||||
}
|
||||
if (jiang) {
|
||||
if (!(card % 100 == 2 || card % 100 == 5 || card % 100 == 8)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int cardValue = card % 100;
|
||||
if (jiang && !(cardValue == 2 || cardValue == 5 || cardValue == 8)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Util.checkCardAndRomve(card, this.cardList, 2)) {
|
||||
// CardUtil.removeCard(this.cardList, card, 2);
|
||||
List<Integer> cardGroup = new ArrayList<Integer>();
|
||||
cardGroup.add(card);
|
||||
cardGroup.add(card);
|
||||
List<Integer> cardGroup = Arrays.asList(card, card);
|
||||
this.push(cardGroup);
|
||||
this.pair_count = 1;
|
||||
return true;
|
||||
|
|
@ -88,11 +81,7 @@ public class WinCard {
|
|||
|
||||
private boolean tryKezi1Zhong(int card) {
|
||||
if (this.zhong_count >= 1 && Util.checkCardAndRomve(card, this.cardList, 2)) {
|
||||
// CardUtil.removeCard(this.cardList, card, 2);
|
||||
List<Integer> cardGroup = new ArrayList<Integer>();
|
||||
cardGroup.add(card);
|
||||
cardGroup.add(card);
|
||||
cardGroup.add(this.zhongid);
|
||||
List<Integer> cardGroup = Arrays.asList(card, card, this.zhongid);
|
||||
this.zhong_count -= 1;
|
||||
this.push(cardGroup);
|
||||
return true;
|
||||
|
|
@ -101,7 +90,8 @@ public class WinCard {
|
|||
}
|
||||
|
||||
private boolean tryShunzi1Zhong(int card) {
|
||||
if (card % 100 > 8) {
|
||||
int cardValue = card % 100;
|
||||
if (cardValue > 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -113,10 +103,7 @@ public class WinCard {
|
|||
Util.removeCard(cardList, card, 1);
|
||||
Util.removeCard(cardList, card + 1, 1);
|
||||
this.zhong_count -= 1;
|
||||
List<Integer> cardGroup = new ArrayList<Integer>();
|
||||
cardGroup.add(card);
|
||||
cardGroup.add(card + 1);
|
||||
cardGroup.add(this.zhongid);
|
||||
List<Integer> cardGroup = Arrays.asList(card, card + 1, this.zhongid);
|
||||
this.push(cardGroup);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -125,10 +112,7 @@ public class WinCard {
|
|||
Util.removeCard(cardList, card, 1);
|
||||
Util.removeCard(cardList, card + 2, 1);
|
||||
this.zhong_count -= 1;
|
||||
List<Integer> cardGroup = new ArrayList<Integer>();
|
||||
cardGroup.add(card);
|
||||
cardGroup.add(this.zhongid);
|
||||
cardGroup.add(card + 2);
|
||||
List<Integer> cardGroup = Arrays.asList(card, this.zhongid, card + 2);
|
||||
this.push(cardGroup);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -139,19 +123,18 @@ public class WinCard {
|
|||
if (this.pair_count > 0) {
|
||||
return false;
|
||||
}
|
||||
if (jiang) {
|
||||
if (!(card % 100 == 2 || card % 100 == 5 || card % 100 == 8)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int cardValue = card % 100;
|
||||
if (jiang && !(cardValue == 2 || cardValue == 5 || cardValue == 8)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.zhong_count < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Util.removeCard(cardList, card, 1);
|
||||
List<Integer> cardGroup = new ArrayList<Integer>();
|
||||
cardGroup.add(card);
|
||||
cardGroup.add(this.zhongid);
|
||||
List<Integer> cardGroup = Arrays.asList(card, this.zhongid);
|
||||
this.push(cardGroup);
|
||||
this.zhong_count -= 1;
|
||||
this.pair_count = 1;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,9 @@ public class ai {
|
|||
private static final Set<Integer> JIANG_PAIS;
|
||||
public boolean isTinAi = false;
|
||||
public boolean isTingpai = false;
|
||||
private Map<String, Double> scoreCache = new HashMap();
|
||||
private Map<String, List<Integer>> tingCache = new HashMap();
|
||||
private Map<String, Double> scoreCache = new HashMap<>();
|
||||
private Map<String, List<Integer>> tingCache = new HashMap<>();
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("=== 长沙麻将测试(含碰杠吃牌) ===");
|
||||
|
|
@ -28,6 +29,10 @@ public class ai {
|
|||
}
|
||||
|
||||
public int findBestDiscard(PlayerState state) {
|
||||
//参数验证
|
||||
if (state == null || state.handCards == null) {
|
||||
throw new IllegalArgumentException("玩家状态和手牌不能为空");
|
||||
}
|
||||
System.out.println("\n=== 长沙麻将AI出牌分析 ===");
|
||||
System.out.println("手牌(" + state.handCards.size() + "张): " + this.formatCards(state.handCards));
|
||||
int pongGroups = state.getPongGroupCount();
|
||||
|
|
@ -37,10 +42,10 @@ public class ai {
|
|||
this.scoreCache.clear();
|
||||
this.tingCache.clear();
|
||||
long startTime = System.currentTimeMillis();
|
||||
Map<Integer, DiscardResult> results = new HashMap();
|
||||
Set<Integer> uniqueCards = new HashSet(state.handCards);
|
||||
Map<Integer, DiscardResult> results = new HashMap<>();
|
||||
Set<Integer> uniqueCards = new HashSet<>(state.handCards);
|
||||
if (state.handCards.size() == 1) {
|
||||
int onlyCard = (Integer)state.handCards.get(0);
|
||||
int onlyCard = state.handCards.get(0);
|
||||
System.out.println("只剩一张牌,必须出: " + this.formatCard(onlyCard));
|
||||
return onlyCard;
|
||||
} else {
|
||||
|
|
@ -80,19 +85,23 @@ public class ai {
|
|||
long endTime = System.currentTimeMillis();
|
||||
System.out.printf("分析耗时: %dms%n", endTime - startTime);
|
||||
if (bestCard != -1) {
|
||||
DiscardResult bestResult = (DiscardResult)results.get(bestCard);
|
||||
DiscardResult bestResult = results.get(bestCard);
|
||||
System.out.println("\n\ud83c\udfaf AI推荐出牌: " + this.formatCard(bestCard));
|
||||
if (!bestResult.tingCards.isEmpty()) {
|
||||
this.isTinAi = true;
|
||||
this.isTingpai = true;
|
||||
System.out.println("✅ 听牌,可听 " + bestResult.tingCards.size() + " 张牌:");
|
||||
System.out.println("----牌组----" + bestResult.tingCards);
|
||||
if (bestResult.tingCards.size() > 0) {
|
||||
|
||||
//添加同步控制
|
||||
synchronized (ChangShaSuanFaTest.tinCards) {
|
||||
ChangShaSuanFaTest.tinCards.clear();
|
||||
ChangShaSuanFaTest.tinCards.addAll(bestResult.tingCards);
|
||||
}
|
||||
|
||||
List<String> tingCardsFormatted = (List)bestResult.tingCards.stream().map(this::formatCard).collect(Collectors.toList());
|
||||
List<String> tingCardsFormatted = bestResult.tingCards.stream()
|
||||
.map(this::formatCard)
|
||||
.collect(Collectors.toList());
|
||||
System.out.println(" " + String.join(" ", tingCardsFormatted));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue