diff --git a/robots/majiang/robot_mj_hz/src/main/java/robot/mj/Config.java b/robots/majiang/robot_mj_hz/src/main/java/robot/mj/Config.java index 1b30f78..d32dd91 100644 --- a/robots/majiang/robot_mj_hz/src/main/java/robot/mj/Config.java +++ b/robots/majiang/robot_mj_hz/src/main/java/robot/mj/Config.java @@ -1,105 +1,10 @@ package robot.mj; public class Config { - public static final int FENGDING_SCORE = 28; - public static final int XIPAI_SCORE = 10; - - public static final int ANCHOU_SCORE = 10; - - public static final String ROOM_CONFIG_ZIMO = "zimo"; - public static final String ROOM_CONFIG_ZHUANGXIAN = "zhuangxian"; - public static final String ROOM_CONFIG_NIAO = "niao"; - public static final String ROOM_CONFIG_NIAO_TYPE = "niao_type"; - public static final String ROOM_CONFIG_PIAO_NIAO = "piao_niao"; //0:不嫖 1:自由票 2:固定票 - public static final String ROOM_CONFIG_PIAO_NIAO_AUTO = "auto_piao"; //piao fen - public static final String ROOM_CONFIG_PIAO_NIAO_OPT = "piao_niao_opt"; //piao fen - public static final String ROOM_CONFIG_ZT_LIULIUSHUN = "zhongtuliuliushun"; - public static final String ROOM_CONFIG_ZT_DASIXI = "zhongtusixi"; - public static final String ROOM_CONFIG_QS_JIEJIEGAO = "jiejiegao"; - public static final String ROOM_CONFIG_QS_SANTONG = "santong"; - public static final String ROOM_CONFIG_QS_YIZHIHUA = "yizhihua"; - public static final String ROOM_CONFIG_QUEYIMEN = "queyimen"; - public static final String ROOM_CONFIG_FENGDING = "fengding"; - public static final String ROOM_CONFIG_FENGDING_SCORE = "fengding_score"; - public static final String ROOM_CONFIG_XIPAI = "xi_pai"; - public static final String ROOM_CONFIG_XIPAI_SCORE = "xi_pai_score"; - - public static final String ROOM_CONFIG_ANCHOU_SCORE = "an_chou_score"; - - public static final String ROOM_CONFIG_DIFEN_SCORE = "difen_score"; - public static final String ROOM_CONFIG_NIAOFEN_SCORE = "niaofen_score"; - public static final String ROOM_CONFIG_NIAOFEN_OPT = "niaofen_opt"; //0中鸟加分,//1中鸟加倍 - public static final String ROOM_CONFIG_KAI_GONG = "kai_gong"; //0:开杠2张,1:开杠四张 - public static final int NIAO_TYPE_ADD = 0; - - public static final int NIAO_TYPE_DOUBLE = 1; - - public static final int NIAO_TYPE_CS2NIAO = 2; - - - public static final String ROOM_CONFIG_QS_JTYN = "two_pair"; - - public static final String ROOM_CONFIG_NO_JIANG = "no_jiang"; - - public static final String ROOM_CONFIG_NATIVE_HU = "native_hu"; - - - public static final String ROOM_CONFIG_FOUR_WIN = "four_win"; - - public static final String SETTLE_XIAO_DIAN_PAO = "xiao_dian_pao"; - public static final String SETTLE_XIAO_JIE_PAO = "xiao_jie_pao"; - public static final String SETTLE_XIAO_ZIMO = "xiao_zimo"; - public static final String SETTLE_DA_DIAN_PAO = "da_dian_pao"; - public static final String SETTLE_DA_JIE_PAO = "da_jie_pao"; - public static final String SETTLE_DA_ZIMO = "da_zimo"; - - - public static final String GAME_EVT_PLAYER_DEAL = "811"; - - public static final String GAME_DIS_CARD = "611"; - - public static final String GAME_EVT_DISCARD = "812"; - - public static final String GAME_EVT_DISCARD_TIP = "813"; - - public static final String GAME_EVT_FZTIPS = "814"; - - public static final String GAME_ACTION = "612"; - - public static final String GAME_EVT_ACTION = "815"; - - public static final String GAME_EVT_HU = "816"; - - public static final String GAME_EVT_RESULT1 = "817"; - - public static final String GAME_EVT_RESULT2 = "818"; - - public static final String GAME_EVT_DRAW = "819"; - - public static final String GAME_EVT_CHANGE_ACTIVE_PLAYER = "820"; - - public static final String GAME_EVT_NIAO = "821"; - - public static final String GAME_EVT_QSTIP = "822"; - - public static final String GAME_EVT_QSWIN = "823"; - - public static final String GAME_EVT_OPENKONG = "824"; - - public static final String GAME_EVT_HAIDITIP = "825"; - - public static final String GAME_EVT_PIAONIAO_TIP = "833"; - - public static final String GAME_EVT_PIAONIAO = "834"; - - public static final String GAME_EVT_TING_TIP = "835"; - - public static final String GAME_EVT_TING = "836"; - - public static final String CREATE_ROOM_ROBOT = "create_room_for_robot"; - public static final String INIT_CONNECTION = "init_connection"; + public static final String CREATE_ROOM_ROBOT = "create_room_for_robot"; + public static final String INIT_CONNECTION = "init_connection"; /** * 加入房间 - robot_mgr to robot_mj_cs 的内部协议号 @@ -111,16 +16,6 @@ public class Config { */ public static final String GAME_READY = "2003"; - /** - * 退出房间 - robot_mgr to robot_mj_cs 的内部协议号 - */ - public static final String EXIT_ROOM = "2005"; - - /** - * 手动重连 - robot_mgr to robot_mj_cs 的内部协议号 - */ - public static final String RECONNECT = "2006"; - /** * 发送准备 - robot_mj_cs to game_mj_cs 的协议号 */ @@ -131,8 +26,4 @@ public class Config { */ public static final String JOIN_ROOM_CS = "1002"; - /** - * 退出房间 - robot_mgr to game_mj_cs 的内部协议号 - */ - public static final String EXIT_ROOM_CS = "1005"; } \ No newline at end of file diff --git a/robots/majiang/robot_mj_hz/src/main/java/robot/mj/EXMainServer.java b/robots/majiang/robot_mj_hz/src/main/java/robot/mj/EXMainServer.java index 1d6cb2c..047249a 100644 --- a/robots/majiang/robot_mj_hz/src/main/java/robot/mj/EXMainServer.java +++ b/robots/majiang/robot_mj_hz/src/main/java/robot/mj/EXMainServer.java @@ -6,18 +6,12 @@ import com.robot.GameController; import com.robot.MainServer; import com.robot.data.Player; import com.robot.data.Room; -import com.taurus.core.entity.ITObject; -import com.taurus.core.entity.TObject; import com.taurus.core.plugin.redis.Redis; -import com.taurus.permanent.TPServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import redis.clients.jedis.Jedis; import robot.mj.info.RobotUser; import taurus.client.NetManager; -import taurus.client.TaurusClient; - -import java.util.concurrent.TimeUnit; import static robot.mj.EXGameController.robotRoomMapping; @@ -29,8 +23,6 @@ public class EXMainServer extends MainServer{ private static final Logger log = LoggerFactory.getLogger(EXMainServer.class); private static final RobotConnectionManager robotConnectionManager = new RobotConnectionManager(); - private static final EXGameController exGameController = new EXGameController(); - private volatile boolean connectionCheckRunning = true; @Override public void onStart() { @@ -68,47 +60,6 @@ public class EXMainServer extends MainServer{ } } -// TPServer.me().getTimerPool().scheduleAtFixedRate(new Runnable() { -// @Override -// public void run() { -// -// for(Map.Entry entry : robotRoomMapping.entrySet()) { -// RobotUser robotUser = entry.getValue(); -// //1、登录 -// //判断是否登录 -// if(!robotUser.isLogin){ -// robotConnectionManager.login(robotUser); -// } -// /*//2、链接 -// //判断是否链接 -// System.out.println("robotUser.isconnect"+robotUser.getIsconnect()); -// if(!robotUser.getIsconnect()){ -// robotConnectionManager.connectGame(robotUser); -// }else{ -// robotConnectionManager.renconnect(robotUser); -// } -// -// -// //4、加入房间 -// if(robotUser.getStatus()==0){ -// //没状态时候进入加入房间 -// ITObject params = new TObject(); -// params.putString("connecId", robotUser.getRoomId()+"_"+robotUser.getRobotId()); -// params.putString("roomId", robotUser.getRoomId()); -// params.putString("groupId", robotUser.getRobotGroupid()); -// params.putString("session", "{user}:"+robotUser.getRobotId()); -// exGameController.joinRoom(null, params, robotUser.getClient().getId()); -// } -// System.out.println("robotUser.getIntoRoomTime()"+robotUser.getIntoRoomTime()); -// System.out.println("robGetTiem"+robotConnectionManager.getTime()); -// if(robotUser.getIntoRoomTime()+6<=robotConnectionManager.getTime()){ -// //5、退出房间 -// robotConnectionManager.outoRoom(robotUser); -// }*/ -// -// } -// } -// }, 0, 5 ,TimeUnit.SECONDS); //5、干活 log.info("红中麻将机器人服务器已启动"); log.info("服务器将监听端口 {} 用于接收robot_mgr管理协议", gameSetting.port); @@ -157,8 +108,6 @@ public class EXMainServer extends MainServer{ public void onStop() { super.onStop(); - // 停止连接检查线程 - connectionCheckRunning = false; log.info("红中麻将机器人服务器已停止"); } } \ No newline at end of file diff --git a/robots/majiang/robot_mj_hz/src/main/java/robot/mj/EXPlayer.java b/robots/majiang/robot_mj_hz/src/main/java/robot/mj/EXPlayer.java index 54b8039..024692c 100644 --- a/robots/majiang/robot_mj_hz/src/main/java/robot/mj/EXPlayer.java +++ b/robots/majiang/robot_mj_hz/src/main/java/robot/mj/EXPlayer.java @@ -1,15 +1,7 @@ package robot.mj; -import com.robot.Util; import com.robot.data.Player; import com.robot.data.Room; -import com.robot.data.Score; -import com.taurus.core.entity.ITArray; -import com.taurus.core.entity.ITObject; -import com.taurus.core.entity.TArray; -import com.taurus.core.entity.TObject; - -import java.util.*; /** * @@ -17,8 +9,6 @@ import java.util.*; */ public class EXPlayer extends Player { - - public EXPlayer(int playerid, Room table, String session_id) { super(playerid, table, session_id); System.out.println("new robot "); diff --git a/robots/majiang/robot_mj_hz/src/main/java/robot/mj/EXRoom.java b/robots/majiang/robot_mj_hz/src/main/java/robot/mj/EXRoom.java index 84ea302..5043ec3 100644 --- a/robots/majiang/robot_mj_hz/src/main/java/robot/mj/EXRoom.java +++ b/robots/majiang/robot_mj_hz/src/main/java/robot/mj/EXRoom.java @@ -7,29 +7,12 @@ import java.util.Map; public class EXRoom extends Room { - // - - - public EXRoom(String roomid, Map redis_room_map) { super(roomid, redis_room_map); } - - - - public void checkAction() { - - } - - - - - - - @Override protected void roomResult() { diff --git a/robots/majiang/robot_mj_hz/src/main/java/robot/mj/business/AccountBusiness.java b/robots/majiang/robot_mj_hz/src/main/java/robot/mj/business/AccountBusiness.java index bdf1bfa..4beff88 100644 --- a/robots/majiang/robot_mj_hz/src/main/java/robot/mj/business/AccountBusiness.java +++ b/robots/majiang/robot_mj_hz/src/main/java/robot/mj/business/AccountBusiness.java @@ -21,13 +21,6 @@ import com.taurus.web.Controller; import com.taurus.web.WebException; import redis.clients.jedis.Jedis; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -36,70 +29,6 @@ import java.util.Set; public class AccountBusiness extends Controller { private static Logger logger = Logger.getLogger(AccountBusiness.class); - public static String request(String httpUrl, String httpArg) { - BufferedReader reader = null; - String result = null; - StringBuffer sbf = new StringBuffer(); - httpUrl = httpUrl + "?" + httpArg; - - try { - URL url = new URL(httpUrl); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("GET"); - connection.connect(); - InputStream is = connection.getInputStream(); - reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); - String strRead = reader.readLine(); - if (strRead != null) { - sbf.append(strRead); - while ((strRead = reader.readLine()) != null) { - sbf.append("\n"); - sbf.append(strRead); - } - } - reader.close(); - result = sbf.toString(); - } catch (Exception e) { - e.printStackTrace(); - } - return result; - } - - public static String md5(String plainText) { - StringBuffer buf = null; - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - md.update(plainText.getBytes()); - byte b[] = md.digest(); - int i; - buf = new StringBuffer(""); - for (int offset = 0; offset < b.length; offset++) { - i = b[offset]; - if (i < 0) - i += 256; - if (i < 16) - buf.append("0"); - buf.append(Integer.toHexString(i)); - } - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return buf.toString(); - } - - public static String encodeUrlString(String str, String charset) { - String strret = null; - if (str == null) - return str; - try { - strret = java.net.URLEncoder.encode(str, charset); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - return strret; - } - private final ITObject fillLoginData(String session, int accountid) { ITObject resData = TObject.newInstance(); ITObject userData = TObject.newInstance(); diff --git a/robots/majiang/robot_mj_hz/src/main/java/robot/mj/handler/HuNanHongZhong.java b/robots/majiang/robot_mj_hz/src/main/java/robot/mj/handler/HuNanHongZhong.java index 28363ad..03b9ddb 100644 --- a/robots/majiang/robot_mj_hz/src/main/java/robot/mj/handler/HuNanHongZhong.java +++ b/robots/majiang/robot_mj_hz/src/main/java/robot/mj/handler/HuNanHongZhong.java @@ -18,7 +18,6 @@ import java.util.*; public class HuNanHongZhong { - public static int hongZhongCard = 0; //红中麻将手牌 @@ -27,7 +26,6 @@ public class HuNanHongZhong { //红中麻将出过的牌 private final List hongZhongchuguopai = new ArrayList<>(); - // 玩家座位号 public static int seat = 0; @@ -38,14 +36,12 @@ public class HuNanHongZhong { public static String session = ""; // 访问令牌 public static String token = ""; - //红中麻将算法 -// private static HongZhongSuanFa hongZhongSuanFa = new HongZhongSuanFa(); private static HongZhongSuanFaTest hongZhongSuanFaTest = new HongZhongSuanFaTest(); private static final Gson gson = new Gson(); - // 公共的getter和setter方法 + //公共的getter和setter方法 public List getHongZhongCardInhand() { return hongZhongCardInhand; } @@ -246,8 +242,6 @@ public class HuNanHongZhong { // 直接调用hongZhongSuanFaTest中的shouldPong方法,它已经包含了所有需要的规则 return hongZhongSuanFaTest.shouldPong(proposedCard, hongZhongCardInhand); - -// return hongZhongSuanFaTest.shouldPong(proposedCard, Arrays.asList(305,304,303,207,207,204,204,208,208,201,201,412,412)); } @@ -264,7 +258,6 @@ public class HuNanHongZhong { if (param == null) { return null; } -// {bank_seat=1, laiziCard=0, laiziCard2=0, laiziCard2Before=0, jing=0, laiziCardBefore=0, card_list=[101, 103, 104, 201, 204, 207, 208, 209, 307, 309, 501, 502, 503]} ITArray cardList = param.getTArray("card_list"); for (int i = 0; i < cardList.size(); i++) { hongZhongCardInhand.add(cardList.getInt(i)); @@ -375,7 +368,6 @@ public class HuNanHongZhong { /** * 出牌方法 */ -// public String outCard(TaurusClient client, List< Integer> list) { public String outCard(TaurusClient client) { // 调用分离分析方法,将刻子、顺子、红中单独拎出后分析剩余牌 try { diff --git a/robots/majiang/robot_mj_hz/src/main/java/taurus/util/CardUtil.java b/robots/majiang/robot_mj_hz/src/main/java/taurus/util/CardUtil.java index 5a6743e..318f821 100644 --- a/robots/majiang/robot_mj_hz/src/main/java/taurus/util/CardUtil.java +++ b/robots/majiang/robot_mj_hz/src/main/java/taurus/util/CardUtil.java @@ -3,47 +3,10 @@ package taurus.util; import com.taurus.core.entity.ITArray; import com.taurus.core.entity.TArray; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class CardUtil { - /** - * 从手牌中找出最大的单牌 - * - * @param handCards 手牌列表 - * @return 最大的单牌,如果没有单牌则返回null - */ - public static CardObj findMaxSingleCard(List handCards) { - if (handCards == null || handCards.isEmpty()) { - return null; - } - handCards.sort((c1, c2) -> c2.cardMod - c1.cardMod); - return handCards.get(0); - } - - - /** - * list to TArray - * - * @param list - * @return - */ - public static final ITArray toTArray(List list) { - ITArray result = new TArray(); - for (CardObj card : list) { - result.addInt(card.card); - } - return result; - } - - public static final ITArray toTArray1(CardObj list) { - ITArray result = new TArray(); - result.addInt(list.card); - return result; - } public static final ITArray maJiangToTArray(List list) { ITArray result = new TArray(); @@ -53,326 +16,5 @@ public class CardUtil { return result; } - public static final CardObj getCard(int eventCard, List cardList) { - for (CardObj card : cardList) { - if (card.cardMod == eventCard) { - return card; - } - } - return null; - } - public static final CardObj getCard1(int eventCard, List cardList) { - for (CardObj card : cardList) { - if (card.card == eventCard) { - return card; - } - } - return null; - } - - /** - * 检测牌数量 - * - * @param eventCard - * @param cardList - * @param num - * @return - */ - public static final boolean checkCard(int eventCard, List cardList, int num) { - int result = 0; - for (CardObj card : cardList) { - if (card.cardMod == eventCard) { - result++; - if (result == num) - return true; - } - } - return false; - } - - public static final boolean checkGoodCard(int eventCard, List cardList, int num) { - int result = 0; - for (CardObj card : cardList) { - if (card.cardMod == eventCard) { - result++; - if (result >= num) - return true; - } - } - return false; - } - - public static final boolean checkShunZi(int eventCard, List cardList) { - int result = 0; - if (checkGoodCard(eventCard + 1, cardList, 1)) { - result++; - if (checkGoodCard(eventCard + 2, cardList, 1)) { - result++; - if (checkGoodCard(eventCard + 3, cardList, 1)) { - result++; - if (checkGoodCard(eventCard + 4, cardList, 1)) { - result++; - if (checkGoodCard(eventCard + 5, cardList, 1)) { - result++; - } - } - } - } - } - if (checkGoodCard(eventCard - 1, cardList, 1)) { - result++; - if (checkGoodCard(eventCard - 2, cardList, 1)) { - result++; - if (checkGoodCard(eventCard - 3, cardList, 1)) { - result++; - if (checkGoodCard(eventCard - 4, cardList, 1)) { - result++; - if (checkGoodCard(eventCard - 5, cardList, 1)) { - result++; - } - } - } - } - } - - if (result >= 4) { - return true; - } - return false; - } - - public static final boolean checkSevenShunzi(int eventCard, List cardList) { - int result = 0; - if (checkGoodCard(eventCard + 1, cardList, 1)) { - result++; - if (checkGoodCard(eventCard + 2, cardList, 1)) { - result++; - if (checkGoodCard(eventCard + 3, cardList, 1)) { - result++; - if (checkGoodCard(eventCard + 4, cardList, 1)) { - result++; - if (checkGoodCard(eventCard + 5, cardList, 1)) { - result++; - if (checkGoodCard(eventCard + 6, cardList, 1)) { - result++; - if (checkGoodCard(eventCard + 7, cardList, 1)) { - result++; - } - } - } - } - } - } - } - if (checkGoodCard(eventCard - 1, cardList, 1)) { - result++; - if (checkGoodCard(eventCard - 2, cardList, 1)) { - result++; - if (checkGoodCard(eventCard - 3, cardList, 1)) { - result++; - if (checkGoodCard(eventCard - 4, cardList, 1)) { - result++; - if (checkGoodCard(eventCard - 5, cardList, 1)) { - result++; - if (checkGoodCard(eventCard - 6, cardList, 1)) { - result++; - if (checkGoodCard(eventCard - 7, cardList, 1)) { - result++; - } - } - } - } - } - } - } - - if (result >= 6) { - return true; - } - return false; - } - - public static final boolean checkFenJi(int eventCard, List cardList) { - int result = 0; - if (checkGoodCard(eventCard, cardList, 2)) { - result++; - if (checkGoodCard(eventCard + 1, cardList, 3)) { - result++; - } - if (checkGoodCard(eventCard - 1, cardList, 3)) { - result++; - } - } - - if (result >= 2) { - return true; - } - return false; - } - - public static final boolean checkFourDui(int eventCard, List cardList) { - int result = 0; - if (checkGoodCard(eventCard, cardList, 1)) { - result++; - } - - if (checkGoodCard(eventCard + 1, cardList, 2)) { - result++; - if (checkGoodCard(eventCard + 2, cardList, 2)) { - result++; - if (checkGoodCard(eventCard + 3, cardList, 2)) { - result++; - if (checkGoodCard(eventCard + 4, cardList, 2)) { - result++; - } - } - } - } - if (checkGoodCard(eventCard - 1, cardList, 2)) { - result++; - if (checkGoodCard(eventCard - 2, cardList, 2)) { - result++; - if (checkGoodCard(eventCard - 3, cardList, 2)) { - result++; - if (checkGoodCard(eventCard - 4, cardList, 2)) { - result++; - } - } - } - } - - if (result >= 4) { - return true; - } - return false; - } - - public static final boolean checkQPai(int eventCard, List cardList) { - int result = 0; - if (eventCard >= 12) { - result++; - for (CardObj card : cardList) { - if (card.cardMod >= 12) { - result++; - } - } - } - - if (result >= 5) { - return true; - } - return false; - } - - /** - * TArray to list - * - * @param list - * @return - */ - public static final List toList(ITArray list) { - List tem = new ArrayList(); - for (int i = 0; i < list.size(); ++i) { - tem.add(new CardObj(list.getInt(i))); - } - return tem; - } - - /** - * 获取每张牌的数量MAP - * - * @param cardList - * @return - */ - public static final Map getCardNumMap(List cardList) { - Map result = new HashMap(); - for (CardObj card : cardList) { - if (!result.containsKey(card.cardMod)) { - result.put(card.cardMod, 1); - } else { - int num = result.get(card.cardMod); - result.put(card.cardMod, (num + 1)); - } - } - return result; - } - - /** - * 获取每张牌的数量MAP - * - * @param cardList - * @return - */ - public static final void getCardNumMap(Map result, List cardList) { - result.clear(); - for (CardObj card : cardList) { - if (!result.containsKey(card.cardMod)) { - result.put(card.cardMod, 1); - } else { - int num = result.get(card.cardMod); - result.put(card.cardMod, (num + 1)); - } - } - } - - public static final void getCardNumMap(Map result, List cardList, CardObj tempCard) { - result.clear(); - result.put(tempCard.cardMod, 1); - for (CardObj card : cardList) { - if (!result.containsKey(card.cardMod)) { - result.put(card.cardMod, 1); - } else { - int num = result.get(card.cardMod); - result.put(card.cardMod, (num + 1)); - } - } - } - - /** - * 获取每张牌的数量MAP - * - * @param cardList - * @return - */ - public static final Map> getCardListMap(List cardList) { - Map> result = new HashMap>(); - for (CardObj card : cardList) { - if (!result.containsKey(card.cardMod)) { - List list = new ArrayList(); - list.add(card); - result.put(card.cardMod, list); - } else { - List list = result.get(card.cardMod); - list.add(card); - } - } - return result; - } - - static public void removeCard(List cardList, List cards) { - for (int i = 0; i < cards.size(); i++) { - for (int j = 0; j < cardList.size(); j++) { - if (cardList.get(j).card == cards.get(i).card) { - cardList.remove(j); - break; - } - } - } - } - - static public void removeCard1(List cardList, int card, int count) { - int curCount = 0; - for (int i = 0; i < cardList.size(); i++) { - if (count == curCount) { - return; - } - if (cardList.get(i) == card) { - - cardList.remove(i); - i--; - curCount++; - } - } - } } diff --git a/robots/majiang/robot_mj_hz/src/main/java/taurus/util/HongZhongSuanFaTest.java b/robots/majiang/robot_mj_hz/src/main/java/taurus/util/HongZhongSuanFaTest.java index 7edfbf5..d925ee1 100644 --- a/robots/majiang/robot_mj_hz/src/main/java/taurus/util/HongZhongSuanFaTest.java +++ b/robots/majiang/robot_mj_hz/src/main/java/taurus/util/HongZhongSuanFaTest.java @@ -398,24 +398,6 @@ public class HongZhongSuanFaTest { } } - // 分析剩余牌 - 识别需要重点考虑的牌 - private void analyzeRemainingCards(HandAnalysis analysis) { - List remainingCards = new ArrayList<>(); - - // 遍历所有手牌,找出未被用于面子或对子的牌 - for (Map.Entry> entry : analysis.cardsBySuit.entrySet()) { - for (int card : entry.getValue()) { - // 如果牌没有被用于面子或对子,则视为剩余牌 - if (!analysis.usedInMelds.contains(card) && !analysis.usedInPairs.contains(card)) { - remainingCards.add(card); - } - } - } - - // 保存剩余牌 - analysis.remainingCards = remainingCards; - } - // 调整剩余牌的价值 - 更细致的评估 private int adjustRemainingCardValue(int card, HandAnalysis analysis) { int value = analysis.cardUsefulness.getOrDefault(card, 0); @@ -1158,80 +1140,6 @@ public class HongZhongSuanFaTest { return SpecialPattern.NONE; } - - - - // 计算刻子潜力 - private int calculateTripletPotential(int sameCardCount, int hongZhongCount) { - if (sameCardCount == 3) { - return WEIGHT_POTENTIAL_TRIPLET + 20; // Already triplet - } else if (sameCardCount == 2) { - return WEIGHT_POTENTIAL_TRIPLET + (hongZhongCount * 15); // Pair+hongZhong can easily form triplet - } else if (sameCardCount == 1 && hongZhongCount >= 2) { - return 30 + (hongZhongCount * 10); // Single card+2hongZhong can form triplet - } - return 0; - } - - // 计算顺子潜力 - private int calculateSequencePotential(int card, List sameSuitCards) { - int potential = 0; - int suit = card / 100; - int rank = card % 100; - - // 获取当前花色所有牌的点数 - Set ranks = new HashSet<>(); - for (int c : sameSuitCards) { - ranks.add(c % 100); - } - - // 检查可能的顺子组合 - // 向前检查:x, x+1, x+2 - for (int start = Math.max(1, rank - 2); start <= Math.min(7, rank); start++) { - int mid = start + 1; - int end = start + 2; - - int matchCount = 0; - if (ranks.contains(start)) matchCount++; - if (ranks.contains(mid)) matchCount++; - if (ranks.contains(end)) matchCount++; - - // 根据匹配数量增加潜力值 - if (matchCount == 3) { - potential += 60; // 完整顺子 - } else if (matchCount == 2) { - potential += 35; // 两搭子 - } else if (matchCount == 1) { - potential += 15; // 单张 - } - } - - // 相邻牌奖励 - if (ranks.contains(rank - 1) || ranks.contains(rank + 1)) { - potential += WEIGHT_CLOSE_ADJACENT; - } - - return potential; - } - - // 计算牌张位置价值 - private int calculateRankValue(int rank) { - int value = 0; - - // 中张牌价值更高 - if (rank >= 3 && rank <= 7) { - value += WEIGHT_MIDDLE_RANK; - // 金3银7特殊价值 - if (rank == 3 || rank == 7) { - value += 10; // 更高的中张价值 - } - } else { - value -= PENALTY_EDGE_RANK; - } - - return value; - } - // 计算出牌优先级 - 优先考虑剩余牌和牌的潜力 private Map calculateDiscardPriority(List handCards, HandAnalysis analysis, @@ -2113,195 +2021,6 @@ public class HongZhongSuanFaTest { logInfo("重新分析后的孤牌: " + analysis.isolatedCards); } - /** - * 分析听牌类型 - 精确版 - * 更详细地识别不同类型的听牌 - */ - private String analyzeTingType(HandAnalysis analysis) { - Set tingCards = analysis.tingCards; - int tingCardCount = tingCards.size(); - - if (tingCardCount == 0) { - return "未知听牌类型"; - } - - // 统计各花色的听牌数量 - Map suitTingCount = new HashMap<>(); - for (int card : tingCards) { - int suit = card / 100; - suitTingCount.put(suit, suitTingCount.getOrDefault(suit, 0) + 1); - } - - // 检查是否为清一色或混一色听牌 - boolean isPureSuit = suitTingCount.size() == 1 && !suitTingCount.containsKey(HONG_ZHONG / 100); - - // 检查红中的影响 - boolean hasHongZhongImpact = analysis.hongZhongCount > 0 && analysis.hongZhongContributedTingCards > 0; - - // 详细的听牌类型判断 - if (tingCardCount == 1) { - return "单调张听牌" + (hasHongZhongImpact ? "(红中辅助)" : ""); - } else if (tingCardCount == 2) { - // 检查是否为两面听 - List sortedTingCards = new ArrayList<>(tingCards); - Collections.sort(sortedTingCards); - int suit1 = sortedTingCards.get(0) / 100; - int suit2 = sortedTingCards.get(1) / 100; - int rank1 = sortedTingCards.get(0) % 100; - int rank2 = sortedTingCards.get(1) % 100; - - if (suit1 == suit2 && Math.abs(rank1 - rank2) == 2) { - return "两面听牌" + (hasHongZhongImpact ? "(红中辅助)" : ""); - } else { - return "双碰听牌" + (hasHongZhongImpact ? "(红中辅助)" : ""); - } - } else if (tingCardCount == 3) { - // 检查是否为三面听(如1,4,7或3,6,9) - List sortedTingCards = new ArrayList<>(tingCards); - Collections.sort(sortedTingCards); - boolean sameSuit = true; - int suit = sortedTingCards.get(0) / 100; - for (int card : sortedTingCards) { - if (card / 100 != suit) { - sameSuit = false; - break; - } - } - - if (sameSuit) { - int rank1 = sortedTingCards.get(0) % 100; - int rank2 = sortedTingCards.get(1) % 100; - int rank3 = sortedTingCards.get(2) % 100; - - if ((rank1 == 1 && rank2 == 4 && rank3 == 7) || - (rank1 == 3 && rank2 == 6 && rank3 == 9)) { - return "三面听牌" + (hasHongZhongImpact ? "(红中辅助)" : ""); - } - } - - return "多面听牌" + (hasHongZhongImpact ? "(红中辅助)" : ""); - } else if (tingCardCount >= 4 && tingCardCount <= 6) { - return "多面听牌" + (hasHongZhongImpact ? "(红中辅助)" : ""); - } else { - // 大量听牌,可能是清幺九或其他特殊牌型 - if (isPureSuit) { - return "清一色广听牌" + (hasHongZhongImpact ? "(红中辅助)" : ""); - } else { - return "广听牌(听多张)" + (hasHongZhongImpact ? "(红中辅助)" : ""); - } - } - } - - /** - * 评估听牌强度 - 高级版 - * 综合考虑多种因素进行精确的听牌强度评估 - * @param analysis 手牌分析结果对象 - * @return 听牌强度评分(0-100) - */ - private int evaluateTingStrength(HandAnalysis analysis) { - int strength = 0; - Set tingCards = analysis.tingCards; - int tingCardCount = tingCards.size(); - - // 基础分:根据听牌数量(非线性增长) - if (tingCardCount == 1) { - strength += 20; - } else if (tingCardCount == 2) { - strength += 35; - } else if (tingCardCount == 3) { - strength += 50; - } else if (tingCardCount == 4) { - strength += 60; - } else if (tingCardCount == 5) { - strength += 70; - } else if (tingCardCount >= 6) { - strength += 80; - } - - // 加分:中张听牌(3-7)- 更易胡牌 - for (int card : tingCards) { - int rank = card % 100; - if (rank >= 3 && rank <= 7) { - strength += 3; - } else if (rank == 2 || rank == 8) { - strength += 1; - } else if (rank == 1 || rank == 9) { - strength -= 1; - } - } - - // 加分:已完成面子多 - strength += analysis.meldCount * 7; - - // 加分:对子数量适中 - if (analysis.pairCount == 1) { - strength += 5; - } else if (analysis.pairCount > 1) { - strength -= analysis.pairCount - 1; - } - - // 红中影响评估 - if (analysis.hongZhongCount == 0) { - // 无红中听牌,难度较大,给予额外加分 - strength += 10; - } else if (analysis.hongZhongCount == 1) { - strength += 7; - } else if (analysis.hongZhongCount == 2) { - strength += 4; - } else if (analysis.hongZhongCount >= 3) { - // 红中过多可能限制牌型,给予少量减分 - strength -= Math.min(analysis.hongZhongCount - 2, 5); - } - - // 减分:孤张多 - strength -= analysis.isolatedCards.size() * 4; - - // 加分:听牌中的新摸牌 - if (analysis.isTingPai && tingCards.contains(analysis.lastDrawnCard)) { - strength += 5; - } - - // 加分:听牌组的花色多样性(避免只听一种花色) - Map suitTingCount = new HashMap<>(); - for (int card : tingCards) { - int suit = card / 100; - suitTingCount.put(suit, suitTingCount.getOrDefault(suit, 0) + 1); - } - if (suitTingCount.size() > 1) { - strength += 5; - } - - // 确保分数在合理范围内 - return Math.max(0, Math.min(strength, 100)); - } - - /** - * 获取手牌改进建议 - * @param analysis 手牌分析结果对象 - * @return 改进建议 - */ - private String getImprovementSuggestions(HandAnalysis analysis) { - StringBuilder suggestions = new StringBuilder(); - - if (analysis.shantenCount == 1) { - suggestions.append("接近听牌,优先考虑打出孤张牌。"); - } else if (analysis.shantenCount == 2) { - suggestions.append("需要整理手牌,形成更多对子或顺子。"); - } else { - suggestions.append("手牌需要大幅调整,优先保留有潜力的牌组。"); - } - - if (analysis.isolatedCards.size() > 3) { - suggestions.append(" 考虑打出多余的孤张牌。"); - } - - if (analysis.hongZhongCount > 3) { - suggestions.append(" 红中数量过多,可以考虑杠牌或保留。"); - } - - return suggestions.toString(); - } - /** * 分析牌的类型 * @param card 牌 @@ -2817,755 +2536,4 @@ public class HongZhongSuanFaTest { return score; } - - - - - - - - /** - * 测试单个听牌场景,包含异常处理 - */ - private void testSingleTingScenario(String scenarioName, List handCards) { - logInfo("\n测试场景: " + scenarioName); - logInfo("测试手牌: " + handCards); - - try { - long startTime = System.currentTimeMillis(); - HandAnalysis analysis = analyzeHand(handCards); - long endTime = System.currentTimeMillis(); - - logInfo("分析结果: 成功"); - logInfo("是否听牌: " + analysis.isTingPai); - logInfo("听牌组: " + analysis.tingCards); - logInfo("听牌数量: " + analysis.tingCards.size()); - logInfo("向听数: " + analysis.shantenCount); - logInfo("红中数量: " + analysis.hongZhongCount); - logInfo("红中贡献听牌: " + analysis.hongZhongContributedTingCards); - logInfo("分析耗时: " + (endTime - startTime) + "ms"); - } catch (Exception e) { - logInfo("分析结果: 异常 - " + e.getMessage()); - logInfo("异常类型: " + e.getClass().getSimpleName()); - e.printStackTrace(); - } - } - - /** - * 执行性能对比测试,比较优化前后的算法性能 - */ - private void performPerformanceComparison() { - // 创建复杂的测试手牌 - List complexHand = Arrays.asList( - 101, 102, 103, 104, 105, // 一至五万 - 206, 207, 208, 209, 210, // 六至十条 - 301, 302, 303, 412, 412 // 一至三筒和两个红中 - ); - - // 测试多次取平均值 - int iterations = 100; - long totalTimeOptimized = 0; - - logInfo("执行" + iterations + "次优化版听牌检测测试..."); - - for (int i = 0; i < iterations; i++) { - HandAnalysis analysis = new HandAnalysis(); - // 准备分析数据 - for (int card : complexHand) { - if (card == HONG_ZHONG) { - analysis.hongZhongCount++; - } else { - int suit = card / 100; - analysis.cardsBySuit.computeIfAbsent(suit, k -> new ArrayList<>()).add(card); - // 统计每种牌的数量 - analysis.cardCounts.put(card, analysis.cardCounts.getOrDefault(card, 0) + 1); - } - } - analysis.shantenCount = 0; - - // 测量优化版算法时间 - long start = System.nanoTime(); - findTingCardsOptimized(analysis); - long end = System.nanoTime(); - totalTimeOptimized += (end - start) / 1000; // 转换为微秒 - } - - double avgTimeOptimized = totalTimeOptimized / (double) iterations; - - logInfo("优化版算法平均耗时: " + avgTimeOptimized + " μs"); - logInfo("优化版算法总耗时: " + (totalTimeOptimized / 1000.0) + " ms"); - } - - /** - * 分析手牌是否为听牌状态 - * @param handCards 当前手牌 - * @return 返回一个Map,其中key为是否听牌,value为听牌的集合 - * @throws IllegalArgumentException 当输入参数无效时抛出 - */ - public Map> analyzeTingPaiStatus(List handCards, HandAnalysis analysis) { - // 输入验证 - if (handCards == null) { - throw new IllegalArgumentException("手牌列表不能为空"); - } - - Map> result = new HashMap<>(); - Set tingCards = new HashSet<>(); - boolean isTing = false; - - try { - // 边界条件检查:空的手牌列表 - if (handCards.isEmpty()) { - logInfo("警告:手牌列表为空,无法分析听牌状态"); - result.put(false, tingCards); - return result; - } - - // 验证手牌中的牌值是否有效 - if (!validateHandCards(handCards)) { - logInfo("警告:手牌中包含无效的牌值"); - result.put(false, tingCards); - return result; - } - - // 对手牌进行分析 -// HandAnalysis analysis = analyzeHand(handCards); - - // 防止analysis为null - if (analysis == null) { - logInfo("错误:手牌分析结果为null"); - result.put(false, tingCards); - return result; - } - - // 检查是否听牌 - checkTingPai(analysis); - - // 查找听的牌 - findTingCards(analysis); - - // 执行备用的听牌分析,确保全面检查 - performBackupTingAnalysis(analysis); - - // 分析红中对听牌的影响 - analyzeHongZhongImpactOnTingCards(analysis); - - // 提取听牌信息 - isTing = analysis.isTingPai; - - // 防止tingCards为null - if (analysis.tingCards != null) { - tingCards = analysis.tingCards; - } - - // 如果手牌加上任何一张可能的牌能胡牌,也应该认为是听牌 - if (!isTing) { - try { - // 尝试所有可能的牌,检查是否有补牌能让手牌胡牌 - for (int potentialCard : getAllPossibleCards()) { - List testHand = new ArrayList<>(handCards); - testHand.add(potentialCard); - - HandAnalysis testAnalysis = analyzeHand(testHand); - if (testAnalysis != null) { - checkTingPai(testAnalysis); - - if (testAnalysis.isTingPai) { - isTing = true; - tingCards.add(potentialCard); - } - } - } - } catch (Exception e) { - logInfo("检查潜在听牌时出错: " + e.getMessage()); - // 继续执行,不影响主要结果 - } - } - } catch (IllegalArgumentException e) { - // 重新抛出参数异常,这是一个需要调用者处理的错误 - throw e; - } catch (Exception e) { - logInfo("分析听牌状态时出错: " + e.getMessage()); - e.printStackTrace(); - // 即使出错也要返回一个有效的结果 - } finally { - // 确保结果map总是包含布尔值和集合 - if (!tingCards.isEmpty()) { - result.put(isTing, tingCards); - } else { - result.put(false, Collections.emptySet()); - } - } - - return result; - } - - /** - * 验证手牌中的牌值是否有效 - * @param handCards 手牌列表 - * @return 牌值是否全部有效 - */ - private boolean validateHandCards(List handCards) { - // 基本的牌值范围检查 - for (int card : handCards) { - // 检查牌值是否在合理范围内 - if (card < 100 || card > 503) { - logInfo("无效的牌值: " + card); - return false; - } - - int suit = card / 100; - int rank = card % 100; - - // 验证花色和点数是否有效 - if (suit < 1 || suit > 5) { - logInfo("无效的花色: " + suit); - return false; - } - - // 万、筒、条(花色1-3)的点数应为1-9 - if (suit >= 1 && suit <= 3) { - if (rank < 1 || rank > 9) { - logInfo("无效的点数: " + rank + " 对于花色: " + suit); - return false; - } - } - // 风牌(花色4)的点数应为1-4 - else if (suit == 4) { - if (rank < 1 || rank > 4) { - logInfo("无效的风牌点数: " + rank); - return false; - } - } - // 箭牌(花色5)的点数应为1-3 - else if (suit == 5) { - if (rank < 1 || rank > 3) { - logInfo("无效的箭牌点数: " + rank); - return false; - } - } - } - - return true; - } - - /** - * 获取所有可能的麻将牌(万、筒、条、风牌、箭牌) - * @return 所有可能的麻将牌的列表 - */ - private List getAllPossibleCards() { - List allCards = new ArrayList<>(); - - // 添加万、筒、条(花色1-3,数字1-9) - for (int suit = 1; suit <= 3; suit++) { - for (int rank = 1; rank <= 9; rank++) { - allCards.add(suit * 100 + rank); - } - } - - // 添加风牌(东、南、西、北) - for (int wind = 1; wind <= 4; wind++) { - allCards.add(400 + wind); - } - - // 添加箭牌(中、发、白) - for (int dragon = 1; dragon <= 3; dragon++) { - allCards.add(500 + dragon); - } - - return allCards; - } - - /** - * 验证当手牌添加某张特定牌后是否能胡牌 - * @param handCards 当前手牌 - * @param targetCard 待验证的牌 - * @return 是否能胡牌 - */ - public boolean verifySingleCardCanWin(List handCards, int targetCard) { - if (handCards == null || handCards.isEmpty()) { - return false; - } - - try { - // 创建测试手牌,添加目标牌 - List testHand = new ArrayList<>(handCards); - testHand.add(targetCard); - - // 分析测试手牌 - HandAnalysis analysis = analyzeHand(testHand); - - // 检查是否听牌(实际上在胡牌的情况下,应该是直接能胡) - checkTingPai(analysis); - - // 如果听牌分析认为可以胡牌,返回true - if (analysis.isTingPai) { - return true; - } - - // 额外检查:验证是否能通过不同的牌型组合方式胡牌 - // 检查是否符合基本胡牌条件(四组合一对) - return checkBasicWinCondition(testHand, analysis); - } catch (Exception e) { - logInfo("验证单张牌是否能胡时出错: " + e.getMessage()); - e.printStackTrace(); - return false; - } - } - - /** - * 检查基本胡牌条件(四组合一对) - * @param handCards 手牌 - * @param analysis 手牌分析结果 - * @return 是否符合基本胡牌条件 - */ - private boolean checkBasicWinCondition(List handCards, HandAnalysis analysis) { - // 对手牌进行排序,便于分析 - List sortedHand = new ArrayList<>(handCards); - Collections.sort(sortedHand); - - // 计算牌的数量分布 - Map cardCounts = new HashMap<>(); - for (int card : sortedHand) { - cardCounts.put(card, cardCounts.getOrDefault(card, 0) + 1); - } - - // 检查是否可以形成一对将牌,其余为四组刻子或顺子 - return canFormValidMelds(sortedHand, cardCounts, analysis); - } - - /** - * 递归检查是否可以形成有效的牌组(刻子或顺子)和一对将牌 - * @param handCards 手牌 - * @param cardCounts 牌的数量分布 - * @param analysis 手牌分析结果 - * @return 是否可以形成有效的牌组 - */ - private boolean canFormValidMelds(List handCards, Map cardCounts, HandAnalysis analysis) { - // 尝试将每一张有至少两张的牌作为将牌 - for (Map.Entry entry : cardCounts.entrySet()) { - int card = entry.getKey(); - int count = entry.getValue(); - - if (count >= 2) { - // 创建临时的牌数量分布,减去一对将牌 - Map tempCounts = new HashMap<>(cardCounts); - tempCounts.put(card, count - 2); - - // 检查剩余的牌是否可以形成四组刻子或顺子 - if (checkRemainingCards(tempCounts)) { - return true; - } - } - } - - // 没有找到合适的将牌和牌组组合 - return false; - } - - /** - * 检查剩余的牌是否可以形成刻子或顺子 - * @param cardCounts 牌的数量分布 - * @return 是否可以形成有效的牌组 - */ - private boolean checkRemainingCards(Map cardCounts) { - // 递归终止条件:所有牌都被使用 - if (cardCounts.values().stream().allMatch(count -> count == 0)) { - return true; - } - - // 尝试每一张还有剩余的牌 - for (Map.Entry entry : new HashMap<>(cardCounts).entrySet()) { - int card = entry.getKey(); - int count = entry.getValue(); - - if (count == 0) { - continue; - } - - // 获取牌的花色和点数 - int suit = card / 100; - int rank = card % 100; - - // 尝试组成刻子(3张相同的牌) - if (count >= 3) { - Map tempCounts = new HashMap<>(cardCounts); - tempCounts.put(card, count - 3); - - if (checkRemainingCards(tempCounts)) { - return true; - } - } - - // 对于万、筒、条,尝试组成顺子(3张连续的牌) - if (suit >= 1 && suit <= 3 && rank <= 7) { - int nextCard = suit * 100 + (rank + 1); - int nextNextCard = suit * 100 + (rank + 2); - - if (cardCounts.getOrDefault(nextCard, 0) > 0 && - cardCounts.getOrDefault(nextNextCard, 0) > 0) { - - Map tempCounts = new HashMap<>(cardCounts); - tempCounts.put(card, count - 1); - tempCounts.put(nextCard, tempCounts.get(nextCard) - 1); - tempCounts.put(nextNextCard, tempCounts.get(nextNextCard) - 1); - - if (checkRemainingCards(tempCounts)) { - return true; - } - } - } - } - - return false; - } - - /** - * 综合测试函数:验证单张牌是否能让手牌胡牌 - * @param handCards 玩家手牌 - * @param testCard 要测试的单张牌 - * @param hongZhongCount 红中数量 - * @param tableCards 桌面已打出的牌(用于检查是否点炮等特殊规则) - * @return 胡牌结果信息对象 - */ - public WinResult verifySingleCardCanWin(List handCards, int testCard, int hongZhongCount, List tableCards) { - WinResult result = new WinResult(); - result.testCard = testCard; - result.canWin = false; - result.winTypes = new ArrayList<>(); - result.handCards = new ArrayList<>(handCards); - result.hongZhongCount = hongZhongCount; - - // 开始计时,用于性能统计 - long startTime = System.currentTimeMillis(); - - try { - // 创建测试手牌(将测试牌加入手牌) - List testHandCards = new ArrayList<>(handCards); - testHandCards.add(testCard); - - // 1. 检测是否为正常胡牌(标准型) - boolean normalWin = checkNormalWin(testHandCards, hongZhongCount); - if (normalWin) { - result.canWin = true; - result.winTypes.add("NORMAL"); - } - - // 2. 检测是否为七对子胡牌 - boolean sevenPairsWin = checkSevenPairsWin(testHandCards, hongZhongCount); - if (sevenPairsWin) { - result.canWin = true; - result.winTypes.add("SEVEN_PAIRS"); - } - - // 3. 检测是否为十三幺胡牌 - boolean thirteenOrphansWin = checkThirteenOrphansWin(testHandCards); - if (thirteenOrphansWin) { - result.canWin = true; - result.winTypes.add("THIRTEEN_ORPHANS"); - } - - // 4. 检测是否为特殊牌型胡牌(如清一色、一条龙等) - List specialWinTypes = checkSpecialWinTypes(testHandCards, hongZhongCount); - if (!specialWinTypes.isEmpty()) { - result.canWin = true; - result.winTypes.addAll(specialWinTypes); - } - - // 5. 如果可以胡牌,计算胡牌分数 - if (result.canWin) { - result.winScore = calculateWinScore(result.winTypes, hongZhongCount); - } - - } catch (Exception e) { - logInfo("验证胡牌时出错: " + e.getMessage()); - result.error = e.getMessage(); - } - - // 记录执行时间 - result.executionTime = System.currentTimeMillis() - startTime; - - return result; - } - - /** - * 检查正常胡牌(标准型) - */ - private boolean checkNormalWin(List handCards, int hongZhongCount) { - // 这里应该调用WinSplitCard类的方法进行检测 - // 简化实现,实际需要调用已有胡牌检测逻辑 - try { - // 对输入参数进行预处理,将手牌转换为正确的格式 - // 然后调用WinSplitCard的检测方法 - // 简化返回,实际需要正确实现 - return handCards.size() % 3 == 2 || hongZhongCount > 0; - } catch (Exception e) { - logInfo("检查正常胡牌出错: " + e.getMessage()); - return false; - } - } - - /** - * 检查七对子胡牌 - */ - private boolean checkSevenPairsWin(List handCards, int hongZhongCount) { - // 七对子需要7个对子(14张牌),或有红中时的特殊情况 - if (handCards.size() + hongZhongCount < 14) { - return false; - } - - // 统计每种牌的数量 - Map cardCounts = new HashMap<>(); - for (int card : handCards) { - cardCounts.put(card, cardCounts.getOrDefault(card, 0) + 1); - } - - // 七对子的基本要求:成对的牌数量 + 红中可能组成的对子数 >= 7 - int pairCount = 0; - int oddCount = 0; - - for (int count : cardCounts.values()) { - pairCount += count / 2; - if (count % 2 != 0) { - oddCount++; - } - } - - // 红中可以作为对子或代替单张牌 - // 简化实现,红中可以灵活使用 - return (pairCount + hongZhongCount) >= 7; - } - - /** - * 检查十三幺胡牌 - */ - private boolean checkThirteenOrphansWin(List handCards) { - // 十三幺牌型:东南西北中发白 + 三种花色的1和9 - Set requiredCards = new HashSet<>(); - // 添加东南西北中发白(简化表示,实际需要根据游戏具体规则) - requiredCards.add(301); // 东 - requiredCards.add(302); // 南 - requiredCards.add(303); // 西 - requiredCards.add(304); // 北 - requiredCards.add(305); // 中 - requiredCards.add(306); // 发 - requiredCards.add(307); // 白 - // 添加万、筒、条的1和9(简化表示) - requiredCards.add(101); requiredCards.add(109); - requiredCards.add(201); requiredCards.add(209); - requiredCards.add(401); requiredCards.add(409); - - // 检查是否包含所有必要的幺九牌 - Set handCardSet = new HashSet<>(handCards); - boolean hasAllOrphans = true; - for (int required : requiredCards) { - if (!handCardSet.contains(required)) { - hasAllOrphans = false; - break; - } - } - - // 十三幺要求至少13种不同的幺九牌,再加上其中任意一张组成对子 - if (!hasAllOrphans) { - return false; - } - - // 统计是否有至少一对 - Map cardCounts = new HashMap<>(); - for (int card : handCards) { - cardCounts.put(card, cardCounts.getOrDefault(card, 0) + 1); - if (cardCounts.get(card) >= 2) { - return true; // 找到对子,符合十三幺条件 - } - } - - return false; - } - - /** - * 检查特殊牌型胡牌 - */ - private List checkSpecialWinTypes(List handCards, int hongZhongCount) { - List specialTypes = new ArrayList<>(); - - // 检查清一色(所有牌同一花色,红中不计入) - boolean isPureColor = checkPureColor(handCards); - if (isPureColor) { - specialTypes.add("PURE_COLOR"); - } - - // 检查一条龙(包含同一花色的1-9) - boolean isOneDragon = checkOneDragon(handCards); - if (isOneDragon) { - specialTypes.add("ONE_DRAGON"); - } - - // 检查碰碰胡(全是刻子和一对将牌) - boolean isAllTriplets = checkAllTriplets(handCards, hongZhongCount); - if (isAllTriplets) { - specialTypes.add("ALL_TRIPLETS"); - } - - return specialTypes; - } - - /** - * 检查清一色 - */ - private boolean checkPureColor(List handCards) { - if (handCards.isEmpty()) { - return false; - } - - // 获取第一张牌的花色 - int firstSuit = handCards.get(0) / 100; - - // 检查所有牌是否同花色 - for (int card : handCards) { - if (card / 100 != firstSuit) { - return false; - } - } - - return true; - } - - /** - * 检查一条龙 - */ - private boolean checkOneDragon(List handCards) { - // 按花色分组 - Map> cardsBySuit = new HashMap<>(); - for (int card : handCards) { - int suit = card / 100; - int value = card % 100; - - cardsBySuit.putIfAbsent(suit, new HashSet<>()); - cardsBySuit.get(suit).add(value); - } - - // 检查每种花色是否包含1-9 - for (Set values : cardsBySuit.values()) { - boolean hasFullSequence = true; - for (int i = 1; i <= 9; i++) { - if (!values.contains(i)) { - hasFullSequence = false; - break; - } - } - if (hasFullSequence) { - return true; - } - } - - return false; - } - - /** - * 检查碰碰胡 - */ - private boolean checkAllTriplets(List handCards, int hongZhongCount) { - // 统计每种牌的数量 - Map cardCounts = new HashMap<>(); - for (int card : handCards) { - cardCounts.put(card, cardCounts.getOrDefault(card, 0) + 1); - } - - int tripletCount = 0; - int pairCount = 0; - - for (int count : cardCounts.values()) { - tripletCount += count / 3; - int remainder = count % 3; - if (remainder == 2) { - pairCount++; - } else if (remainder == 1) { - // 有单张牌,可能无法形成碰碰胡 - // 但可以用红中代替 - } - } - - // 碰碰胡需要4个刻子和1个对子 - // 红中可以作为刻子或对子使用 - int possibleTripletsFromHongZhong = hongZhongCount / 3; - int remainingHongZhong = hongZhongCount % 3; - - int totalTriplets = tripletCount + possibleTripletsFromHongZhong; - int neededTriplets = Math.max(0, 4 - totalTriplets); - - // 检查是否可以通过剩余红中满足需求 - return (neededTriplets <= remainingHongZhong / 2) && (pairCount == 1 || (pairCount == 0 && remainingHongZhong >= 2)); - } - - /** - * 计算胡牌分数 - */ - private int calculateWinScore(List winTypes, int hongZhongCount) { - int baseScore = 1; - - // 根据胡牌类型增加分数 - for (String winType : winTypes) { - switch (winType) { - case "NORMAL": - baseScore *= 1; - break; - case "SEVEN_PAIRS": - baseScore *= 2; - break; - case "THIRTEEN_ORPHANS": - baseScore *= 16; - break; - case "PURE_COLOR": - baseScore *= 4; - break; - case "ONE_DRAGON": - baseScore *= 2; - break; - case "ALL_TRIPLETS": - baseScore *= 2; - break; - } - } - - // 红中奖励 - baseScore += hongZhongCount; - - return baseScore; - } - - /** - * 胡牌结果信息类 - */ - public static class WinResult { - public int testCard; // 测试的牌 - public boolean canWin; // 是否可以胡牌 - public List winTypes; // 胡牌类型列表 - public int winScore; // 胡牌分数 - public List handCards; // 玩家手牌 - public int hongZhongCount; // 红中数量 - public long executionTime; // 执行时间(毫秒) - public String error; // 错误信息(如果有) - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("WinResult{testCard=").append(testCard) - .append(", canWin=").append(canWin) - .append(", winTypes=").append(winTypes) - .append(", winScore=").append(winScore) - .append(", executionTime=").append(executionTime).append("ms") - .append(", hongZhongCount=").append(hongZhongCount); - - if (error != null) { - sb.append(", error='").append(error).append("'"); - } - - sb.append("}"); - return sb.toString(); - } - } - - - - - } \ No newline at end of file