您的位置:首页 > 编程语言 > Java开发

深入解析棋牌湖南放炮罚,跑胡子手游源码(java版)

2017-01-05 11:20 302 查看

深入解析棋牌湖南放炮罚,跑胡子手游后台源码(java版)

最近开发了一款湖南放炮罚的房卡模式带三级分销的手游,现在我就将我开发中的思路给朋友们分享一下。

首先介绍一下棋牌游戏最近的火热度吧。

最近微信群和朋友圈中忽然流行起了一款APP手机棋牌房卡麻将游戏,微信群各种被刷,朋友圈也被各霸了,约战的,晒成绩的,开好房间,约上好友,酣战一场!

这就是“ APP手机棋牌房卡麻将游戏”,一款将传统麻将机搬上智能手机,利用零散闲碎的空余时间与好友来一场说约就约的局的手机游戏。手机房卡麻将”来源于传统桌麻,游戏玩法与桌麻相差不大。玩家无需注册,可以直接微信登陆,方便快捷。登陆后便有一定数量免费房卡可供开房,开房后分享到微信群里,喊上好友输入房间号便可开局了。

说说放炮罚的游戏玩法,这个对理解开发很有作用。

点击链接查看跑胡子规则

下面就具体说说开发这一快吧,这里具体讲讲思路

一,设计数据库

数据库设计这块是根据现有的需求来设计的。比如现在我们是房卡模式,具有回放功能,战绩查询功能,发公告的功能。聊天等这里就可以根据自己的需求去设计。

二,通讯协议的拟定

这里的通讯协议像棋牌手游这种肯定是选用长连接。用soket协议,具体的自己去封装一下,这里不做具体的讲解。

三,创建房间

/**
* 创建房间
* @param avatar
*/
public void CreateRoom(Avatar avatar){
//这里设置房间的创建者是一个全局变量
createAvator = avatar;
//初始化一个集合用于装在这个房间的玩家VO
roomVO.setPlayerList(new ArrayList<AvatarVO>());
//这里初始化房间的玩家
playerList = new ArrayList<Avatar>();
//设置是否是庄家
avatar.avatarVO.setMain(true);
//这里将房间的信息设置到人员里面去,便于以后的调用
avatar.setRoomVO(roomVO);
//添加到玩牌的玩家集合中去
playerList.add(avatar);
roomVO.getPlayerList().add(avatar.avatarVO);
}


四,进入房间

/**
* 进入房间,
* @param avatar
*/
public  boolean intoRoom(Avatar avatar){
//当玩家的人数等于三的时候就发送消息给该玩家房间人数满了。不能继续加入了
if(playerList.size() == 3){
try {
avatar.getSession().sendMsg(newErrorResponse(ErrorCode.Error_000011));
} catch (IOException e) {
e.printStackTrace();
}
return false;
}else {
//设置后面的加入房间的人都不是庄家因为我们默认是开房的人事庄家
avatar.avatarVO.setMain(false);
//房间号也放入avatarvo中
avatar.avatarVO.setRoomId(roomVO.getRoomId());
avatar.setRoomVO(roomVO);
//通知房间里面的其他几个玩家
noticJoinMess(avatar);
playerList.add(avatar);
roomVO.getPlayerList().add(avatar.avatarVO);
RoomManager.getInstance().addUuidAndRoomId(avatar.avatarVO.getAccount().getUuid()
,roomVO.getRoomId());
avatar.getSession().sendMsg(new JoinRoomResponse(1, roomVO));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
}
}


五,检测是否可以开始游戏,退出房间,申请解散房间

这里就自己去想想实现代码了这里占不介绍。

六,游戏准备

当加入房间后我们去判断准备的人是不是三个人都准备了。如果都准备了我们就开始游戏。

七,初始化牌

由于现在我们是湖南的放炮罚。所以我们有八十张牌,

大的  壹、贰、叁、肆、伍、陆、柒、捌、玖、拾    各四张
小的  一、二、三、四、五、六、七、八、九、十    各四张


这里初始化一个全局的数组。size=20的 他的索引就是牌的值,数组对应索引出对应的值就是牌的数量。列如:

//代表的就是 二、二、三、三、三、四、四、四、五、六、七、七、九、九、九、十、叁、叁、叁这些牌
int[] paiArray={0, 2, 3,3, 1, 1, 2, 0, 3, 1, 0, 0,3, 0, 0, 0, 0, 0, 0, 0};


下面就是初始化牌的代码

/**
* 初始化牌
*/
public void initCard(RoomVO value) {
roomVO = value;
paiCount = 20;
listCard = new ArrayList<Integer>();
for (int i = 0; i < paiCount; i++) {
for (int k = 0; k < 4; k++) {
listCard.add(i);
}
}

for (int i = 0; i < playerList.size(); i++) {
playerList.get(i).avatarVO.setPaiArray(new int[2][paiCount]);
}
// 洗牌
shuffleTheCards();
// 发牌
dealingTheCards();
}
/**
* 随机洗牌
*/
public void shuffleTheCards() {
Collections.shuffle(listCard);
Collections.shuffle(listCard);
}


当然发牌后就得检查是否有起手胡的情况和是否有提(放炮罚中是提其实就是相当于四川麻将的直杠)的情况了。如果有则给客户端发有胡的消息。或者是杠的消息。客户端操作后调用我们的胡的协议或者杠的协议。

八,出牌

/**
* 出牌
*
* @param avatar
* @param cardPoint
*/
public void putOffCard(Avatar avatar, int cardPoint) {
System.err.println("出牌:"+cardPoint);
System.err.println("出牌:玩家号"+playerList.indexOf(avatar)+"出牌前旧牌:"+avatar.printPaiString());
System.err.println("出牌:玩家号"+playerList.indexOf(avatar)+"出牌前新牌:"+avatar.printNewPaiString());
//添加当前的操作
for (int i = 0; i < playerList.size(); i++) {
playerList.get(i).avatarVO.addOperation(playerList.indexOf(avatar),"chupai",cardPoint);
}
avatar.avatarVO.setHasMopaiChupai(true);// 修改出牌 摸牌状态
// 已经出牌就清除所有的吃,碰,杠,胡的数组
clearAvatar();
//当前出的牌
putOffCardPoint = cardPoint;
System.out.println("出牌点数"+putOffCardPoint+"---出牌人索引:"+playerList.indexOf(avatar));
//出牌人索引
curAvatarIndex = playerList.indexOf(avatar);
PlayRecordOperation(curAvatarIndex, cardPoint, 1, -1, null, null);
avatar.pullCardFormList(putOffCardPoint);
for (int i = 0; i < playerList.size(); i++) {
// 不能返回给自己
if (i != curAvatarIndex) {
playerList
.get(i)
.getSession()
.sendMsg(
new ChuPaiResponse(1, putOffCardPoint,
curAvatarIndex));
//               System.out.println("发送打牌消息----"+playerList.get(i).avatarVO.getAccount().getNickname());
} else {
playerList.get(i).gangIndex.clear();// 每次出牌就先清除缓存里面的可以杠的牌下标
}
}
// 出牌时,房间为可抢杠胡并且有癞子时才检测其他玩家有没胡的情况
Avatar ava;
StringBuffer sbs = new StringBuffer();
boolean checkGang=false;
boolean checkPeng=false;
boolean checkChi=false;
boolean checkHu=false;
int chick=0;
for (int i = 0; i < playerList.size(); i++) {
ava = playerList.get(i);
checkGang = ava.checkGang(putOffCardPoint);
checkPeng =
1eba6
ava.checkPeng(putOffCardPoint);
if(checkGang){
chick+=1;
}
if(checkPeng){
chick+=1;
}
}

for (int i = 0; i < playerList.size(); i++) {
ava = playerList.get(i);
StringBuffer sb = new StringBuffer();
ava.chiIndex.clear();
ava.biIndex.clear();
// 判断吃,碰, 胡 杠的时候需要把以前吃,碰,杠胡的牌踢出再计算
checkGang = ava.checkGang(putOffCardPoint);
checkPeng = ava.checkPeng(putOffCardPoint);
checkHu = ava.checkHu(putOffCardPoint);
checkChi =  ava.checkChi(putOffCardPoint);
if (checkHu&&(ava.getUuId() != avatar.getUuId())&&!ava.guoHu) {
huAvatar.add(ava);
// 同时传会杠的牌的点数
sb.append("hu:" + putOffCardPoint + ",");
}

if (checkGang&&(ava.getUuId() != avatar.getUuId())) {
gangAvatar.add(ava);
System.err.println("打牌有杠 是否是二次杠的值:"+ava.isfirstGang);

if(ava.isfirstGang>0){
// 同时传会杠的牌的点数
sb.append("gang:" + putOffCardPoint + ","+"ergang"+",");
}else{
// 同时传会杠的牌的点数
sb.append("gang:" + putOffCardPoint + ","+""+",");
}
}
if (checkPeng&&!checkGang&&(ava.getUuId() != avatar.getUuId())&&!ava.guoHu) {
penAvatar.add(ava);
sb.append("peng:" + curAvatarIndex + ":"
+ putOffCardPoint + ",");
}
//放炮罚。。。检查吃只有下一家才能吃
if ( roomVO.getRoomType() == 4 &&checkChi&& getNextAvatarIndex() ==i&&!checkGang&&!checkPeng&&!ava.guoHu&&chick==0){
chiAvatar.add(ava);
sb.append("chi:"+curAvatarIndex+":"+ putOffCardPoint + ",");
}else{
ava.chiIndex.clear();
ava.biIndex.clear();
}
if (sb.length() > 1) {
/*
* try { Thread.sleep(300); } catch
* (InterruptedException e) { e.printStackTrace(); }
*/
try { Thread.sleep(2000); } catch
(InterruptedException e) { e.printStackTrace(); }
sbs.append(sb);
if(chiAvatar.size()>0&&!sb.toString().contains("gang")&&!sb.toString().contains("peng")&&!sb.toString().contains("hu")&&ava.chiIndex.size()>0){
HashMap<String, Object> map = new HashMap<>();
System.out.println("打牌:吃的组合:"+ava.chiIndex);
map.put("chiIndexList", ava.chiIndex);
ava.getSession().sendMsg(
new ReturnInfoResponse(1, sb.toString(),map));
System.out.println("打牌:有吃的情况下返回给前段的数据-------------"+sb+map);
}else {
ava.getSession().sendMsg(
new ReturnInfoResponse(1, sb.toString()));
System.out.println("打牌:有碰胡杠的情况下返回给前段的数据----------"+sb);
}
// responseMsg = new ReturnInfoResponse(1,
// sb.toString());
// lastAvtar = ava;
ava.chiIndex.clear();
ava.biIndex.clear();
}
}
System.err.println("出牌:玩家号"+playerList.indexOf(avatar)+"出牌后旧牌:"+avatar.printPaiString());
System.err.println("出牌:玩家号"+playerList.indexOf(avatar)+"出牌后新牌:"+avatar.printNewPaiString());
// 如果没有吃,碰,杠,胡的情况,则下家自动摸牌
String string = new String(sbs);
if(string.contains("hu")||(string.contains("gang")&&!string.contains("ergang"))||string.contains("peng")||string.contains("chi")||string.contains("zjHu")){
System.out.println("打牌:有胡或碰或吃的时候不调用自动摸牌");
}else {

// 出牌信息放入到缓存中,掉线重连的时候,返回房间信息需要
//              avatar.avatarVO.updateChupais(cardPoint);
if(string.contains("ergang")){
try { Thread.sleep(2000); } catch
(InterruptedException e) { e.printStackTrace(); }
}else {
avatar.avatarVO.addChupais(cardPoint,playerList.indexOf(avatar));
}

try { Thread.sleep(1000); } catch
(InterruptedException e) { e.printStackTrace(); }
System.out.println("打牌:调用自动摸牌");
chuPaiCallBack();
}
}


代码有点乱说说思路吧:

1,首先出牌了就清除以前的用于装吃碰杠胡的玩家的信息。

2,判断出的这张牌是否有胡,碰,杠,吃的情况如果有就给相应的玩家发送消息。让玩家操作。

3,如果没有就自己调用下家自动摸牌的方法。下家自动摸牌。当然这里必须清除当前操作的玩家的索引和下家玩家的索引。

4,当判断到有胡,碰,杠,吃的情况后向客户端发送消息,等待客户端做操作。他可以选择胡,碰,杠,吃,和放弃的操作。

九,摸牌

/**
* 摸牌
*
*
*/
public void pickCard() {
clearAvatar();
// 摸牌
pickAvatarIndex = getNextAvatarIndex();
// pickAvatarIndex = nextIndex;
// 本次摸得牌点数,下一张牌的点数,及本次摸的牌点数
int tempPoint = getNextCardPoint();
System.out.println("摸牌:"+tempPoint+"----上一家出牌"+putOffCardPoint+"--摸牌人索引:"+pickAvatarIndex);
//添加当前的操作断线重连用的数据
for (int i = 0; i < playerList.size(); i++) {
playerList.get(i).avatarVO.addOperation(pickAvatarIndex,"mopai",tempPoint);
}
if (tempPoint != -1) {
// 回放记录
PlayRecordOperation(pickAvatarIndex, tempPoint, 2, -1, null, null);

currentCardPoint = tempPoint;
Avatar avatar = playerList.get(pickAvatarIndex);

System.err.println("摸牌:玩家号"+playerList.indexOf(avatar)+"摸牌前旧牌:"+avatar.printPaiString());
System.err.println("摸牌:玩家号"+playerList.indexOf(avatar)+"摸牌前新牌:"+avatar.printNewPaiString());

avatar.avatarVO.setHasMopaiChupai(true);// 修改出牌 摸牌状态
avatar.qiangHu = true;
avatar.canHu = true;
avatar.iszjPeng = false;

// 摸起来也要判断是否可以杠,胡
boolean checkPeng = avatar.checkPeng(tempPoint);
boolean checkSelfGang = avatar.checkGang(tempPoint);
boolean checkHu = avatar.checkHu(tempPoint);
if(checkPeng){
}else {
avatar.putCardInList(tempPoint);
}
//移除摸到的牌
StringBuffer sb = new StringBuffer();
if(checkPeng||checkSelfGang||checkHu){
if (checkHu&&!avatar.guoHu) {
avatar.iszjHu=true;
huAvatar.add(avatar);
sb.append("zjHu:" + pickAvatarIndex + ":"
+ tempPoint + ",");

}
if (checkSelfGang) {
avatar.iszjGang=true;
gangAvatar.add(avatar);
System.err.println("摸牌有杠 是否是二次杠的值:"+avatar.isfirstGang);
if(avatar.isfirstGang>0){//证明已经杠了一次
sb.append("zjErGang");
for (int i : avatar.gangIndex) {
sb.append(":" + i);
}
sb.append(",");

sb.append("zjGang");
for (int i : avatar.gangIndex) {
sb.append(":" + i);
}
sb.append(",");
}else {
sb.append("zjGang");
for (int i : avatar.gangIndex) {
sb.append(":" + i);
}
sb.append(",");

}

//                   avatar.gangIndex.clear();//9-18出牌了才清楚(在杠时断线重连后需要这里面的数据)
}
if (checkPeng&&!checkSelfGang) {
avatar.setIszjPeng(true);
penAvatar.add(avatar);
sb.append("zjPeng:" + pickAvatarIndex + ":"
+ tempPoint + ",");

}
if (sb.length() > 2) {
if(!sb.toString().contains("zjHu")&&sb.toString().contains("zjErGang")){
System.out.println("自己摸牌摸到有二次的杠牌发送消息:"+sb.toString());
System.out.println("自己摸牌摸到有二次的杠牌调用下家自动摸牌");
try { Thread.sleep(1000); } catch
(InterruptedException e) { e.printStackTrace(); }
avatar.getSession().sendMsg(
new ReturnInfoResponse(1, sb.toString()));
//有二次杠的时候调用下家自动摸牌
System.out.println("自己摸牌摸到有二次的杠牌调用下家自动摸牌");
try { Thread.sleep(2000); } catch
(InterruptedException e) { e.printStackTrace(); }
chuPaiCallBack();
}else {
System.out.println("摸牌:有胡碰杠的情况发送消息:"+sb.toString());
avatar.getSession().sendMsg(
new ReturnInfoResponse(1, sb.toString()));
}
}
System.err.println("摸牌:玩家号"+playerList.indexOf(avatar)+"摸牌后旧牌:"+avatar.printPaiString());
System.err.println("摸牌:玩家号"+playerList.indexOf(avatar)+"摸牌后新牌:"+avatar.printNewPaiString());

}else{
avatar.getSession().sendMsg(new PickCardResponse(1, tempPoint));
System.out.println("摸牌:没有胡碰杠的情况发送消息:"+tempPoint);
for (int i = 0; i < playerList.size(); i++) {
if (i != pickAvatarIndex) {
playerList
.get(i)
.getSession()
.sendMsg(
new OtherPickCardResponse(1,
pickAvatarIndex));
System.out.println("摸牌:没有胡碰杠的情况循环提示其他用户消息:"+pickAvatarIndex);
} else {
playerList.get(i).gangIndex.clear();// 每次摸牌就先清除缓存里面的可以杠的牌下标
}
}
}

} else {
//黄庄
int totalCount = roomVO.getRoundNumber();
int useCount = RoomManager.getInstance().getRoom(roomVO.getRoomId())
.getCount();
if (roomVO.getCurrentRound()==1) {
// 第一局结束扣房卡
deductRoomCard();
}

// System.out.println("流局");
PlayRecordOperation(pickAvatarIndex, -1, 9, -1, null, null);
// 流局处理,直接算分
HashMap<String, Object> map = new HashMap<>();
//获取到底牌
ArrayList<Object> diPaiList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
int nextCardPoint = getNextCardPoint();
if(nextCardPoint!=-1){
diPaiList.add(nextCardPoint);
}
}

//          if((playerList.get(0).huInterestCont>=playerList.get(0).getRoomVO().getToCount()*100)||(playerList.get(1).huInterestCont>=playerList.get(1).getRoomVO().getToCount()*100)||(playerList.get(2).huInterestCont>=playerList.get(2).getRoomVO().getToCount()*100)){//牌局结束
if((playerList.get(0).huInterestCont>=100)||(playerList.get(1).huInterestCont>=100)||(playerList.get(2).huInterestCont>=100)){//牌局结束
ArrayList<Object> arrayList = new ArrayList<>();
//获取三个玩家的最后得到的胡息数
playerList.get(0).huInterest=(playerList.get(0).huInterest-playerList.get(1).huInterest)+(playerList.get(0).huInterest-playerList.get(2).huInterest);
playerList.get(1).huInterest=(playerList.get(1).huInterest-playerList.get(0).huInterest)+(playerList.get(1).huInterest-playerList.get(2).huInterest);
playerList.get(2).huInterest=(playerList.get(2).huInterest-playerList.get(1).huInterest)+(playerList.get(2).huInterest-playerList.get(1).huInterest);
for (int i = 0; i <playerList.size(); i++) {
//当前分数加入总胡息数
playerList.get(i).huInterestCont+= playerList.get(i).huInterest;

HashMap<String, Object> retmap = new HashMap<>();
retmap.put("thishuInterest", playerList.get(i).huInterest);
retmap.put("roomhuInterest", playerList.get(i).huInterestCont);
retmap.put("fowling", 0);
retmap.put("thisintegral", playerList.get(i).huInterest);
arrayList.add(retmap);
}
for (int i = 0; i < playerList.size(); i++) {
map.put("huIndex", -1);
map.put("faPaoIndex", -1);
map.put("arrayList", arrayList);
map.put("diPai", diPaiList);
playerList
.get(i)
.getSession()
.sendMsg(new HuPaiAllResponse(1,JsonUtilTool.toJson(map)));
//发送消息之后清除
}
// 游戏回放
//              PlayRecordOperation(playerList.indexOf(avatar), cardIndex,
//                      playRecordType, -1, null, null);
addStandings();
// 4局完成之后解散房间//销毁
RoomLogic roomLogic = RoomManager.getInstance().getRoom(
roomVO.getRoomId());
roomLogic.destoryRoomLogic();
roomLogic = null;

}else {
ArrayList<Object> arrayList = new ArrayList<>();
//获取三个玩家的最后得到的胡息数
for (int i = 0; i <playerList.size(); i++) {
HashMap<String, Object> retmap = new HashMap<>();
retmap.put("thishuInterest", playerList.get(i).huInterest);
retmap.put("roomhuInterest", playerList.get(i).huInterestCont);
retmap.put("fowling", 0);
retmap.put("thisintegral", playerList.get(i).huInterest);
arrayList.add(retmap);
}
addStandings();
//当别人放炮的时候
for (int i = 0; i < playerList.size(); i++) {
map.put("huIndex", -1);
map.put("faPaoIndex", -1);
map.put("arrayList", arrayList);
map.put("diPai", diPaiList);
playerList
.get(i)
.getSession()
.sendMsg(new HuPaiResponse(1,JsonUtilTool.toJson(map)));
//发送消息之后清除
playerList.get(i).huInterest=0;
playerList.get(i).HuCardsMultiples=1;
playerList.get(i).HuCardsScore=0;

//修改庄家为下一家
if (playerList.get(i).avatarVO.isMain()) {
playerList.get(i).avatarVO.setMain(false);
if(i==0){
bankerAvatar = playerList.get(1);
playerList.get(1).avatarVO.setMain(true);
}
if(i==1){
bankerAvatar = playerList.get(2);
playerList.get(2).avatarVO.setMain(true);
}
if(i==2){
bankerAvatar = playerList.get(0);
playerList.get(0).avatarVO.setMain(true);
}
}

}
// 游戏回放
PlayRecordOperation(playerList.indexOf(avatar), cardIndex,
}

singleOver = true;// 10-11新增
}
}


同样的总结一下思路吧

1,判断摸到的这个牌,和自己的牌做对比是否可以碰,杠,胡和出牌时一样的判断方法,只不过这里是只判断自己。

2,如果有碰,杠,胡那么向客户端发送消息。由客户端去操作。并向我返回消息。

3,如果没有那么就将自己摸到的牌打出去。

4,如果摸牌的时候,发现底牌没有可以摸的了。那么就是黄庄了。调用结算的方法。结算。

十,判断吃

/**
* 檢測是否可以吃
* @param cardIndex
* @return
*/
public boolean checkChi(int cardIndex){
boolean flag = false;
//system.out.println("判断吃否可以吃牌-----cardIndex:"+cardIndex);
/**
* 这里检测吃的时候需要踢出掉碰 杠了的牌****
*/
int []  cardList = avatarVO.getChickChiArray();
for (int i = 0; i < cardList.length; i++) {
if(cardList[i]==3){
knack++;
cardList[i]=0;
}
if(cardList[i]==4){
knack++;
cardList[i]=0;
}
}
//小1                到                   小10
if(cardIndex>=0  && cardIndex <=9){
if(cardIndex == 0 && cardList[1] >=1 && cardList[2] >=1 ){
flag = true;
putChiIndex(0,1,2);
}
if (cardIndex == 0 &&(cardList[10] >=2)) {
flag = true;
putChiIndex(0,10,10);
} if(cardIndex == 1 && cardList[0] >=1 && cardList[2] >=1){
flag = true;
putChiIndex(1,0,2);
} if (cardIndex == 1 &&cardList[3] >=1 && cardList[2] >=1) {
flag = true;
putChiIndex(1,3,2);
} if (cardIndex == 1 &&cardList[11] >=2) {
flag = true;
putChiIndex(1,11,11);
} if(cardIndex ==9 &&cardList[8] >=1 && cardList[7] >=1){
flag = true;
putChiIndex(9,8,7);
} if(cardIndex ==9 &&cardList[19] >=2){
flag = true;
putChiIndex(cardIndex,cardList[9],cardList[9]);
} if(cardIndex ==8 && cardList[9] >=1 && cardList[7] >=1){
flag = true;
putChiIndex(8,9,7);
} if(cardIndex ==8 && cardList[6] >=1 && cardList[7] >=1){
flag = true;
putChiIndex(8,6,7);
} if(cardIndex ==8 &&cardList[18] >=2) {
flag = true;
putChiIndex(8,18,18);
} if(cardIndex==1&&cardList[6] >=1&&cardList[9] >=1){
flag = true;
putChiIndex(1,6,9);
} if(cardIndex==6&&cardList[1] >=1&&cardList[9] >=1){
flag = true;
putChiIndex(6,1,9);
} if(cardIndex==9&&cardList[1] >=1&&cardList[6] >=1){
flag = true;
putChiIndex(9,1,6);
} if(cardIndex>=2&&cardIndex<=7){//2 到  7
if(cardList[cardIndex-1] >=1 && cardList[cardIndex+1] >=1){
flag = true;
putChiIndex(cardIndex,cardIndex-1,cardIndex+1);
} if (cardList[cardIndex-1] >=1 && cardList[cardIndex-2] >=1) {
flag = true;
putChiIndex(cardIndex,cardIndex-1,cardIndex-2);
} if (cardList[cardIndex+1] >=1 && cardList[cardIndex+2] >=1){
flag = true;
putChiIndex(cardIndex,cardIndex+1,cardIndex+2);
} if ((cardList[cardIndex+10] >=2)){
flag = true;
putChiIndex(cardIndex,cardIndex+10,cardIndex+10);
}
if ((cardList[cardIndex+10] >=1&&cardList[cardIndex]>=1)){
flag = true;
putChiIndex(cardIndex,cardIndex,cardIndex+10);
}
}
}else if (cardIndex>=10  && cardIndex <=19) {
if(cardIndex == 10 && cardList[11] >=1 && cardList[12] >=1 ){
flag = true;
putChiIndex(10,11,12);
}
if (cardIndex == 10 &&(cardList[0] >=2)) {
flag = true;
putChiIndex(10,0,0);
} if(cardIndex == 11 && cardList[10] >=1 && cardList[12] >=1){
flag = true;
putChiIndex(11,10,12);
} if (cardIndex == 11 &&cardList[13] >=1 && cardList[12] >=1) {
flag = true;
putChiIndex(11,13,12);
} if (cardIndex == 11 &&cardList[1] >=2) {
flag = true;
putChiIndex(11,1,1);
} if(cardIndex ==19 &&cardList[18] >=1 && cardList[17] >=1){
flag = true;
putChiIndex(19,18,17);
} if(cardIndex ==19 &&cardList[9] >=2){
flag = true;
putChiIndex(19,9,9);
} if(cardIndex ==18 && cardList[19] >=1 && cardList[17] >=1){
flag = true;
putChiIndex(18,19,17);
} if(cardIndex ==18 && cardList[16] >=1 && cardList[17] >=1){
flag = true;
putChiIndex(18,16,17);
} if(cardIndex ==18 &&cardList[8] >=2) {
flag = true;
putChiIndex(18,8,8);
} if(cardIndex==11&&cardList[16] >=1&&cardList[19] >=1){
flag = true;
putChiIndex(11,16,19);
} if(cardIndex==16&&cardList[11] >=1&&cardList[19] >=1){
flag = true;
putChiIndex(16,11,19);
} if(cardIndex==19&&cardList[11] >=1&&cardList[16] >=1){
flag = true;
putChiIndex(19,11,16);
} if(cardIndex>=12&&cardIndex<=17){//2 到  7
if(cardList[cardIndex-1] >=1 && cardList[cardIndex+1] >=1){
flag = true;
putChiIndex(cardIndex,cardIndex-1,cardIndex+1);
} if (cardList[cardIndex-1] >=1 && cardList[cardIndex-2] >=1) {
flag = true;
putChiIndex(cardIndex,cardIndex-1,cardIndex-2);
} if (cardList[cardIndex+1] >=1 && cardList[cardIndex+2] >=1){
flag = true;
putChiIndex(cardIndex,cardIndex+1,cardIndex+2);
} if ((cardList[cardIndex-10] >=2)){
flag = true;
putChiIndex(cardIndex,cardIndex-10,cardIndex-10);
}
if ((cardList[cardIndex-10] >=1&&cardList[cardIndex]>=1)){
flag = true;
putChiIndex(cardIndex,cardIndex,cardIndex-10);
}
}

}else {
System.out.println("判断吃的时候索引越界:传入的牌:"+cardIndex);
}
//检查吃的时候如果有吃。那么看手里的牌是否有这个组合。如果有,那么是否可以比牌。有比才可以吃。
if(flag&&cardList[cardIndex]>=1&&chiIndex.size()>0){
int kk =0;
for (int i = 0; i < chiIndex.size(); i++) {
Map<String, Object> chiMap = chiIndex.get(i);
Integer chipai = (Integer) chiMap.get("chipai");
Integer chipai1 = (Integer) chiMap.get("chipai1");
Integer chipai2 = (Integer) chiMap.get("chipai2");
boolean bo1=(chipai==chipai1);
boolean bo2=(chipai==chipai2);
boolean bo3=(chipai1==chipai2);
boolean bo=(chipai==chipai1?true:chipai==chipai2?true:chipai1==chipai2?true:false);

if(cardList[chipai]>=1&&cardList[chipai1]>=1&&cardList[chipai2]>=1&&!bo){
kk++;
}
if (bo&&bo1&&cardList[chipai]>=1&&cardList[chipai2]>=1) {
kk++;
}
if (bo&&bo2&&cardList[chipai]>=1&&cardList[chipai1]>=1) {
kk++;
}
if (bo&&bo3&&cardList[chipai]>=1&&cardList[chipai2]>=1) {
kk++;
}
}
if(kk<2){
flag=false;
}

}
return flag;
}


总结一下吧。上面这个代码写的 不好,但是可以解决吃的问题。

大概的思路就是。用于判断吃的数组,是手牌。是排除了碰杠的情况下的数据。然后用写死的方式去判断一些特殊的组合。通用的组合处理通用的吃得数据。

十一,检查碰

/**
* 檢測是否可以碰 大于等于2张可以碰
* @param cardIndex
* @return
*/
public boolean checkPeng(int cardIndex){
boolean flag = false;
if(avatarVO.getPaiArray()[0][cardIndex] == 2 ){
if(resultRelation.get(1) == null ){
flag = true;
}
else{
String strs [] = resultRelation.get(1).split(",");
for (int i = 0; i < strs.length; i++) {
if(strs[i].equals(cardIndex+"")){
flag  =  false;
i = strs.length;
}
else{
flag  =  true;
}
}
}
}
return flag;
}


总结一下。碰的话这里就简单很多了。就是判断我的手牌里面的牌的张数是否大于2大于则可以碰

十二,检查是否可以跑,或者提(就是四川麻将杠的意思)

/**
* 檢測是否可以杠别人出的牌/此牌对应的下标不为1(碰过了的牌)
* @param cardIndex
* @return
*/
public boolean checkGang(int cardIndex){
boolean flag = false;
gangIndex.clear();//每次出牌就先清除缓存里面的可以杠的牌下标
if(avatarVO.getPaiArray()[0][cardIndex] == 3){
gangIndex.add(cardIndex);
flag = true;
}
return flag;
}


检查是否有杠就是检查是否手牌的某一张牌牌的数量为3这里想一下就很容易理解了。但是有个情况是你自己碰 了的牌。再次摸到一张这时也是需要检查的。

十三,检查胡

这里在放炮罚中的胡牌算法。我这是我自己写的一个逻辑。还是有一定的缺陷。但是一般情况写还是可以检测到的。代码如下:

/**
* 检查是否胡牌
* @param tempPoint
* @return
*/
public boolean checkHu(int tempPoint) {
if(this.huInterest>=15){//当胡息数大于15的时候再判断
System.out.println("当前胡息数__"+this.huInterest);

putCardInListAsChi(tempPoint);
int[] atmp1=new int[20];
System.arraycopy(avatarVO.getChickChiArray(), 0, atmp1, 0, 20);
if(HuCardsAlgorithm(atmp1,avatarVO.getPaiArray()[0])){
return true;
}
pullCardFormListAsChi(tempPoint);
}
return false;
}

public void printHuXi(String type,int i) {
System.err.println(type+"后:"+"当前玩家"+i+"胡息数__:"+this.huInterest);
}

public boolean HuCardsAlgorithm(int[] paiArray, int[] js) {
//        int[] paiArray={0, 2, 3,3, 1, 1, 2, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
this.thisknack=0;
for (int i = 0; i < paiArray.length; i++) {
if(paiArray[i]==4){//当牌里面有跑的时候
paiArray[i]=0;
this.thisknack++;
}
if(paiArray[i]==3){//当牌里面有碰
paiArray[i]=0;
this.thisknack++;
}
}
for (int i = 0; i < paiArray.length; i++) {
//当时大小搭的时候也要去除
if(i<=9){
if (paiArray[i] == 1 &&(paiArray[i+10]==2)) {
paiArray[i]=0;
paiArray[i+10]=0;
this.thisknack++;
}
}else {
if (paiArray[i] == 1 &&(paiArray[i-10]==2)) {
paiArray[i]=0;
paiArray[i-10]=0;
this.thisknack++;
}
}
}
//当是2,7,10的时候也要去除
for (int k = 0; k < 2; k++) {
if (paiArray[1] >= 1 &&paiArray[6] >= 1&&paiArray[9] >= 1) {
paiArray[1]--;
paiArray[6]--;
paiArray[9]--;
this.thisknack++;
}
if (paiArray[11] >= 1 &&paiArray[16] >= 1&&paiArray[19] >= 1) {
paiArray[11]--;
paiArray[16]--;
paiArray[19]--;
this.thisknack++;
}
}

for (int i = 0; i < paiArray.length; i++) {
if(this.isfirstGang>0){//如果有提牌或者跑牌那么就判断是否有一对。一对也是一方门子
int  ii=0;
if(paiArray[i]==2&&ii!=1){//当牌里面有碰这里判断只能去掉一对
paiArray[i]=0;
this.thisknack++;
ii=1;
}
}
}
int atmp1[] = new int[10];
int atmp2[] = new int[10];
System.arraycopy(paiArray, 0, atmp1, 0, 10);
System.arraycopy(paiArray, 10, atmp2, 0, 10);

boolean fitThreePairs1 = fitThreePairs(atmp1);
boolean fitThreePairs2 = fitThreePairs(atmp2);
System.out.println("胡牌检测时thisknack="+thisknack+"并且knack="+this.knack);
if(fitThreePairs1&&fitThreePairs2){
System.out.println("恭喜!!胡牌");
int kk=0;
kk+=js[1];
kk+=js[6];
kk+=js[9];
kk+=js[11];
kk+=js[16];
kk+=js[19];
if(kk==1){//只有一张红字的牌
HuCardsMultiples=HuCardsMultiples*2;
}
if(kk>=10&&kk<=12){
HuCardsMultiples=HuCardsMultiples*2;
}
if(kk>=13){
HuCardsScore=100;
}
if(kk==0){//乌胡
HuCardsScore=100;
}
if(js[1]==3||js[6]==3||js[9]==3||js[11]==3||js[16]==3||js[19]==3){//三张一样的红字
HuCardsMultiples=HuCardsMultiples*2;
}
if(huInterest==30){
HuCardsScore=100;
}
if(huInterest==20){
HuCardsMultiples=HuCardsMultiples*2;
}
if(iszjHu){
HuCardsMultiples=HuCardsMultiples*2;
}
//          }

return true;
}else{
System.out.println("继续努力"+"门子:"+(thisknack));
return false;
}
}
public boolean fitThreePairs(int[] cardsNoPair){
int size = cardsNoPair.length;
for (int i = 0; i < size - 2; i++)
{
if (cardsNoPair[i] == 0)
{
continue;
}
if (cardsNoPair[i] == 3 || cardsNoPair[i] == 4)
{
cardsNoPair[i] -= 3;
}
if (cardsNoPair[i] == 2)
{
cardsNoPair[i] -= 2;
cardsNoPair[i + 1] -= 2;
cardsNoPair[i + 2] -= 2;
if(cardsNoPair[i]>=0&&cardsNoPair[i + 1]>=0&&cardsNoPair[i + 2]>=0){
this.thisknack+=2;
}
}
if (cardsNoPair[i] == 1)
{
cardsNoPair[i]--;
cardsNoPair[i + 1]--;
cardsNoPair[i + 2]--;
if(cardsNoPair[i]>=0&&cardsNoPair[i + 1]>=0&&cardsNoPair[i + 2]>=0){
this.thisknack+=1;
}
}
}
// 剩下的牌如果存在必须为3个相同的组合
if (cardsNoPair[size - 2] == 3)
{
cardsNoPair[size - 2] -= 3;
}
if (cardsNoPair[size - 1] == 3)
{
cardsNoPair[size - 1] -= 3;
}
// 胡牌条件是恰好全0
for (int i = 0; i < size; i++)
{
if (cardsNoPair[i] != 0)
{
return false;
}
}
return true;
}


说一下思路吧

1,首先去除手牌里面的跑的牌,杠的牌,大小搭的牌。

2,判断是否有杠,如果有杠那么可以去除一对牌。因为在放炮罚中有杠一对牌是可以当成一个门子的。

3,将手牌分成两个数组。一个数组装小的一到十一个数组装大的一到十

4,分别判断小的,和大的在去除了一句话后。是否数组里面全都是0。

5,如果全是0那么就是证明是胡了。胡的算法在网上搜索到时要组成七方门子。

好了就说到这里吧。记录一下我为这个麻将游戏而失去的青春岁月。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息