删除 YouleNexus 内嵌 .git,统一由根仓库唯一管理。提交: - projects/ 旧 H5 模板 Game_Surface_3 与各子游戏源码 - cocoscreator_projects/YouleNexus 工程 + cocos-creator-mcp 扩展源码 - CLAUDE.md、.mcp.json 等配置 library/temp/node_modules/dist 等缓存由 .gitignore 排除。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
466 lines
14 KiB
JavaScript
466 lines
14 KiB
JavaScript
/*================= cls_aset2: 小局基础类 =================
|
|
注意:
|
|
1,此牌类是基础小局类;各子游戏需要继承此基础类后下编写自己的小局类。
|
|
2,子游戏开发人员不能修改该文件。
|
|
=========================================================*/
|
|
var cls_aset2 = {
|
|
|
|
//================ 新建一小局 ================
|
|
New: function(){
|
|
//定义小局
|
|
var o_aset = this.declare();
|
|
//初始化牌列表
|
|
this.initcardlist(o_aset);
|
|
//除掉不要的牌
|
|
this.deletecard(o_aset);
|
|
//设置每张牌的分值
|
|
this.setcardscore(o_aset);
|
|
return o_aset;
|
|
},
|
|
//小局的数据定义
|
|
declare: function(){
|
|
var o_aset = {};
|
|
//玩家列表
|
|
o_aset.playerlist = []; //在此定义和存储玩家的状态,比如准备状态、叫分的分值、游戏的得分等等,格式如[[], [], ...], [{}, {}, ...], [player, player, ...]
|
|
//牌列表
|
|
o_aset.cardlist = []; //格式为[[], [], [], ...],里面的每个小数组就是一张牌
|
|
//庄(位置)
|
|
o_aset.zhuang = -1;
|
|
//控制权(位置)
|
|
o_aset.control = -1;
|
|
//当前是第几轮出牌
|
|
o_aset.play = 0;
|
|
//当前是本轮的第几个出牌
|
|
o_aset.index = 0;
|
|
|
|
return o_aset;
|
|
},
|
|
//初始化牌列表
|
|
initcardlist: function(o_aset){
|
|
//几副牌
|
|
var card_count = this.get_cardcount();
|
|
//牌类
|
|
var card_class = this.get_cardclass();
|
|
//初始化
|
|
for (var i = 1; i <= card_count; i++){ //几副牌
|
|
for (var j = 1; j <= 4; j++){ //方块、梅花、红心、黑桃四种花色
|
|
for (var k = 1; k <= 13; k++){ //A到K
|
|
var id = (i - 1) * 54 + (j - 1) * 13 + k - 1; //牌的绝对id
|
|
//新建一张牌
|
|
var card_object = card_class.New(id);
|
|
o_aset.cardlist.push(card_object);
|
|
}
|
|
}
|
|
//小王
|
|
var card_object = card_class.New((i - 1) * 54 + 53 - 1);
|
|
o_aset.cardlist.push(card_object);
|
|
//大王
|
|
var card_object = card_class.New((i - 1) * 54 + 54 - 1);
|
|
o_aset.cardlist.push(card_object);
|
|
}
|
|
},
|
|
//几副牌
|
|
get_cardcount: function(){
|
|
return 1;
|
|
},
|
|
//小局对应的牌类
|
|
get_cardclass: function(){
|
|
return cls_card2;
|
|
},
|
|
//除掉不要的牌
|
|
deletecard: function(o_aset){
|
|
for (var i = 0; i < o_aset.cardlist.length; i++){
|
|
var o_card = o_aset.cardlist[i];
|
|
this.get_cardclass().SetDeal(o_card, -1);
|
|
}
|
|
|
|
//下面的代码是3人二七王除掉3、4的例子。类似功能需要在子游戏中重写该方法
|
|
// for (var i = 0; i < o_aset.cardlist.length; i++){
|
|
// var o_card = o_aset.cardlist[i];
|
|
// var card_number = this.get_cardclass().GetNumber(o_card);
|
|
// if (card_number == 3 || card_number == 4){
|
|
// this.get_cardclass().SetDeal(o_card, -2);
|
|
// }
|
|
// }
|
|
},
|
|
//设置每张牌的分值
|
|
setcardscore: function(o_aset){
|
|
for (var i = 0; i < o_aset.cardlist.length; i++){
|
|
var o_card = o_aset.cardlist[i];
|
|
var card_deal = this.get_cardclass().GetDeal(o_card);
|
|
if (card_deal != -2){
|
|
this.get_cardclass().SetScore(o_card, 0);
|
|
}
|
|
}
|
|
|
|
//下面的代码是设置5、10、K分值的例子。类似功能需要在子游戏中重写该方法
|
|
// for (var i = 0; i < o_aset.cardlist.length; i++){
|
|
// var o_card = o_aset.cardlist[i];
|
|
// var card_deal = this.get_cardclass().GetDeal(o_card);
|
|
// if (card_deal != -2){
|
|
// var card_number = this.get_cardclass().GetNumber(o_card);
|
|
// switch (card_number){
|
|
// case 5:
|
|
// this.get_cardclass().SetScore(o_card, 5);
|
|
// break;
|
|
// case 10:
|
|
// this.get_cardclass().SetScore(o_card, 10);
|
|
// break;
|
|
// case 13:
|
|
// this.get_cardclass().SetScore(o_card, 10);
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
},
|
|
|
|
//===================== 发牌 =====================
|
|
DealCard: function(o_aset, o_desk){
|
|
//需要发牌的位置列表
|
|
var seatlist = this.get_dealseatlist(o_aset, o_desk);
|
|
//每人需要发多少张牌
|
|
var dealcount = this.get_dealcount(o_aset, o_desk);
|
|
//需要留几张底牌
|
|
var bottomcount = this.get_bottomcount(o_aset, o_desk);
|
|
//注意:dealcount * seatlist + bottomcount必须等于除掉不要的牌之后的牌的总数
|
|
|
|
//发牌数组
|
|
var tmplist = [];
|
|
for (var i = 0; i < seatlist.length; i++){
|
|
for (var j = 0; j < dealcount; j++){
|
|
tmplist.push(seatlist[i]);
|
|
}
|
|
}
|
|
for (var i = 0; i < bottomcount; i++){
|
|
tmplist.push(-1);
|
|
}
|
|
|
|
//随机发牌
|
|
for (var i = 0; i < o_aset.cardlist.length; i++){
|
|
var o_card = o_aset.cardlist[i];
|
|
var card_deal = this.get_cardclass().GetDeal(o_card);
|
|
if (card_deal != -2){
|
|
var idx = min_random(0, tmplist.length - 1);
|
|
this.get_cardclass().SetDeal(o_card, tmplist[idx]);
|
|
this.get_cardclass().SetStart(o_card, tmplist[idx]);
|
|
this.get_cardclass().SetPlay(o_card, -1);
|
|
this.get_cardclass().SetOver(o_card, tmplist[idx]);
|
|
//将发牌数组的最后一位移至该位置
|
|
if (idx < tmplist.length - 1) {
|
|
tmplist[idx] = tmplist[tmplist.length - 1];
|
|
};
|
|
//发牌数组长度减一
|
|
tmplist.length = tmplist.length - 1;
|
|
}
|
|
}
|
|
},
|
|
//需要发牌的位置列表
|
|
get_dealseatlist: function(o_aset, o_desk){
|
|
var seatlist = [];
|
|
for (var i = 0; i < o_desk.o_room.seatlist.length; i++){
|
|
if (o_desk.o_room.seatlist[i]){
|
|
if (o_desk.o_room.seatlist[i].gameinfo.isbet){
|
|
seatlist.push(i);
|
|
}
|
|
}
|
|
}
|
|
return seatlist;
|
|
},
|
|
//每人需要发多少张牌
|
|
get_dealcount: function(o_aset, o_desk){
|
|
return 0;
|
|
},
|
|
//需要留几张底牌
|
|
get_bottomcount: function(o_aset, o_desk){
|
|
return 0;
|
|
},
|
|
|
|
//==================== 拿底牌 ====================
|
|
PutBottomCard: function(o_aset, seat){
|
|
var bottomcardlist = this.GetBottomCards(o_aset);
|
|
for (var i = 0; i < bottomcardlist.length; i++) {
|
|
var o_card = bottomcardlist[i];
|
|
this.get_cardclass().SetStart(o_card, seat);
|
|
}
|
|
},
|
|
|
|
//===================== 埋牌 =====================
|
|
BuryCard: function(o_aset, seat, cardidlist){
|
|
/*参数:
|
|
seat:哪个位置要埋牌
|
|
cardidlist:要埋的牌的id
|
|
返回值:true表示执行成功,false表示执行失败。*/
|
|
if (this.canBuryCard(o_aset, seat, cardidlist)){
|
|
this.doBuryCard(o_aset, seat, cardidlist);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
},
|
|
get_burycardcount: function(){
|
|
return 8;
|
|
},
|
|
//检查是否可埋牌
|
|
canBuryCard: function(o_aset, seat, cardidlist){
|
|
//检查控制权
|
|
if (seat != o_aset.control){
|
|
return false;
|
|
}
|
|
//检查埋牌数量
|
|
if (cardidlist.length != this.get_burycardcount()){
|
|
return false;
|
|
}
|
|
//检查要埋的牌是否在玩家手上
|
|
var inhandcardids = this.GetCardIdsInhand(o_aset, seat);
|
|
return min_ary_include(inhandcardids, cardidlist);
|
|
},
|
|
//埋牌
|
|
doBuryCard: function(o_aset, seat, cardidlist){
|
|
var cardlist = this.CardIdsToCards(o_aset, cardidlist);
|
|
for (var i = 0; i < cardlist.length; i++) {
|
|
var o_card = cardlist[i];
|
|
this.get_cardclass().SetPlay(o_card, -2);
|
|
}
|
|
},
|
|
|
|
//===================== 出牌 =====================
|
|
PlayCard: function(o_aset, seat, cardidlist, mode){
|
|
/*参数:
|
|
seat:哪个位置要出牌
|
|
cardidlist:要出的牌的id
|
|
mode:出牌模式 0-需要跟随上一家出牌 1-需要跟随第一家出牌
|
|
返回值:true表示执行成功,false表示执行失败。*/
|
|
var can = this.canPlayCard(o_aset, seat, cardidlist, mode); //检查是否可出
|
|
if (can.result){ //可出
|
|
this.doPlayCard(o_aset, seat, cardidlist); //出下去
|
|
return true;
|
|
} else { //不可出
|
|
return false;
|
|
}
|
|
},
|
|
//检查是否可出牌
|
|
canPlayCard: function(o_aset, seat, cardidlist, mode){
|
|
var can = {}; //返回的结果
|
|
can.result = false; //是否可以出出去
|
|
can.cards = null; //牌(对象)
|
|
can.cardtype = null; //牌型
|
|
can.value = null; //大小
|
|
can.flower = null; //花色
|
|
|
|
//检查控制权
|
|
if (seat != o_aset.control){
|
|
can.result = false;
|
|
return can;
|
|
}
|
|
//检查要出的牌是否在玩家手上
|
|
var inhandcardids = this.GetCardIdsInhand(o_aset, seat);
|
|
if (!min_ary_include(inhandcardids, cardidlist)){
|
|
can.result = false;
|
|
return can;
|
|
}
|
|
|
|
return can;
|
|
},
|
|
//第一个出牌时分析选中的牌是否可以出出去(主要是分析牌型)
|
|
canPlayCard_first: function(o_aset, cardidlist){
|
|
var can = {}; //返回的结果
|
|
can.result = false; //是否可以出出去
|
|
can.cards = null; //牌(对象)
|
|
can.cardtype = null; //牌型
|
|
can.value = null; //大小
|
|
can.flower = null; //花色
|
|
|
|
|
|
return can;
|
|
},
|
|
//不是第一个出牌时分析选中的牌是否可以出出去(主要是分析牌型是否符合前面出牌的牌型)
|
|
canPlayCard_second: function(o_aset, cardidlist, mode){
|
|
var can = {}; //返回的结果
|
|
can.result = false; //是否可以出出去
|
|
can.cards = null; //牌(对象)
|
|
can.cardtype = null; //牌型
|
|
can.value = null; //大小
|
|
can.flower = null; //花色
|
|
|
|
return can;
|
|
},
|
|
//出牌
|
|
doPlayCard: function(o_aset, seat, cardidlist){
|
|
var cardlist = this.CardIdsToCards(o_aset, cardidlist);
|
|
for (var i = 0; i < cardlist.length; i++) {
|
|
var o_card = cardlist[i];
|
|
this.get_cardclass().SetPlay(o_card, o_aset.play);
|
|
this.get_cardclass().SetIndex(o_card, o_aset.index);
|
|
}
|
|
},
|
|
|
|
//=================== 可跟随的牌 ===================
|
|
CanFollowCard: function(o_aset, seat, mode){
|
|
//根据第一个人或上一个人出的牌,分析seat这个位置上的人必出的牌和可出的牌
|
|
|
|
},
|
|
|
|
//==================== 小局结算 =====================
|
|
CloseAccount: function(o_aset, o_desk){
|
|
|
|
},
|
|
|
|
//================ 获取各种情况的牌 ================
|
|
//获取开局时玩家发到手上的牌
|
|
GetDealCardsBySeat: function(o_aset, seat){
|
|
return this.GetCardsByDealstate(o_aset, seat);
|
|
},
|
|
GetDealCardIdsBySeat: function(o_aset, seat){
|
|
var cardlist = this.GetDealCardsBySeat(o_aset, seat);
|
|
return this.CardsToCardIds(cardlist);
|
|
},
|
|
//获取底牌
|
|
GetBottomCards: function(o_aset){
|
|
return this.GetCardsByDealstate(o_aset, -1);
|
|
},
|
|
GetBottomCardIds: function(o_aset){
|
|
var cardlist = this.GetBottomCards(o_aset);
|
|
return this.CardsToCardIds(cardlist);
|
|
},
|
|
//获取玩家当前手上有的牌
|
|
GetCardsInhand: function(o_aset, seat){
|
|
var cardlist = [];
|
|
for (var i = 0; i < o_aset.cardlist.length; i++){
|
|
var o_card = o_aset.cardlist[i];
|
|
var card_start = this.get_cardclass().GetStart(o_card);
|
|
if (card_start == seat){
|
|
var card_play = this.get_cardclass().GetPlay(o_card);
|
|
if (card_play == -1 || card_play == null){
|
|
cardlist.push(o_card);
|
|
}
|
|
}
|
|
}
|
|
return cardlist;
|
|
},
|
|
GetCardIdsInhand: function(o_aset, seat){
|
|
var cardlist = this.GetCardsInhand(o_aset, seat);
|
|
return this.CardsToCardIds(cardlist);
|
|
},
|
|
//获取埋牌 参数:seat谁埋的牌,可以不传,默认只有一个人会埋牌
|
|
GetBuryCards: function(o_aset, seat){
|
|
return this.GetCardsByPlaystate(o_aset, -2, seat);
|
|
},
|
|
GetBuryCardIds: function(o_aset, seat){
|
|
var cardlist = this.GetBuryCards(o_aset, seat);
|
|
return this.CardsToCardIds(cardlist);
|
|
},
|
|
//获取上一轮出牌
|
|
GetPriorPlayCard: function(o_aset, round){
|
|
|
|
},
|
|
//获取下一轮出牌
|
|
GetNextPlayCard: function(o_aset, round){
|
|
|
|
},
|
|
|
|
//================== 各种底层函数 ==================
|
|
//根据发牌状态获取牌列表
|
|
GetCardsByDealstate: function(o_aset, dealstate){
|
|
var cardlist = [];
|
|
for (var i = 0; i < o_aset.cardlist.length; i++){
|
|
var o_card = o_aset.cardlist[i];
|
|
var card_deal = this.get_cardclass().GetDeal(o_card);
|
|
if (card_deal == dealstate){
|
|
cardlist.push(o_card);
|
|
}
|
|
}
|
|
return cardlist;
|
|
},
|
|
//根据出牌状态获取牌列表
|
|
GetCardsByPlaystate: function(o_aset, playstate, seat){
|
|
var cardlist = [];
|
|
for (var i = 0; i < o_aset.cardlist.length; i++){
|
|
var o_card = o_aset.cardlist[i];
|
|
var card_play = this.get_cardclass().GetPlay(o_card);
|
|
if (card_play == playstate){
|
|
if (seat != null){
|
|
var card_start = this.get_cardclass().GetStart(o_card);
|
|
if (card_start == seat){
|
|
cardlist.push(o_card);
|
|
}
|
|
} else {
|
|
cardlist.push(o_card);
|
|
}
|
|
}
|
|
}
|
|
return cardlist;
|
|
},
|
|
//将牌对象列表转换成牌id列表
|
|
CardsToCardIds: function(cardlist){
|
|
var cardidlist = [];
|
|
for (var i = 0; i < cardlist.length; i++){
|
|
var o_card = cardlist[i];
|
|
var card_id = this.get_cardclass().GetId(o_card);
|
|
cardidlist.push(card_id);
|
|
}
|
|
return cardidlist;
|
|
},
|
|
//将牌id列表转换成牌对象列表
|
|
CardIdsToCards: function(o_aset, cardidlist){
|
|
var cardlist = [];
|
|
for (var i = 0; i < cardidlist.length; i++){
|
|
var o_card = o_aset.cardlist[cardidlist[i]];
|
|
cardlist.push(o_card);
|
|
}
|
|
return cardlist;
|
|
},
|
|
|
|
//新建小局类
|
|
NewClass: function(){
|
|
var cls = {};
|
|
cls.New = cls_aset2.New;
|
|
cls.declare = cls_aset2.declare;
|
|
cls.initcardlist = cls_aset2.initcardlist;
|
|
cls.get_cardcount = cls_aset2.get_cardcount;
|
|
cls.get_cardclass = cls_aset2.get_cardclass;
|
|
cls.deletecard = cls_aset2.deletecard;
|
|
cls.setcardscore = cls_aset2.setcardscore;
|
|
|
|
cls.DealCard = cls_aset2.DealCard;
|
|
cls.get_dealseatlist = cls_aset2.get_dealseatlist;
|
|
cls.get_dealcount = cls_aset2.get_dealcount;
|
|
cls.get_bottomcount = cls_aset2.get_bottomcount;
|
|
|
|
cls.PutBottomCard = cls_aset2.PutBottomCard;
|
|
|
|
cls.BuryCard = cls_aset2.BuryCard;
|
|
cls.get_burycardcount = cls_aset2.get_burycardcount;
|
|
cls.canBuryCard = cls_aset2.canBuryCard;
|
|
cls.doBuryCard = cls_aset2.doBuryCard;
|
|
|
|
cls.PlayCard = cls_aset2.PlayCard;
|
|
cls.canPlayCard = cls_aset2.canPlayCard;
|
|
cls.canPlayCard_first = cls_aset2.canPlayCard_first;
|
|
cls.canPlayCard_second = cls_aset2.canPlayCard_second;
|
|
cls.doPlayCard = cls_aset2.doPlayCard;
|
|
|
|
cls.CanFollowCard = cls_aset2.CanFollowCard;
|
|
|
|
cls.CloseAccount = cls_aset2.CloseAccount;
|
|
|
|
cls.GetDealCardsBySeat = cls_aset2.GetDealCardsBySeat;
|
|
cls.GetDealCardIdsBySeat = cls_aset2.GetDealCardIdsBySeat;
|
|
cls.GetBottomCards = cls_aset2.GetBottomCards;
|
|
cls.GetBottomCardIds = cls_aset2.GetBottomCardIds;
|
|
cls.GetCardsInhand = cls_aset2.GetCardsInhand;
|
|
cls.GetCardIdsInhand = cls_aset2.GetCardIdsInhand;
|
|
cls.GetBuryCards = cls_aset2.GetBuryCards;
|
|
cls.GetBuryCardIds = cls_aset2.GetBuryCardIds;
|
|
cls.GetPriorPlayCard = cls_aset2.GetPriorPlayCard;
|
|
cls.GetNextPlayCard = cls_aset2.GetNextPlayCard;
|
|
|
|
cls.GetCardsByDealstate = cls_aset2.GetCardsByDealstate;
|
|
cls.GetCardsByPlaystate = cls_aset2.GetCardsByPlaystate;
|
|
cls.CardsToCardIds = cls_aset2.CardsToCardIds;
|
|
cls.CardIdsToCards = cls_aset2.CardIdsToCards;
|
|
return cls;
|
|
}
|
|
}
|
|
|
|
|