目录结构调整
This commit is contained in:
77
codes/games/server/class/class.app.js
Normal file
77
codes/games/server/class/class.app.js
Normal file
@@ -0,0 +1,77 @@
|
||||
///////////////////////////////////////////////////
|
||||
//////////////cls_app: 应用基础类//////////////////
|
||||
///////////////////////////////////////////////////
|
||||
var cls_app = cls_app || {
|
||||
//构造函数
|
||||
new: function(_str_appname, _obj_packet) {
|
||||
/*
|
||||
参数说明:
|
||||
_str_appname 应用名称
|
||||
_obj_packet 所有应用的总包接口对象
|
||||
*/
|
||||
|
||||
//创建一个实例
|
||||
var app = {};
|
||||
|
||||
// ================= 实例的公有属性 ================= //
|
||||
//应用名称
|
||||
app.appname = _str_appname;
|
||||
//总包接口
|
||||
app.packet_face = _obj_packet;
|
||||
//给客户端发包函数
|
||||
app.SendPack = app.packet_face.SendPack;
|
||||
//给http客户端发包函数
|
||||
app.SendPack_Http = app.packet_face.SendPack_Http;
|
||||
//给tcp客户端发包函数
|
||||
app.SendPack_Tcp = app.packet_face.SendPack_Tcp;
|
||||
//将app添加到packet_face的应用列表中
|
||||
app.packet_face.applist.push(app);
|
||||
|
||||
//模块列表 [{"face":room_face,"facename":"room_face","routename":"room"}]
|
||||
app.modlist = [];
|
||||
|
||||
// ================= 实例的公有方法 ================= //
|
||||
//TCP客户端断开
|
||||
app.OnTcpDisConnected = function(_str_tcpid) {
|
||||
cls_app.OnTcpDisConnected(app, _str_tcpid);
|
||||
}
|
||||
|
||||
//处理数据包
|
||||
app.ReceivePack = function(_pack) {
|
||||
return cls_app.ReceivePack(app, _pack);
|
||||
}
|
||||
|
||||
return app;
|
||||
},
|
||||
|
||||
// ================= 所有实例的共享方法 ================= //
|
||||
//TCP客户端断开
|
||||
OnTcpDisConnected: function(_obj_app, _str_tcpid) {
|
||||
for (var i = 0; i < _obj_app.modlist.length; i++) {
|
||||
if (_obj_app.modlist[i].OnTcpDisConnected) {
|
||||
_obj_app.modlist[i].OnTcpDisConnected(_str_tcpid);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//处理数据包
|
||||
ReceivePack: function(_obj_app, _pack) {
|
||||
if (typeof(_pack) == "string") {
|
||||
_pack = JSON.parse(_pack); //转换json
|
||||
}
|
||||
//路由各个模块
|
||||
for (var i = 0; i < _obj_app.modlist.length; i++) {
|
||||
if (_pack.route == _obj_app.modlist[i].routename) {
|
||||
if (_obj_app.modlist[i].DoPack) {
|
||||
var repack = _obj_app.modlist[i].DoPack(_pack);
|
||||
//发包
|
||||
if (repack && _obj_app.SendPack) {
|
||||
_obj_app.SendPack(repack);
|
||||
}
|
||||
return repack;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
502
codes/games/server/class/class.aset2.js
Normal file
502
codes/games/server/class/class.aset2.js
Normal file
@@ -0,0 +1,502 @@
|
||||
/*================= 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;
|
||||
}
|
||||
}
|
||||
},
|
||||
DealCardByList: 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;
|
||||
}
|
||||
}
|
||||
742
codes/games/server/class/class.card2.js
Normal file
742
codes/games/server/class/class.card2.js
Normal file
@@ -0,0 +1,742 @@
|
||||
/*===================== cls_card2: 牌的基础类 ======================
|
||||
扑克牌的统一定义:
|
||||
1,单张牌的定义是一个长度为14的数组 [Id, Flower, Number, ArithF, ArithN, Score, Deal, Start, Play, Index, Over, Tag1, Tag2, Tag3]
|
||||
第一位:Id,牌的绝对id,即数组下标,从0开始计数。
|
||||
第二位:Flower,牌的物理花色,5:王 4:黑桃 3:红心 2:梅花 1:方块。
|
||||
第三位:Number,牌的物理大小,1:A 2:2 ... 9:9 10:10 11:J 12:Q 13:K 53:小王 54:大王。
|
||||
第四位:ArithF,牌的算法花色,区别于物理花色,用于牌型计算和比较牌的大小。
|
||||
要求是大于0的整数,不能等于0或小于0,默认等于物理花色。
|
||||
第五位:ArithN,牌的算法大小,区别于物理大小,用于牌型计算和比较牌的大小。
|
||||
要求是大于0的整数,不能等于0或小于0,默认等于物理大小。
|
||||
第六位:Score,牌的分值,如5、10、K。
|
||||
第七位:Deal,发牌状态。
|
||||
-2:规则去除的牌;
|
||||
-1:未发的牌(底牌);
|
||||
>=0:发牌发到谁手上,即座位号。
|
||||
第八位:Start,开局状态,开局时牌在谁手上,与座位编号对应。
|
||||
第九位:Play,出牌状态。
|
||||
-2:埋的牌;
|
||||
-1:未出的牌(手上的牌);
|
||||
>=0:牌是第几轮出出去的,从0开始计数。
|
||||
第十位:Index,本轮中的出牌顺序号,从0开始计数。
|
||||
第十一位:Over,牌局结束时被谁得到,与座位编号对应。
|
||||
第十二位:Tag1,扩展属性1。
|
||||
第十三位:Tag2,扩展属性2。
|
||||
第十四位:Tag3,扩展属性3。
|
||||
2,基础牌型的统一定义:
|
||||
所有基础牌型都由两个值表示:tong,同,表示一样的牌;shun,顺,表示连续的牌。
|
||||
单张:tong=1,shun=1
|
||||
对子:tong=2,shun=1
|
||||
两连对:tong=2,shun=2
|
||||
三连对:tong=2,shun=3
|
||||
三个:tong=3,shun=1
|
||||
飞机:tong=3,shun=2
|
||||
四个:tong=4,shun=1
|
||||
五连顺:tong=1,shun=5
|
||||
六连顺:tong=1,shun=6
|
||||
其他基础牌型以此类推
|
||||
|
||||
注意:
|
||||
1,此牌类是基础扑克牌类、通用扑克牌类;各子游戏可以直接使用,也可以继承此基础类后下编写自己的牌类。
|
||||
2,子游戏开发人员不能修改该文件。
|
||||
3,访问牌的属性时要求使用Get和Set方法,不能直接通过数组下标的形式访问。
|
||||
===================================================================*/
|
||||
var cls_card2 = {
|
||||
|
||||
//新建一张牌
|
||||
New: function(id){
|
||||
return this.declare(id);
|
||||
},
|
||||
//牌的数据定义
|
||||
declare: function(id){
|
||||
//id转物理花色
|
||||
var IdToFlower = function(cardid){
|
||||
var yu = cardid % 54;
|
||||
if (yu == 52 || yu == 53){
|
||||
return 5;
|
||||
}
|
||||
return parseInt(yu / 13) + 1;
|
||||
}
|
||||
//id转物理数值
|
||||
var IdToNumber = function(cardid){
|
||||
var yu = cardid % 54;
|
||||
if (yu == 52){
|
||||
return 53;
|
||||
}
|
||||
if (yu == 53){
|
||||
return 54;
|
||||
}
|
||||
return yu % 13 + 1;
|
||||
}
|
||||
|
||||
var o_card = [];
|
||||
o_card[0] = id;
|
||||
o_card[1] = IdToFlower(id);
|
||||
o_card[2] = IdToNumber(id);
|
||||
o_card[3] = o_card[1];
|
||||
o_card[4] = o_card[2];
|
||||
o_card[5] = null;
|
||||
o_card[6] = null;
|
||||
o_card[7] = null;
|
||||
o_card[8] = null;
|
||||
o_card[9] = null;
|
||||
o_card[10] = null;
|
||||
o_card[11] = null;
|
||||
o_card[12] = null;
|
||||
o_card[13] = null;
|
||||
return o_card;
|
||||
},
|
||||
//牌的id,整型,只读
|
||||
GetId: function(o_card){
|
||||
return o_card[0];
|
||||
},
|
||||
//牌的物理花色,整型,只读
|
||||
GetFlower: function(o_card){
|
||||
return o_card[1];
|
||||
},
|
||||
//牌的物理大小,整型,只读
|
||||
GetNumber: function(o_card){
|
||||
return o_card[2];
|
||||
},
|
||||
//牌的算法花色,整型
|
||||
GetArithF: function(o_card){
|
||||
return o_card[3];
|
||||
},
|
||||
SetArithF: function(o_card, value){
|
||||
o_card[3] = value;
|
||||
},
|
||||
//牌的算法大小,整型
|
||||
GetArithN: function(o_card){
|
||||
return o_card[4];
|
||||
},
|
||||
SetArithN: function(o_card, value){
|
||||
o_card[4] = value;
|
||||
},
|
||||
//牌的分值,整型
|
||||
GetScore: function(o_card){
|
||||
return o_card[5];
|
||||
},
|
||||
SetScore: function(o_card, value){
|
||||
o_card[5] = value;
|
||||
},
|
||||
//发牌状态,整型
|
||||
GetDeal: function(o_card){
|
||||
return o_card[6];
|
||||
},
|
||||
SetDeal: function(o_card, value){
|
||||
o_card[6] = value;
|
||||
},
|
||||
//开局状态,整型
|
||||
GetStart: function(o_card){
|
||||
return o_card[7];
|
||||
},
|
||||
SetStart: function(o_card, value){
|
||||
o_card[7] = value;
|
||||
},
|
||||
//出牌状态,整型
|
||||
GetPlay: function(o_card){
|
||||
return o_card[8];
|
||||
},
|
||||
SetPlay: function(o_card, value){
|
||||
o_card[8] = value;
|
||||
},
|
||||
//出牌顺序,整型
|
||||
GetIndex: function(o_card){
|
||||
return o_card[9];
|
||||
},
|
||||
SetIndex: function(o_card, value){
|
||||
o_card[9] = value;
|
||||
},
|
||||
//结束时被谁得到,整型
|
||||
GetOver: function(o_card){
|
||||
return o_card[10];
|
||||
},
|
||||
SetOver: function(o_card, value){
|
||||
o_card[10] = value;
|
||||
},
|
||||
//扩展属性
|
||||
GetTag1: function(o_card){
|
||||
return o_card[11];
|
||||
},
|
||||
SetTag1: function(o_card, value){
|
||||
o_card[11] = value;
|
||||
},
|
||||
GetTag2: function(o_card){
|
||||
return o_card[12];
|
||||
},
|
||||
SetTag2: function(o_card, value){
|
||||
o_card[12] = value;
|
||||
},
|
||||
GetTag3: function(o_card){
|
||||
return o_card[13];
|
||||
},
|
||||
SetTag3: function(o_card, value){
|
||||
o_card[13] = value;
|
||||
},
|
||||
/*
|
||||
以下提供几个针对牌数组的基础算法,这两个方法是基于牌的算法花色和算法大小实现的,各子游戏在调用前需要将牌的算法花色和算法大小先设置好。
|
||||
|
||||
设置算法花色的原则是:
|
||||
1,如果对花色没要求则需要将所有牌的算法花色统一。比如斗地主中的五连顺是任何花色都可以一起连顺子的,则需要将所有牌的算法花色全部设置成0,表示都是同一花色,然后在同一花色下取顺子。
|
||||
2,如果对花色有要求则需要根据实际情况区分算法花色。比如升级中的两连对是指同一花色下的两连对,则需要将算法花色设置成不同的值,表示不同算法花色之间是不能组成两连对的。
|
||||
|
||||
设置算法大小的原则是:算法大小即可表示是否连牌,也可表示牌的大小关系。
|
||||
1,设置算法大小时要求做到数字连续则表示是连牌。比如A的物理大小是1,K的物理大小是13,1和13是不连续的,此时需要将A的算法大小设置成14,将K的算法大小设置成13,14和13是连续的,表示A和K可以连牌。再比如王牌和A是不能作为连牌出现的,则需要将王的算法大小设置成16,将A的算法大小设置成14,16和14不是连续的,表示王和A不能连牌。
|
||||
2,设置算法大小时要求做到数字大小则表示是牌的大小。比如A的物理大小是1,K的物理大小是13,1比13小,但A比K大,此时需要将A的算法大小设置成14,将K的算法大小设置成13,14比13大,表示A比K大。再比如王牌比A大,则需要将王的算法大小设置成16,将A的算法大小设置成14,16大于14,表示王比A大。
|
||||
*/
|
||||
|
||||
//根据算法花色筛选牌
|
||||
FilterCardListByArithF: function(o_cardlist, ArithF){
|
||||
/*参数说明
|
||||
o_cardlist:需要进行筛选的牌数组
|
||||
ArithF:要筛选的算法花色,默认不筛选
|
||||
|
||||
返回值:筛选后的牌数组*/
|
||||
var result = [];
|
||||
for (var i = 0; i < o_cardlist.length; i++) {
|
||||
var o_card = o_cardlist[i];
|
||||
var card_ArithF = this.GetArithF(o_card);
|
||||
if (!ArithF || card_ArithF == ArithF) {
|
||||
result.push(o_cardlist[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
//根据算法大小筛选牌
|
||||
FilterCardListByArithN: function(o_cardlist, min_ArithN, max_ArithN){
|
||||
/*参数说明
|
||||
o_cardlist:需要进行筛选的牌数组
|
||||
min_ArithN:要筛选的算法大小最小值,>=,默认不限制
|
||||
max_ArithN:要筛选的算法大小最大值,<=,默认不限制
|
||||
返回值:筛选后的牌数组*/
|
||||
var result = [];
|
||||
for (var i = 0; i < o_cardlist.length; i++) {
|
||||
var o_card = o_cardlist[i];
|
||||
var card_ArithN = this.GetArithN(o_card);
|
||||
if ((!min_ArithN || card_ArithN >= min_ArithN) &&
|
||||
(!max_ArithN || card_ArithN <= max_ArithN)) {
|
||||
result.push(o_cardlist[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
//根据算法大小对牌数组进行排序(冒泡排序法)
|
||||
SortCardList: function(o_cardlist, options){
|
||||
/*参数说明
|
||||
o_cardlist: 需要进行排序的牌数组
|
||||
options : 排序选项,长度为2的数组,结构为[大小排序方向,花色排序方向]
|
||||
第一位: 算法大小排序方向,0-从小到大排序 1-从大到小排序,默认为0。
|
||||
第二位: 物理花色排序方向,算法大小相同时是否再按物理花色排序,默认为0。
|
||||
0-根据算法大小排序方向默认选择物理花色排序方向,
|
||||
options[0]=0时,物理花色默认按“方块->梅花->红心->黑桃”排序;
|
||||
options[0]=1时,物理花色默认按“黑桃->红心->梅花->方块”排序。
|
||||
1-不按物理花色排序,在o_cardlist中是什么顺序就什么顺序。
|
||||
2-按物理花色从小到大,方块->梅花->红心->黑桃
|
||||
3-按物理花色从大到小,黑桃->红心->梅花->方块
|
||||
返回值: 排序后的牌数组*/
|
||||
var ArithN_direct = 0; //算法大小排序方向
|
||||
var Flower_direct = 0; //物理花色排序方向
|
||||
if (options) {
|
||||
ArithN_direct = parseInt(options[0]);
|
||||
Flower_direct = parseInt(options[1]);
|
||||
}
|
||||
if (!Flower_direct){
|
||||
if (ArithN_direct) {
|
||||
//算法大小从大到小排序时,默认按“黑桃->红心->梅花->方块”排序
|
||||
Flower_direct = 3;
|
||||
} else {
|
||||
//算法大小从小到大排序时,默认按“方块->梅花->红心->黑桃”排序
|
||||
Flower_direct = 2;
|
||||
}
|
||||
}
|
||||
|
||||
//j与j+1互换位置
|
||||
var doChangej = function(){
|
||||
var tmp = o_cardlist[j];
|
||||
o_cardlist[j] = o_cardlist[j + 1];
|
||||
o_cardlist[j + 1] = tmp;
|
||||
}
|
||||
|
||||
for (var i = 0; i < o_cardlist.length; i++){
|
||||
for (var j = 0; j < o_cardlist.length - i - 1; j++){
|
||||
var ArithN_j = this.GetArithN(o_cardlist[j]);
|
||||
var ArithN_j1 = this.GetArithN(o_cardlist[j + 1]);
|
||||
if (ArithN_direct == 0 && ArithN_j > ArithN_j1){
|
||||
//从小到大排序
|
||||
doChangej();
|
||||
continue;
|
||||
}
|
||||
if (ArithN_direct == 1 && ArithN_j < ArithN_j1){
|
||||
//从大到小排序
|
||||
doChangej();
|
||||
continue;
|
||||
}
|
||||
if (ArithN_j == ArithN_j1){
|
||||
//算法大小相同时
|
||||
if (Flower_direct == 1){
|
||||
//不按物理花色排序
|
||||
continue;
|
||||
}
|
||||
var Flower_j = this.GetFlower(o_cardlist[j]);
|
||||
var Flower_j1 = this.GetFlower(o_cardlist[j + 1]);
|
||||
if (Flower_direct == 2 && Flower_j > Flower_j1){
|
||||
//按“方块->梅花->红心->黑桃”排序
|
||||
doChangej();
|
||||
continue;
|
||||
}
|
||||
if (Flower_direct == 3 && Flower_j < Flower_j1){
|
||||
//按“黑桃->红心->梅花->方块”排序
|
||||
doChangej();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return o_cardlist;
|
||||
},
|
||||
|
||||
//获取指定牌型(基础牌型)的各种组合(只组合,无排列)
|
||||
GetCardListByCardType: function(o_cardlist, cardtype, options){
|
||||
/*参数说明
|
||||
o_cardlist:在这些牌中获取指定牌型,必须是经过了从小到大排序后的牌数组。
|
||||
cardtype :目标牌型,长度为2的数组,结构为[同,顺]。
|
||||
例如单张为[1,1],对子为[2,1],五连顺为[1,5]。
|
||||
options :取牌选项,长度为4的数组,结构为[结果数量,取牌方向,拆牌标志,一次标志]
|
||||
第一位:结果数量,0-获取所有可能的结果,>0要取的结果数量,默认为0。
|
||||
比如,牌数组为[2,3,5,7]时,
|
||||
当options[0]=0时,则取单张的结果为2,3,5,7;
|
||||
当options[0]=1时,则取单张的结果为2;
|
||||
当options[0]=3时,则取单张的结果为2,3,5。
|
||||
第二位:取牌方向,0-从小到大取结果,1-从大到小取结果,默认为0。
|
||||
第三位:拆牌标志,0-不拆牌,1-拆牌,默认为0。
|
||||
比如,牌数组为[2,2,3,5,5,5,7],
|
||||
当options[2]=0时,则取单张时会不取对子的牌和三张的牌,即结果为3,7;
|
||||
当options[2]=1时,则取单张时会拆掉对子的牌和三张的牌,即结果为2,3,5,7。
|
||||
第四位:一次标志,0-相同大小的牌只取一次,1-取所有情况,默认为0。
|
||||
比如,牌数组为[红心2, 黑桃2, 方块3, 方块5, 红心5, 黑桃5, 方块7],
|
||||
当options[3]=0时,则取单张的结果为:红心2, 方块3, 方块5, 方块7;
|
||||
当options[3]=1时,则取单张时结果为:红心2, 黑桃2, 方块3, 方块5, 红心5, 黑桃5, 方块7。
|
||||
返回值:满足牌型要求的牌组合数组。
|
||||
格式如
|
||||
[
|
||||
[o_card, o_card, o_card, ...],
|
||||
[o_card, o_card, o_card, ...],
|
||||
[o_card, o_card, o_card, ...],
|
||||
...
|
||||
]
|
||||
注意:统一用第一张牌的算法大小值表示牌型大小,比如34567是顺子,56789也是顺子,用3表示34567顺子的大小,用5表示56789顺子的大小,5大于3,表示56789的顺子比34567的顺子大*/
|
||||
|
||||
var cardtype_tong = parseInt(cardtype[0]); //牌型-同
|
||||
var cardtype_shun = parseInt(cardtype[1]); //牌型-顺
|
||||
var options_count = 0; //结果数量
|
||||
var options_direct= 0; //取牌方向
|
||||
var options_split = 0; //拆牌标志
|
||||
var options_once = 0; //一次标志
|
||||
if (options){
|
||||
options_count = parseInt(options[0]);
|
||||
options_direct= parseInt(options[1]);
|
||||
options_split = parseInt(options[2]);
|
||||
options_once = parseInt(options[3]);
|
||||
}
|
||||
|
||||
//将牌按大小分组,即相同大小的牌归为一组。如,将[2,2,3,5,5,5,7]这样的牌数组转成[[2,2],[3],[5,5,5],[7]]
|
||||
var SameGroupList = [];
|
||||
var SameGroup = [];
|
||||
for (var i = 0; i < o_cardlist.length; i++){
|
||||
var o_card = o_cardlist[i];
|
||||
if (SameGroup.length == 0){
|
||||
SameGroup.push(o_card);
|
||||
} else {
|
||||
var card_ArithN = this.GetArithN(o_card);
|
||||
var SameGroup_ArithN = this.GetArithN(SameGroup[0]);
|
||||
if (card_ArithN == SameGroup_ArithN){
|
||||
SameGroup.push(o_card);
|
||||
} else {
|
||||
SameGroupList.push(SameGroup);
|
||||
SameGroup = [];
|
||||
SameGroup.push(o_card);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (SameGroup.length > 0){
|
||||
SameGroupList.push(SameGroup);
|
||||
}
|
||||
|
||||
//将牌分组按牌型的“同”获取各自的组合。例如,将[[2,2],[3],[5,5,5],[7]]这样的牌分组按“同”等于2转成[[[2,2]], [[方5,梅5],[方5,红5],[梅5,红5]]]
|
||||
var TongGroupList = [];
|
||||
for (var i = 0; i < SameGroupList.length; i++){
|
||||
if (SameGroupList[i].length < cardtype_tong){
|
||||
// TongGroupList.push([]);
|
||||
continue;
|
||||
}
|
||||
if (SameGroupList[i].length == cardtype_tong){
|
||||
TongGroupList.push([SameGroupList[i]]);
|
||||
continue;
|
||||
}
|
||||
if (SameGroupList[i].length > cardtype_tong){
|
||||
if (!options_split){ //不允许拆牌
|
||||
// TongGroupList.push([]);
|
||||
continue;
|
||||
}
|
||||
if (!options_once){ //同样大小的牌只取一次
|
||||
TongGroupList.push([SameGroupList[i].slice(0, cardtype_tong)]);
|
||||
} else {
|
||||
TongGroupList.push(min_CombineInAry(SameGroupList[i], cardtype_tong));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//返回结果
|
||||
var resultlist = [];
|
||||
var ShunGroup = [];
|
||||
//检查ShunGroup是否是连顺,如果是连顺则在ShunGroup取结果保存到resultlist中
|
||||
var check_return_ShunGroup = function(){
|
||||
var isShun = true;
|
||||
for (var j = 0; j < ShunGroup.length; j++){
|
||||
if (ShunGroup[j].length == 0) {
|
||||
isShun = false;
|
||||
break;
|
||||
}
|
||||
if (j > 0) {
|
||||
var j1_ArithN = this.GetArithN(ShunGroup[j-1][0][0]);
|
||||
var j_ArithN = this.GetArithN(ShunGroup[j][0][0]);
|
||||
//相减等于1表示是顺
|
||||
if (j_ArithN - j1_ArithN != 1){
|
||||
isShun = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isShun){
|
||||
return false;
|
||||
}
|
||||
var result = min_CombineByArys(ShunGroup);
|
||||
for (var j = 0; j < result.length; j++) {
|
||||
var temp = [];
|
||||
for (var k = 0; k < result[j].length; k++) {
|
||||
temp = temp.concat(result[j][k]);
|
||||
}
|
||||
resultlist.push(temp);
|
||||
|
||||
if (options_count && resultlist.length >= options_count) {
|
||||
//达到了要取的结果数量
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}.bind(this);
|
||||
|
||||
//按牌型的“顺”获取符合要求的结果
|
||||
if (!options_direct){
|
||||
//从小到大取结果
|
||||
for (var i = 0; i <= TongGroupList.length - cardtype_shun; i++){
|
||||
ShunGroup = TongGroupList.slice(i, i + cardtype_shun);
|
||||
if (check_return_ShunGroup()){
|
||||
return resultlist;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//从大到小取结果
|
||||
for (var i = TongGroupList.length - cardtype_shun; i >= 0; i--){
|
||||
ShunGroup = TongGroupList.slice(i, i + cardtype_shun);
|
||||
if (check_return_ShunGroup()){
|
||||
return resultlist;
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultlist;
|
||||
},
|
||||
GetCardListByCardTypeA: function(o_cardlist, cardtype, options, min_ArithN, max_ArithN){
|
||||
/*参数说明
|
||||
o_cardlist:同GetCardListByCardType中的参数说明。
|
||||
cardtype :同GetCardListByCardType中的参数说明。
|
||||
options :同GetCardListByCardType中的参数说明。
|
||||
min_ArithN:同FilterCardListByArithN中的参数说明。
|
||||
max_ArithN:同FilterCardListByArithN中的参数说明。
|
||||
返回值:同GetCardListByCardType中的参数说明。*/
|
||||
var cardlist = this.FilterCardListByArithN(o_cardlist, min_ArithN, max_ArithN);
|
||||
return this.GetCardListByCardType(cardlist, cardtype, options);
|
||||
},
|
||||
GetCardListByCardTypeB: function(o_cardlist, cardtype, options, ArithF, min_ArithN, max_ArithN){
|
||||
/*参数说明
|
||||
o_cardlist:可以是未排序的牌数组,该函数会实现排序。
|
||||
cardtype :同GetCardListByCardType中的参数说明。
|
||||
options :同GetCardListByCardType中的参数说明。
|
||||
ArithF :同FilterCardListByArithF中的参数说明。
|
||||
min_ArithN:同FilterCardListByArithN中的参数说明。
|
||||
max_ArithN:同FilterCardListByArithN中的参数说明。
|
||||
返回值:同GetCardListByCardType中的参数说明。*/
|
||||
var cardlist = this.FilterCardListByArithF(o_cardlist, ArithF);
|
||||
this.SortCardList(cardlist);
|
||||
cardlist = this.FilterCardListByArithN(cardlist, min_ArithN, max_ArithN);
|
||||
return this.GetCardListByCardType(cardlist, cardtype, options);
|
||||
},
|
||||
|
||||
//获取指定牌型(扩展牌型)的一种组合(只取一种组合)
|
||||
GetCardListByExtendCardTypeA: function(o_cardlist, cardtypelist){
|
||||
/*参数说明
|
||||
o_cardlist :同GetCardListByCardTypeA中的参数说明。
|
||||
cardtypelist:扩展牌型和取牌选项。
|
||||
结构为[
|
||||
[cardtype, options, min_ArithN, max_ArithN],
|
||||
[cardtype, options, min_ArithN, max_ArithN],
|
||||
[cardtype, options, min_ArithN, max_ArithN]
|
||||
]
|
||||
其中cardtype、options、min_ArithN、max_ArithN同GetCardListByCardTypeA中的参数说明。
|
||||
例如3带1,cardtypelist=[
|
||||
[[3,1], [1,x,x,x], min_ArithN, max_ArithN],
|
||||
[[1,1], [1,x,x,x], min_ArithN, max_ArithN]
|
||||
]
|
||||
3带2,cardtypelist=[
|
||||
[[3,1], [1,x,x,x], min_ArithN, max_ArithN],
|
||||
[[1,1], [1,x,x,x], min_ArithN, max_ArithN],
|
||||
[[1,1], [1,x,x,x], min_ArithN, max_ArithN]
|
||||
]
|
||||
3带1对,cardtypelist=[
|
||||
[[3,1], [1,x,x,x], min_ArithN, max_ArithN],
|
||||
[[2,1], [1,x,x,x], min_ArithN, max_ArithN]
|
||||
]
|
||||
注意:options中第一参数一定为1,表示只取一个结果,如果传的值不等于1,也会按等于1处理。
|
||||
|
||||
返回值:同GetCardListByCardTypeA中的参数说明。*/
|
||||
|
||||
var cardlist = o_cardlist;
|
||||
var result = [];
|
||||
for (var i = 0; i < cardtypelist.length; i++){
|
||||
var cardtype = cardtypelist[i][0];
|
||||
var options = cardtypelist[i][1];
|
||||
if (options[0] != 1){
|
||||
options[0] = 1;
|
||||
}
|
||||
var min_ArithN = cardtypelist[i][2];
|
||||
var max_ArithN = cardtypelist[i][3];
|
||||
var BaseCardGroup = this.GetCardListByCardTypeA(cardlist, cardtype, options, min_ArithN, max_ArithN);
|
||||
if (BaseCardGroup.length == 0){
|
||||
return [];
|
||||
}
|
||||
result = result.concat(BaseCardGroup[0]);
|
||||
cardlist = min_ary_deduct(cardlist, BaseCardGroup[0]);
|
||||
}
|
||||
return [result];
|
||||
},
|
||||
|
||||
//获取牌数组的最大牌型
|
||||
GetMaxCardTypeByCardList: function(o_cardlist, option){
|
||||
/*参数说明
|
||||
o_cardlist: 必须是经过了从小到大排序后的牌数组。
|
||||
option: 选项,默认为0
|
||||
0-返回"同"最多的最大牌型(如果"同"相同则取"顺"最多的,如果"顺"也相同则取"值"最大的)
|
||||
1-返回"顺"最多的最大牌型(如果"顺"相同则取"同"最多的,如果"同"也相同则取"值"最大的)
|
||||
返回值:结构为[cardtype, cardlist]。其中,
|
||||
cardtype为基础牌型,结构为[同,顺];
|
||||
cardlist为满足cardtype的牌数组,牌型相同时取最大值的牌。
|
||||
|
||||
例如,当option=0时,
|
||||
牌数组为[3,7,7,7,9,9,J,J,J,Q,Q], 返回值为[[3,1], [J,J,J]]
|
||||
牌数组为[3,7,7,7,8,8,8,9,9,J,J,J,Q,Q], 返回值为[[3,2], [7,7,7,8,8,8]]
|
||||
牌数组为[3,7,7,7,8,8,8,9,9,J,J,J,Q,Q,Q],返回值为[[3,2], [J,J,J,Q,Q,Q]]
|
||||
当option=1时,
|
||||
牌数组为[2,4,5,6,8,9,J,J,Q,Q,K], 返回值为[[1,3], [J,Q,K]]
|
||||
牌数组为[2,4,4,5,5,6,6,8,9,J,J,Q,Q,K], 返回值为[[2,3], [4,4,5,5,6,6]]
|
||||
牌数组为[2,4,4,5,5,6,6,8,9,J,J,Q,Q,K,K],返回值为[[3,2], [J,J,Q,Q,K,K]]*/
|
||||
var result = [];
|
||||
|
||||
//将o_cardlist按大小分组。
|
||||
//如,将[2,2,3,5,5,5,7]这样的牌数组转成[[2,2],[3],[5,5,5],[7]]
|
||||
var changeto_SameGroupList = function(){
|
||||
var SameGroupList = [];
|
||||
var SameGroup = [];
|
||||
for (var i = 0; i < o_cardlist.length; i++){
|
||||
var o_card = o_cardlist[i];
|
||||
if (SameGroup.length == 0){
|
||||
SameGroup.push(o_card);
|
||||
} else {
|
||||
var card_ArithN = this.GetArithN(o_card);
|
||||
var SameGroup_ArithN = this.GetArithN(SameGroup[0]);
|
||||
if (card_ArithN == SameGroup_ArithN){
|
||||
SameGroup.push(o_card);
|
||||
} else {
|
||||
SameGroupList.push(SameGroup);
|
||||
SameGroup = [];
|
||||
SameGroup.push(o_card);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (SameGroup.length > 0){
|
||||
SameGroupList.push(SameGroup);
|
||||
}
|
||||
return SameGroupList;
|
||||
}.bind(this);
|
||||
|
||||
var SameGroupList = changeto_SameGroupList();
|
||||
switch (option){
|
||||
case 0: //取"同"最多的牌型 [A,2,2,3,4,4,5,5,7,7,8,8,9,9,J,J,Q,Q,K,K]
|
||||
//检查ShunGroup是否是连顺
|
||||
var check_ShunGroup_isShun = function(){
|
||||
for (var j = 0; j < ShunGroup.length; j++){
|
||||
if (ShunGroup[j].length == 0) {
|
||||
return false;
|
||||
}
|
||||
if (j > 0) {
|
||||
var j1_ArithN = this.GetArithN(ShunGroup[j-1][0]);
|
||||
var j_ArithN = this.GetArithN(ShunGroup[j][0]);
|
||||
//相减等于1表示是顺
|
||||
if (j_ArithN - j1_ArithN != 1){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}.bind(this);
|
||||
|
||||
result[0] = [SameGroupList[0].length, 1];
|
||||
result[1] = SameGroupList[0];
|
||||
for (var i = 1; i < SameGroupList.length; i++) {
|
||||
if (SameGroupList[i].length > result[0][0]){
|
||||
result[0] = [SameGroupList[i].length, 1];
|
||||
result[1] = SameGroupList[i];
|
||||
} else if (SameGroupList[i].length == result[0][0]){
|
||||
var ArithN_i = this.GetArithN(SameGroupList[i][0]);
|
||||
var ArithN_r = this.GetArithN(result[1][result[1].length - 1]);
|
||||
if (ArithN_i - ArithN_r == 1){ //相减等于1表示是顺
|
||||
result[0][1] = result[0][1] + 1;
|
||||
result[1] = result[1].concat(SameGroupList[i]);
|
||||
} else {
|
||||
if (i + result[0][1] <= SameGroupList.length){
|
||||
var ShunGroup = SameGroupList.slice(i, i + result[0][1]);
|
||||
var isShun = check_ShunGroup_isShun();
|
||||
if (isShun){
|
||||
var check_Tong = true;
|
||||
for (var j = 1; j < ShunGroup.length; j++) {
|
||||
if (ShunGroup[j].length != result[0][0]){
|
||||
check_Tong = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (check_Tong) {
|
||||
result[1] = [];
|
||||
for (var j = 0; j < ShunGroup.length; j++) {
|
||||
result[1] = result[1].concat(ShunGroup[j]);
|
||||
}
|
||||
i = i + result[0][1] - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: //取"顺"最多的牌型 [A,3,4,6,8,8,9,9,J,J,J,Q,Q,Q]
|
||||
//将SameGroupList转成ShunGroupList
|
||||
//如,将[[2,2],[3],[5,5,5],[6,6],[7],[9,9]]转成[[[2,2],[3]], [[5,5,5],[6,6],[7]], [[9,9]]]
|
||||
var changeto_ShunGroupList = function(){
|
||||
var ShunGroupList = [];
|
||||
for (var i = 0; i < SameGroupList.length; i++) {
|
||||
var ArithN_i = this.GetArithN(SameGroupList[i][0]);
|
||||
var isFound = false;
|
||||
for (var j = 0; j < ShunGroupList.length; j++) {
|
||||
var ArithN_j = this.GetArithN(ShunGroupList[j][ShunGroupList[j].length - 1][0]);
|
||||
if (ArithN_i - ArithN_j == 1) {
|
||||
ShunGroupList[j].push(SameGroupList[i]);
|
||||
isFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isFound){
|
||||
ShunGroupList.push([SameGroupList[i]]);
|
||||
}
|
||||
}
|
||||
return ShunGroupList;
|
||||
}.bind(this);
|
||||
|
||||
//获取ShunGroup中最小的"同"数
|
||||
var get_ShunGroup_minTong = function(){
|
||||
var min_Tong = ShunGroup[0].length;
|
||||
for (var j = 1; j < ShunGroup.length; j++) {
|
||||
if (ShunGroup[j].length < min_Tong) {
|
||||
min_Tong = ShunGroup[j].length;
|
||||
}
|
||||
}
|
||||
return min_Tong;
|
||||
}.bind(this);
|
||||
|
||||
//根据ShunGroup的min_Tong设置result
|
||||
var set_result_byShunGroup_byMinTong = function(){
|
||||
result[0] = [min_Tong, ShunGroup.length];
|
||||
result[1] = [];
|
||||
for (var j = 0; j < ShunGroup.length; j++) {
|
||||
result[1] = result[1].concat(ShunGroup[j].slice(0, min_Tong));
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
var ShunGroupList = changeto_ShunGroupList();
|
||||
//在ShunGroupList中取最长的"顺"
|
||||
for (var i = 0; i < ShunGroupList.length; i++) {
|
||||
var ShunGroup = ShunGroupList[i];
|
||||
var min_Tong = get_ShunGroup_minTong();
|
||||
if (i == 0){
|
||||
set_result_byShunGroup_byMinTong();
|
||||
} else {
|
||||
if (ShunGroup.length > result[0][1]) {
|
||||
set_result_byShunGroup_byMinTong();
|
||||
} else if (ShunGroup.length == result[0][1]) {
|
||||
if (min_Tong >= result[0][0]){
|
||||
set_result_byShunGroup_byMinTong();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
GetMaxCardTypeByCardListA: function(o_cardlist){
|
||||
/*参数说明 o_cardlist:可以是未排序的牌数组,该函数会实现排序。*/
|
||||
this.SortCardList(o_cardlist);
|
||||
return this.GetMaxCardTypeByCardList(o_cardlist);
|
||||
},
|
||||
|
||||
//新建单张牌类
|
||||
NewClass: function(){
|
||||
var cls = {};
|
||||
cls.New = cls_card2.New;
|
||||
cls.declare = cls_card2.declare;
|
||||
cls.GetId = cls_card2.GetId;
|
||||
cls.GetFlower = cls_card2.GetFlower;
|
||||
cls.GetNumber = cls_card2.GetNumber;
|
||||
cls.GetArithF = cls_card2.GetArithF;
|
||||
cls.SetArithF = cls_card2.SetArithF;
|
||||
cls.GetArithN = cls_card2.GetArithN;
|
||||
cls.SetArithN = cls_card2.SetArithN;
|
||||
cls.GetScore = cls_card2.GetScore;
|
||||
cls.SetScore = cls_card2.SetScore;
|
||||
cls.GetDeal = cls_card2.GetDeal;
|
||||
cls.SetDeal = cls_card2.SetDeal;
|
||||
cls.GetStart = cls_card2.GetStart;
|
||||
cls.SetStart = cls_card2.SetStart;
|
||||
cls.GetPlay = cls_card2.GetPlay;
|
||||
cls.SetPlay = cls_card2.SetPlay;
|
||||
cls.GetIndex = cls_card2.GetIndex;
|
||||
cls.SetIndex = cls_card2.SetIndex;
|
||||
cls.GetOver = cls_card2.GetOver;
|
||||
cls.SetOver = cls_card2.SetOver;
|
||||
cls.GetTag1 = cls_card2.GetTag1;
|
||||
cls.SetTag1 = cls_card2.SetTag1;
|
||||
cls.GetTag2 = cls_card2.GetTag2;
|
||||
cls.SetTag2 = cls_card2.SetTag2;
|
||||
cls.GetTag3 = cls_card2.GetTag3;
|
||||
cls.SetTag3 = cls_card2.SetTag3;
|
||||
cls.FilterCardListByArithF = cls_card2.FilterCardListByArithF;
|
||||
cls.FilterCardListByArithN = cls_card2.FilterCardListByArithN;
|
||||
cls.SortCardList = cls_card2.SortCardList;
|
||||
cls.GetCardListByCardType = cls_card2.GetCardListByCardType;
|
||||
cls.GetCardListByCardTypeA = cls_card2.GetCardListByCardTypeA;
|
||||
cls.GetCardListByCardTypeB = cls_card2.GetCardListByCardTypeB;
|
||||
cls.GetCardListByExtendCardTypeA = cls_card2.GetCardListByExtendCardTypeA;
|
||||
cls.GetMaxCardTypeByCardList = cls_card2.GetMaxCardTypeByCardList;
|
||||
cls.GetMaxCardTypeByCardListA = cls_card2.GetMaxCardTypeByCardListA;
|
||||
return cls;
|
||||
}
|
||||
}
|
||||
225
codes/games/server/class/class.desk.js
Normal file
225
codes/games/server/class/class.desk.js
Normal file
@@ -0,0 +1,225 @@
|
||||
///////////////////////////////////////////////////
|
||||
/////////////// cls_desk: 牌桌基础类 //////////////
|
||||
///////////////////////////////////////////////////
|
||||
var cls_desk = cls_desk || {
|
||||
|
||||
//创建单个牌桌实例
|
||||
new: function(o_room){
|
||||
/*
|
||||
参数说明:
|
||||
o_room 牌桌对应的房间对象
|
||||
|
||||
补充说明:
|
||||
1,房间对象由框架负责创建和释放。
|
||||
2,房间对象管理的是人,解决诸如谁在房间里,谁在哪个位置上,谁进了房间,谁离开了房间等问题。
|
||||
3,牌桌对象由游戏负责创建,牌桌对象会随着房间的释放而释放,子游戏不用管牌桌的释放。
|
||||
4,牌桌对象管理的是牌,解决诸如哪个位置上发了什么牌,出了什么牌等问题。
|
||||
5,此牌桌类是基础牌桌类,各子游戏需要在继承此基础类的情况下编写自己的牌桌类。
|
||||
*/
|
||||
var desk = {};
|
||||
|
||||
//牌桌与房间互挂
|
||||
o_room.o_desk = desk; //可通过房间对象的o_desk属性访问牌桌对象
|
||||
desk.o_room = o_room; //可通过牌桌对象的o_desk属性访问房间对象
|
||||
|
||||
//数据
|
||||
desk.data = {}; //要求data必须是纯数据,不能在data下面写方法、函数、定时器
|
||||
//定时器
|
||||
desk.timer = {}; //可根据实际需要在desk.timer下定义多个定时器
|
||||
//收发包
|
||||
desk.pack = []; //调试状态下记录牌桌的收包发包情况
|
||||
//流程方法
|
||||
desk.flow = {};
|
||||
//算法方法
|
||||
desk.arith = {};
|
||||
|
||||
//////////在下面定义实例的属性
|
||||
//数据-小局列表
|
||||
desk.data.asetlist = []; //每开一小局则往该数组中添加一个aset小局对象,[aset, aset, aset, ...], [{}, {}, {}, ...], [[], [], [], ...],数组长度即可表示当前是第几小局,数组最后一个小局对象即是当前小局
|
||||
|
||||
|
||||
/////////在下面定义实例的方法,要求实例的方法必须调用类的方法,以节省内存资源,要求实例的方法名要与类的方法名保持一致
|
||||
//记录游戏的收包情况(不包括框架的收包),要求前端向服务器发包时根据配置参数的设置情况将前端内存数据一起发上来,数据放在pack.data.d里面,服务器收到包后必须调用该方法
|
||||
desk.flow.save_receivepack = function(pack, seat, playerid){
|
||||
return cls_desk.save_receivepack(desk, pack, seat, playerid);
|
||||
}
|
||||
//记录游戏的发包情况(不包括框架的发包),要求服务器向前端发包后一定要调用该方法
|
||||
desk.flow.save_sendpack = function(pack, seat, playerid){
|
||||
return cls_desk.save_sendpack(desk, pack, seat, playerid);
|
||||
}
|
||||
//将当前小局的收发包情况保存成TXT
|
||||
desk.flow.save_pack_curraset = function(callback_succ, callback_fail){
|
||||
return cls_desk.save_pack_curraset(desk, callback_succ, callback_fail);
|
||||
}
|
||||
//输出日志
|
||||
desk.flow.save_log = function(dir, file, log){
|
||||
return cls_desk.save_log(desk, dir, file, log);
|
||||
}
|
||||
//清日志
|
||||
desk.flow.clear_log = function(dir, file){
|
||||
return cls_desk.clear_log(desk, dir, file);
|
||||
}
|
||||
//获取当前小局对象
|
||||
desk.flow.get_curraset = function(){
|
||||
return cls_desk.get_curraset(desk); //必须调用类的方法,且需要将实例对象作为参数传入类方法,这里只能写一句代码
|
||||
}
|
||||
//获取当前小局局数
|
||||
desk.flow.get_currasetnum = function(){
|
||||
return cls_desk.get_currasetnum(desk); //必须调用类的方法,且需要将实例对象作为参数传入类方法,这里只能写一句代码
|
||||
}
|
||||
|
||||
return desk;
|
||||
},
|
||||
|
||||
////////////以下都是类的方法,要求所有的逻辑算法全部都要用类方法来实现
|
||||
//记录收包情况
|
||||
save_receivepack: function(o_desk, pack, seat, playerid){
|
||||
try{
|
||||
if (o_desk.o_room.o_game.method.isdebugger()){ //如果是调试状态下,则记录收包情况
|
||||
var o_save = {};
|
||||
o_save.time = min_now(); //时间
|
||||
o_save.type = 0; //收包
|
||||
o_save.seat = seat; //位置
|
||||
o_save.playerid = playerid; //玩家id
|
||||
o_save.data = {};
|
||||
//前端内存数据
|
||||
o_save.data.client = pack.data.d;
|
||||
//服务器房间内存数据
|
||||
o_save.data.room = o_desk.o_room.method.get_roominfo();
|
||||
//服务器牌桌内存数据
|
||||
o_save.data.desk = min_copyjson(o_desk.data);
|
||||
for (var i = 0; i < o_save.data.desk.asetlist.length; i++) {
|
||||
if (i < o_save.data.desk.asetlist.length - 1){
|
||||
o_save.data.desk.asetlist[i] = null;
|
||||
};
|
||||
};
|
||||
delete pack.data.d;
|
||||
//接收到的数据包
|
||||
o_save.pack = pack;
|
||||
o_desk.pack.push(o_save);
|
||||
}
|
||||
}catch(e){};
|
||||
},
|
||||
//记录发包情况
|
||||
save_sendpack: function(o_desk, pack, seat, playerid){
|
||||
try{
|
||||
if (o_desk.o_room.o_game.method.isdebugger()){ //如果是调试状态下,则记录发包情况
|
||||
var o_save = {};
|
||||
o_save.time = min_now(); //时间
|
||||
o_save.type = 1; //发包
|
||||
o_save.seat = seat; //位置
|
||||
o_save.playerid = playerid; //玩家id
|
||||
o_save.data = {};
|
||||
//服务器房间内存数据
|
||||
o_save.data.room = o_desk.o_room.method.get_roominfo();
|
||||
//服务器牌桌内存数据
|
||||
o_save.data.desk = min_copyjson(o_desk.data);
|
||||
for (var i = 0; i < o_save.data.desk.asetlist.length; i++) {
|
||||
if (i < o_save.data.desk.asetlist.length - 1){
|
||||
o_save.data.desk.asetlist[i] = null;
|
||||
};
|
||||
};
|
||||
//发送的数据包
|
||||
o_save.pack = pack;
|
||||
o_desk.pack.push(o_save);
|
||||
}
|
||||
}catch(e){};
|
||||
},
|
||||
//将当前小局的收发包情况保存成TXT
|
||||
save_pack_curraset: function(o_desk, callback_succ, callback_fail){
|
||||
try{
|
||||
if (o_desk.o_room.o_game.method.isdebugger()){
|
||||
for (var i = 0; i < o_desk.pack.length; i++) {
|
||||
o_desk.pack[i].saveflag = 1;
|
||||
};
|
||||
|
||||
var o_makewartime = new Date(o_desk.o_room.makewartime);
|
||||
var yyyy = o_makewartime.getFullYear();
|
||||
var mm = o_makewartime.getMonth() + 1;
|
||||
var dd = o_makewartime.getDate();
|
||||
var dir = yyyy + "-" + mm + "-" + dd;
|
||||
var file = o_desk.o_room.o_game.o_agent.agentid + "-" + o_desk.o_room.o_game.gameid + "-" + o_desk.o_room.roomcode + "-" + o_desk.flow.get_currasetnum() + ".txt";
|
||||
var data = JSON.stringify(o_desk.pack);
|
||||
|
||||
var cfg = {};
|
||||
// cfg.url = "http://120.26.52.206:8080/debug.php";
|
||||
cfg.url = "http://10.117.216.66:8080/debug.php";
|
||||
cfg.data = "dir=" + dir + "&file=" + file + "&data=" + data;
|
||||
cfg.type = "POST";
|
||||
cfg.success = function(str){
|
||||
for (var i = 0; i < o_desk.pack.length; i++) {
|
||||
if (o_desk.pack[i].saveflag){
|
||||
o_desk.pack.splice(i, 1);
|
||||
i--;
|
||||
};
|
||||
};
|
||||
if(callback_succ){
|
||||
callback_succ();
|
||||
};
|
||||
};
|
||||
cfg.error = function(str){
|
||||
for (var i = 0; i < o_desk.pack.length; i++) {
|
||||
if (o_desk.pack[i].saveflag){
|
||||
delete o_desk.pack[i].saveflag;
|
||||
};
|
||||
};
|
||||
console.log(min_now() + " 保存牌局调试数据失败1");
|
||||
console.log("dir=" + dir);
|
||||
console.log("file=" + file);
|
||||
console.log(str);
|
||||
if(callback_fail){
|
||||
callback_fail();
|
||||
};
|
||||
};
|
||||
min_http(cfg);
|
||||
}
|
||||
}catch(e){
|
||||
console.log(min_now() + " 保存牌局调试数据失败2");
|
||||
console.log("dir=" + dir);
|
||||
console.log("file=" + file);
|
||||
console.log(e);
|
||||
};
|
||||
},
|
||||
//输出日志
|
||||
save_log: function(o_desk, dir, file, log){
|
||||
try{
|
||||
var cfg = {};
|
||||
// cfg.url = "http://120.26.52.206:8080/savelog.php";
|
||||
cfg.url = "http://10.117.216.66:8080/savelog.php";
|
||||
cfg.data = "dir=" + dir + "&file=" + file + "&data=" + log;
|
||||
cfg.type = "POST";
|
||||
cfg.success = function(str){};
|
||||
cfg.error = function(str){
|
||||
console.log(min_now() + " 输出日志失败:" + dir + "/" + file);
|
||||
console.log(str);
|
||||
};
|
||||
min_http(cfg);
|
||||
}catch(e){}
|
||||
},
|
||||
//清日志
|
||||
clear_log: function(o_desk, dir, file){
|
||||
try{
|
||||
var cfg = {};
|
||||
// cfg.url = "http://120.26.52.206:8080/clearlog.php";
|
||||
cfg.url = "http://10.117.216.66:8080/clearlog.php";
|
||||
cfg.data = "dir=" + dir + "&file=" + file;
|
||||
cfg.type = "POST";
|
||||
cfg.success = function(str){};
|
||||
cfg.error = function(str){
|
||||
console.log(min_now() + " 清空日志失败:" + dir + "/" + file);
|
||||
console.log(str);
|
||||
};
|
||||
min_http(cfg);
|
||||
}catch(e){}
|
||||
},
|
||||
//获取当前小局对象
|
||||
get_curraset: function(o_desk){
|
||||
return o_desk.data.asetlist[desk.data.asetlist.length - 1];
|
||||
},
|
||||
//获取当前小局局数
|
||||
get_currasetnum: function(o_desk){
|
||||
return o_desk.data.asetlist.length;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
287
codes/games/server/class/class.desk2.js
Normal file
287
codes/games/server/class/class.desk2.js
Normal file
@@ -0,0 +1,287 @@
|
||||
/*================= cls_desk2: 牌桌基础类 =================
|
||||
说明:
|
||||
1,房间对象由框架负责创建和释放。
|
||||
2,房间对象管理的是人,解决诸如谁在房间里,谁在哪个位置上,谁进了房间,谁离开了房间等问题。
|
||||
3,牌桌对象由游戏负责创建,牌桌对象会随着房间的释放而释放,子游戏不用管牌桌的释放。
|
||||
4,牌桌对象管理的是牌,解决诸如哪个位置上发了什么牌,出了什么牌等问题。
|
||||
|
||||
注意:
|
||||
1,此牌桌类是基础类;各子游戏需要在继承此基础类的情况下编写自己的牌桌类。
|
||||
2,子游戏开发人员不能修改该文件。
|
||||
3,子游戏只能调用实例方法,不能直接调用类方法。
|
||||
=========================================================*/
|
||||
var cls_desk2 = {
|
||||
|
||||
//debug服务器地址
|
||||
// debugserver: "120.26.52.206:8080", //外网地址,开发人员本地调试时使用该地址
|
||||
debugserver: "10.117.216.66:8080", //内网地址,正式服务器上使用该地址
|
||||
|
||||
//创建实例
|
||||
new: function(object_room){//参数说明:object_room 牌桌对应的房间对象
|
||||
var object = {};
|
||||
|
||||
//牌桌与房间互挂
|
||||
object_room.o_desk = object; //可通过房间对象的o_desk属性访问牌桌对象
|
||||
object.o_room = object_room; //可通过牌桌对象的o_desk属性访问房间对象
|
||||
|
||||
//=============== 在下面定义实例的属性 ===============
|
||||
//数据
|
||||
object.data = {}; //要求data必须是纯数据,不能在data下面写方法、函数、定时器
|
||||
//定时器
|
||||
object.timer = {}; //可根据实际需要在desk.timer下定义多个定时器
|
||||
//收发包
|
||||
object.pack = []; //调试状态下记录牌桌的收包发包情况
|
||||
//bug调试方法
|
||||
object.debug = {};
|
||||
//游戏内容方法
|
||||
object.method = {};
|
||||
|
||||
//小局列表。每开一小局则往该数组中添加一个aset小局对象,格式如[aset, aset, aset, ...],数组长度即可表示当前是第几小局,数组最后一个小局对象即是当前小局
|
||||
object.data.asetlist = [];
|
||||
|
||||
|
||||
//=============== 在下面定义实例的方法 ===============
|
||||
/*1,要求实例的方法必须调用类的方法,以节省内存资源。
|
||||
2,要求实例的方法必须只用一句代码调用类的方法,并将实例对象作为第一个参数传给类方法。
|
||||
3,要求实例的方法名要与类的方法名保持一致。*/
|
||||
|
||||
//====================== bug调试 =====================
|
||||
//记录游戏的收包情况(不包括框架的收包),要求前端向服务器发包时根据isdebugger参数的配置情况将前端的内存数据一起发上来,数据放在pack.data.d里面,服务器收到前端发来的包后必须调用该方法
|
||||
//参数说明:pack前端发来的包,seat哪个位置发来的包,哪个玩家发来的包
|
||||
object.debug.save_receivepack = function(pack, seat, playerid){
|
||||
return cls_desk2.save_receivepack(object, pack, seat, playerid);
|
||||
}
|
||||
//记录游戏的发包情况(不包括框架的发包),要求服务器向前端发包后一定要调用该方法
|
||||
/*参数说明:pack向前端发的包,seat给哪个位置发包,给哪个玩家发包。
|
||||
如果是向所有玩家发包则seat传-1,playerid传null,
|
||||
如果是向多个玩家发包则seat传位置数组,playerid传玩家id数组*/
|
||||
object.debug.save_sendpack = function(pack, seat, playerid){
|
||||
return cls_desk2.save_sendpack(object, pack, seat, playerid);
|
||||
}
|
||||
//将当前小局的收发包情况保存到debug服务器上,要求小局结算后,下一个小局新建前调用此方法
|
||||
//参数说明:callback_succ保存成功的回调函数,callback_fail保存失败的回调函数
|
||||
object.debug.save_pack_curraset = function(callback_succ, callback_fail){
|
||||
return cls_desk2.save_pack_curraset(object, callback_succ, callback_fail);
|
||||
}
|
||||
//输出调试日志到debug服务器上,输入后可在debug服务器上或浏览器中查看日志内容
|
||||
//参数说明:dir日志目录名,file日志文件名,log要输出的日志内容
|
||||
object.debug.save_log = function(dir, file, log){
|
||||
return cls_desk2.save_log(object, dir, file, log);
|
||||
}
|
||||
//清空debug服务器上的调试日志
|
||||
//参数说明:dir日志目录名,file日志文件名
|
||||
object.debug.clear_log = function(dir, file){
|
||||
return cls_desk2.clear_log(object, dir, file);
|
||||
}
|
||||
|
||||
|
||||
//====================== 游戏内容 =====================
|
||||
//对应的小局类
|
||||
object.method.AsetClass = function(){
|
||||
return cls_aset2;
|
||||
}
|
||||
//新建一小局
|
||||
object.method.NewAset = function(){
|
||||
return cls_desk2.NewAset(object);
|
||||
}
|
||||
//大局结算
|
||||
object.method.CloseAccount = function(){
|
||||
return cls_desk2.CloseAccount(object);
|
||||
}
|
||||
|
||||
//获取当前小局对象
|
||||
object.method.CurrAset = function(){
|
||||
return cls_desk2.CurrAset(object);
|
||||
}
|
||||
//获取当前小局是第几小局
|
||||
object.method.CurrAsetNum = function(){
|
||||
return cls_desk2.CurrAsetNum(object);
|
||||
}
|
||||
//获取下一个有人的位置
|
||||
object.method.GetNextSeat = function(seat){
|
||||
return cls_desk2.GetNextSeat(object, seat);
|
||||
}
|
||||
|
||||
return object;
|
||||
},
|
||||
|
||||
//================ 在下面定义类的方法 ================
|
||||
//===================== bug调试 ======================
|
||||
//记录服务器收包情况
|
||||
save_receivepack: function(o_desk, pack, seat, playerid){
|
||||
try{
|
||||
if (o_desk.o_room.o_game.method.isdebugger()){ //如果是调试状态下,则记录收包情况
|
||||
var o_save = {};
|
||||
o_save.time = min_now(); //记录的时间
|
||||
o_save.type = 0; //服务器收到前端的发包
|
||||
o_save.seat = seat; //哪个位置发来的包
|
||||
o_save.playerid = playerid; //哪个玩家发来的包
|
||||
o_save.data = {};
|
||||
//前端内存数据
|
||||
o_save.data.client = pack.data.d;
|
||||
//服务器房间内存数据
|
||||
o_save.data.room = o_desk.o_room.method.get_roominfo();
|
||||
//服务器牌桌内存数据
|
||||
o_save.data.desk = min_copyjson(o_desk.data);
|
||||
for (var i = 0; i < o_save.data.desk.asetlist.length; i++) {
|
||||
if (i < o_save.data.desk.asetlist.length - 1){
|
||||
o_save.data.desk.asetlist[i] = null;
|
||||
};
|
||||
};
|
||||
delete pack.data.d;
|
||||
//接收到的数据包
|
||||
o_save.pack = pack;
|
||||
o_desk.pack.push(o_save);
|
||||
}
|
||||
}catch(e){};
|
||||
},
|
||||
//记录服务器发包情况
|
||||
save_sendpack: function(o_desk, pack, seat, playerid){
|
||||
try{
|
||||
if (o_desk.o_room.o_game.method.isdebugger()){ //如果是调试状态下,则记录发包情况
|
||||
var o_save = {};
|
||||
o_save.time = min_now(); //记录的时间
|
||||
o_save.type = 1; //服务器向前端发包
|
||||
o_save.seat = seat; //服务器向哪个位置发包
|
||||
o_save.playerid = playerid; //服务器向哪个玩家发包
|
||||
o_save.data = {};
|
||||
//服务器房间内存数据
|
||||
o_save.data.room = o_desk.o_room.method.get_roominfo();
|
||||
//服务器牌桌内存数据
|
||||
o_save.data.desk = min_copyjson(o_desk.data);
|
||||
for (var i = 0; i < o_save.data.desk.asetlist.length; i++) {
|
||||
if (i < o_save.data.desk.asetlist.length - 1){
|
||||
o_save.data.desk.asetlist[i] = null;
|
||||
};
|
||||
};
|
||||
//发送的数据包
|
||||
o_save.pack = pack;
|
||||
o_desk.pack.push(o_save);
|
||||
}
|
||||
}catch(e){};
|
||||
},
|
||||
//将当前小局的收发包情况保存到debug服务器上
|
||||
save_pack_curraset: function(o_desk, callback_succ, callback_fail){
|
||||
try{
|
||||
if (o_desk.o_room.o_game.method.isdebugger()){
|
||||
for (var i = 0; i < o_desk.pack.length; i++) {
|
||||
o_desk.pack[i].saveflag = 1;
|
||||
};
|
||||
|
||||
var o_makewartime = new Date(o_desk.o_room.makewartime);
|
||||
var yyyy = o_makewartime.getFullYear();
|
||||
var mm = o_makewartime.getMonth() + 1;
|
||||
var dd = o_makewartime.getDate();
|
||||
var dir = yyyy + "-" + mm + "-" + dd;
|
||||
var file = o_desk.o_room.o_game.o_agent.agentid + "-" + o_desk.o_room.o_game.gameid + "-" + o_desk.o_room.roomcode + "-" + o_desk.method.CurrAsetNum() + ".txt";
|
||||
var data = JSON.stringify(o_desk.pack);
|
||||
|
||||
var cfg = {};
|
||||
cfg.url = "http://" + cls_desk2.debugserver + "/debug.php";
|
||||
cfg.data = "dir=" + dir + "&file=" + file + "&data=" + data;
|
||||
cfg.type = "POST";
|
||||
cfg.success = function(str){
|
||||
for (var i = 0; i < o_desk.pack.length; i++) {
|
||||
if (o_desk.pack[i].saveflag){
|
||||
o_desk.pack.splice(i, 1);
|
||||
i--;
|
||||
};
|
||||
};
|
||||
if(callback_succ){
|
||||
callback_succ();
|
||||
};
|
||||
};
|
||||
cfg.error = function(str){
|
||||
for (var i = 0; i < o_desk.pack.length; i++) {
|
||||
if (o_desk.pack[i].saveflag){
|
||||
delete o_desk.pack[i].saveflag;
|
||||
};
|
||||
};
|
||||
console.log(min_now() + " 保存牌局调试数据失败1");
|
||||
console.log("dir=" + dir);
|
||||
console.log("file=" + file);
|
||||
console.log(str);
|
||||
if(callback_fail){
|
||||
callback_fail();
|
||||
};
|
||||
};
|
||||
min_http(cfg);
|
||||
}
|
||||
}catch(e){
|
||||
console.log(min_now() + " 保存牌局调试数据失败2");
|
||||
console.log("dir=" + dir);
|
||||
console.log("file=" + file);
|
||||
console.log(e);
|
||||
};
|
||||
},
|
||||
//输出调试日志到debug服务器上
|
||||
save_log: function(o_desk, dir, file, log){
|
||||
try{
|
||||
if (typeof(log) == "object"){
|
||||
log = JSON.stringify(log);
|
||||
}
|
||||
var cfg = {};
|
||||
cfg.url = "http://" + cls_desk2.debugserver + "/savelog.php";
|
||||
cfg.data = "dir=" + dir + "&file=" + file + "&data=" + log;
|
||||
cfg.type = "POST";
|
||||
cfg.success = function(str){};
|
||||
cfg.error = function(str){
|
||||
console.log(min_now() + " 输出调试日志失败");
|
||||
console.log(str);
|
||||
};
|
||||
min_http(cfg);
|
||||
}catch(e){}
|
||||
},
|
||||
//清空debug服务器上的调试日志
|
||||
clear_log: function(o_desk, dir, file){
|
||||
try{
|
||||
var cfg = {};
|
||||
cfg.url = "http://" + cls_desk2.debugserver + "/clearlog.php";
|
||||
cfg.data = "dir=" + dir + "&file=" + file;
|
||||
cfg.type = "POST";
|
||||
cfg.success = function(str){};
|
||||
cfg.error = function(str){
|
||||
console.log(min_now() + " 清空调试日志失败");
|
||||
console.log(str);
|
||||
};
|
||||
min_http(cfg);
|
||||
}catch(e){}
|
||||
},
|
||||
|
||||
//===================== 游戏内容 ======================
|
||||
//新建一小局
|
||||
NewAset: function(o_desk){
|
||||
var o_aset = o_desk.method.AsetClass().New();
|
||||
o_desk.data.asetlist.push(o_aset);
|
||||
return o_aset;
|
||||
},
|
||||
//获取当前小局对象
|
||||
CurrAset: function(o_desk){
|
||||
return o_desk.data.asetlist[o_desk.data.asetlist.length - 1];
|
||||
},
|
||||
//获取当前小局局数
|
||||
CurrAsetNum: function(o_desk){
|
||||
return o_desk.data.asetlist.length;
|
||||
},
|
||||
//获取下一个有人的位置
|
||||
GetNextSeat: function(o_desk, seat){
|
||||
if (seat < 0){
|
||||
return -1;
|
||||
}
|
||||
var seatcount = o_desk.o_room.o_game.seatcount;
|
||||
if (seat >= seatcount){
|
||||
return -1;
|
||||
}
|
||||
var i = seat;
|
||||
var o_nextplayer = null;
|
||||
while (!o_nextplayer){
|
||||
i = (i + 1) % seatcount;
|
||||
o_nextplayer = o_desk.o_room.seatlist[i];
|
||||
}
|
||||
return i;
|
||||
},
|
||||
//大局结算
|
||||
CloseAccount: function(o_desk){
|
||||
|
||||
}
|
||||
}
|
||||
135
codes/games/server/class/class.flow2.js
Normal file
135
codes/games/server/class/class.flow2.js
Normal file
@@ -0,0 +1,135 @@
|
||||
/*=============== cls_flowMgr2: 流程管理类 ===============
|
||||
注意:
|
||||
1,子游戏开发人员不能修改该文件。
|
||||
=========================================================*/
|
||||
var cls_flowMgr2 = {
|
||||
//创建实例
|
||||
new: function(){
|
||||
object = {};
|
||||
//流程库
|
||||
object.lib = [];
|
||||
//流程配置
|
||||
object.steplist = [];
|
||||
//当前流程,即steplist的数组下标
|
||||
object.idx = -1;
|
||||
|
||||
object.method = {};
|
||||
|
||||
//在流程库中添加一个流程
|
||||
object.method.addflow = function(id, name, func_start, func_over, time, flag1, flag2){
|
||||
/*参数说明:
|
||||
id : 流程id,必须唯一
|
||||
name : 流程名,主要起到说明和备注的作用
|
||||
func_start: 进入该流程时执行的函数(先完成本流程的开始处理,再根据time开启定时器)
|
||||
func_over : 该流程结束时执行的函数(先完成本流程的结束处理,再进入下一流程)
|
||||
time : 进入该流程后开启的定时器(自动触发func_over结束该流程)时长,毫秒
|
||||
-1: 不需要开启定时器,需要用户触发func_over结束流程
|
||||
0: 不需要开启定时器,执行完func_start后立即执行func_over结束流程
|
||||
>0: 需要开启定时器,定时器自动触发func_over结束流程
|
||||
flag1: 进入流程时执行完func_start后,是否由子游戏开启本流程的定时器,默认为0
|
||||
0: 由流程管理对象管理
|
||||
1: 由子游戏管理
|
||||
flag2: 结束流程时执行完func_over后,是否由子游戏关闭定时器并进入下一流程,默认为0
|
||||
0: 由流程管理对象管理
|
||||
1: 由子游戏管理*/
|
||||
return cls_flowMgr2.addflow(object, id, name, func_start, func_over, time, flag1, flag2);
|
||||
}
|
||||
//设置流程。参数steplist为流程配置,是一个流程id数组,如[2,1,1,3,2,4]
|
||||
object.method.set = function(steplist){
|
||||
object.steplist = steplist;
|
||||
}
|
||||
//获取当前流程
|
||||
object.method.currflow = function(){
|
||||
cls_flowMgr2.currflow(object);
|
||||
}
|
||||
//开始按流程配置执行
|
||||
object.method.startflow = function(){
|
||||
cls_flowMgr2.startflow(object);
|
||||
}
|
||||
//进入下一流程
|
||||
object.method.nextflow = function(){
|
||||
cls_flowMgr2.nextflow(object);
|
||||
}
|
||||
return object;
|
||||
},
|
||||
|
||||
//在流程库中添加一个流程
|
||||
addflow: function(o_flowMgr, id, name, func_start, func_over, time, flag1, flag2){
|
||||
var o_flow = {};
|
||||
o_flow.id = id; //流程id
|
||||
o_flow.name = name; //流程名
|
||||
o_flow.func_start = func_start; //进入该流程是执行的函数
|
||||
o_flow.func_over = func_over; //该流程结束时执行的函数
|
||||
o_flow.time = time; //进入该流程后开启的定时器时长
|
||||
o_flow.flag1 = flag1;
|
||||
o_flow.flag2 = flag2;
|
||||
o_flow.timer = null; //定时器id
|
||||
o_flowMgr.lib.push(o_flow);
|
||||
return o_flow;
|
||||
},
|
||||
//获取当前流程
|
||||
currflow: function(o_flowMgr){
|
||||
if (!o_flowMgr.steplist || o_flowMgr.steplist.length == 0){
|
||||
return null;
|
||||
}
|
||||
if (o_flowMgr.idx == -1 || o_flowMgr.idx >= o_flowMgr.steplist.length){
|
||||
return null;
|
||||
}
|
||||
var flowid = o_flowMgr.steplist[o_flowMgr.idx];
|
||||
var flowidx = min_ary_indexof(o_flowMgr.lib, flowid, "id");
|
||||
if (flowidx == -1){
|
||||
return null;
|
||||
}
|
||||
return o_flowMgr.lib[flowidx];
|
||||
},
|
||||
//开始按流程配置执行程序
|
||||
startflow: function(o_flowMgr){
|
||||
if (o_flowMgr.lib.length == 0){
|
||||
return;
|
||||
}
|
||||
if (o_flowMgr.steplist.length == 0){
|
||||
return;
|
||||
}
|
||||
o_flowMgr.idx = 0;
|
||||
this.exec(o_flowMgr);
|
||||
},
|
||||
//进入下一流程
|
||||
nextflow: function(o_flowMgr){
|
||||
var o_flow = this.currflow(o_flowMgr);
|
||||
if (o_flow){
|
||||
if (o_flow.func_over) {
|
||||
o_flow.func_over();
|
||||
}
|
||||
if (!o_flow.flag2){
|
||||
if (o_flow.timer){
|
||||
clearTimeout(o_flow.timer);
|
||||
o_flow.timer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
o_flowMgr.idx = o_flowMgr.idx + 1;
|
||||
this.exec(o_flowMgr);
|
||||
},
|
||||
//执行当前流程
|
||||
exec: function(o_flowMgr){
|
||||
var o_flow = this.currflow(o_flowMgr);
|
||||
if (!o_flow){
|
||||
return;
|
||||
}
|
||||
if (!o_flow.func_start){
|
||||
return;
|
||||
}
|
||||
o_flow.func_start();
|
||||
if (o_flow.time == 0) {
|
||||
this.nextflow(o_flowMgr);
|
||||
} else if (o_flow.time > 0) {
|
||||
//需要开启定时器
|
||||
if (!o_flow.flag1) {
|
||||
if (o_flow.func_over) {
|
||||
o_flow.timer = setTimeout(o_flow.func_over, o_flow.time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
70
codes/games/server/class/class.mod.js
Normal file
70
codes/games/server/class/class.mod.js
Normal file
@@ -0,0 +1,70 @@
|
||||
///////////////////////////////////////////////////
|
||||
//////////////cls_mod: 模块基础类//////////////////
|
||||
///////////////////////////////////////////////////
|
||||
var cls_mod = cls_mod || {
|
||||
//构造函数
|
||||
new: function(_str_modname, _str_routename, _obj_app) {
|
||||
/*
|
||||
_str_modname 模块名称
|
||||
_str_routename 模块的路由名称
|
||||
_obj_app 所属的应用对象
|
||||
*/
|
||||
|
||||
//创建一个实例
|
||||
var mod = {};
|
||||
|
||||
// ================= 实例的公有属性 ================= //
|
||||
//模块名称
|
||||
mod.modname = _str_modname;
|
||||
//路由名称
|
||||
mod.routename = _str_routename;
|
||||
//所属的应用
|
||||
mod.app = _obj_app;
|
||||
//将mod对象添加到app的模块列表中
|
||||
mod.app.modlist.push(mod);
|
||||
mod.app[_str_modname] = mod;
|
||||
|
||||
// ================= 实例的公有方法 ================= //
|
||||
//收包处理
|
||||
mod.DoPack = function(_msg) {
|
||||
return cls_mod.DoPack(mod, _msg);
|
||||
}
|
||||
|
||||
//输出mod
|
||||
cls_mod.OutputMod(mod);
|
||||
|
||||
return mod;
|
||||
},
|
||||
|
||||
DoPack: function(_obj_mod, _msg) {
|
||||
if (typeof(_msg) == "string") {
|
||||
_msg = JSON.parse(_msg); //转换json
|
||||
}
|
||||
//执行rpc
|
||||
if (_msg.rpc) {
|
||||
if (min_ExitsFunction(_obj_mod[_msg.rpc])) {
|
||||
return _obj_mod[_msg.rpc](_msg);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
OutputMod: function(_obj_mod) {
|
||||
if (typeof global !== "undefined")
|
||||
{} else {
|
||||
global = {};
|
||||
}
|
||||
|
||||
if (typeof module !== "undefined")
|
||||
{} else {
|
||||
module = {};
|
||||
module.exports = {};
|
||||
}
|
||||
|
||||
global[_obj_mod.modname] = _obj_mod;
|
||||
global[_obj_mod.modname].DoPack = _obj_mod.DoPack;
|
||||
|
||||
if (module) {
|
||||
module.exports[_obj_mod.modname] = _obj_mod;
|
||||
}
|
||||
}
|
||||
}
|
||||
93
codes/games/server/class/class.mysql.js
Normal file
93
codes/games/server/class/class.mysql.js
Normal file
@@ -0,0 +1,93 @@
|
||||
///////////////////////////////////////////////////
|
||||
///////////// cls_mysql: 数据库操作 ///////////////
|
||||
///////////////////////////////////////////////////
|
||||
var cls_mysql = cls_mysql || {
|
||||
|
||||
//构造函数
|
||||
new: function(url, func_fail_sendpack){
|
||||
var mysql = {};
|
||||
//php地址
|
||||
mysql.url = url;
|
||||
//发生错误时的回包函数
|
||||
mysql.func_fail_sendpack = func_fail_sendpack;
|
||||
|
||||
//执行sql语句
|
||||
mysql.execsql = function(method, sql, para, func_succ, pack) {
|
||||
/*
|
||||
method: php方法名 execsql/opensql
|
||||
sql: 要执行的sql语句
|
||||
para: 要执行的sql语句的参数数组
|
||||
func_succ: sql语句执行成功后的回调函数
|
||||
pack: 客户端发来的数据包,执行失败的话会根据pack返回客户端执行失败的结果
|
||||
*/
|
||||
var data = {}
|
||||
data.m = method;
|
||||
data.s = sql;
|
||||
data.p = para;
|
||||
|
||||
var strdata = JSON.stringify(data);
|
||||
//将=号替换为^,php收到后再替换回来,以避免=号POST传参会截断的问题
|
||||
strdata = strdata.replace(/\=/g,"^");
|
||||
//将+号替换为#,php收到后再替换回来,以避免+号POST传参会截断的问题
|
||||
strdata = strdata.replace(/\+/g,"#");
|
||||
//将&号替换为!,php收到后再替换回来,以避免&号POST传参会截断的问题
|
||||
strdata = strdata.replace(/\&/g,"!");
|
||||
|
||||
var cfg = {};
|
||||
cfg.url = mysql.url;
|
||||
cfg.data = "data=" + strdata;
|
||||
cfg.type = "POST";
|
||||
cfg.success = function(str) {
|
||||
try {
|
||||
var result = JSON.parse(str);
|
||||
} catch(e) {
|
||||
console.log(min_now() + " 数据库执行结果转换json失败.");
|
||||
console.log(str);
|
||||
console.log(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.state != 0) {
|
||||
console.log(min_now() + " 请求" + mysql.url + "失败.");
|
||||
console.log(result);
|
||||
console.log(data);
|
||||
|
||||
if (pack) {
|
||||
console.log(JSON.stringify(pack));
|
||||
//返回客户端执行失败的结果
|
||||
if (mysql.func_fail_sendpack) {
|
||||
pack.data = {};
|
||||
pack.data.state = result.state;
|
||||
pack.data.error = result.error;
|
||||
mysql.func_fail_sendpack(pack);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//执行sql成功执行回调函数
|
||||
// console.log(result);
|
||||
if (func_succ) {
|
||||
func_succ(result.data);
|
||||
}
|
||||
}
|
||||
};
|
||||
cfg.error = function(str){
|
||||
console.log(min_now() + " 请求" + mysql.url + "失败.");
|
||||
console.log(str);
|
||||
console.log(data);
|
||||
|
||||
if (pack) {
|
||||
console.log(JSON.stringify(pack));
|
||||
//返回客户端执行失败的结果
|
||||
if (mysql.func_fail_sendpack) {
|
||||
pack.data = {};
|
||||
pack.data.state = 99;
|
||||
pack.data.error = "请求数据库失败.";
|
||||
mysql.func_fail_sendpack(pack);
|
||||
}
|
||||
}
|
||||
};
|
||||
min_http(cfg);
|
||||
}
|
||||
return mysql;
|
||||
}
|
||||
}
|
||||
70
codes/games/server/class/class.pai.js
Normal file
70
codes/games/server/class/class.pai.js
Normal file
@@ -0,0 +1,70 @@
|
||||
///////////////////////////////////////////////////
|
||||
////////////////// cls_pai: 单张牌 ////////////////
|
||||
///////////////////////////////////////////////////
|
||||
var cls_pai = cls_pai || {
|
||||
|
||||
//创建单张牌实例
|
||||
new: function(id, score, dealowner){
|
||||
/*
|
||||
参数说明:
|
||||
id 牌的绝对id
|
||||
score 牌在游戏中的分值
|
||||
dealowner 发牌状态
|
||||
|
||||
扑克牌的统一编码规则:
|
||||
1,牌面花色的定义 5:王 4:黑桃 3:红心 2:梅花 1:方块
|
||||
2,牌面数值的定义 1:A 2:2 3:3 ... 9:9 10:10 11:J 12:Q 13:K 53:小王 54:大王
|
||||
*/
|
||||
var pai = {};
|
||||
|
||||
//属性
|
||||
pai.id = id; //绝对id,即数组下标,从0开始计数
|
||||
pai.score = score; //牌在游戏中的分值
|
||||
pai.dealowner = dealowner; //发牌状态
|
||||
//-1:规则去除的牌
|
||||
// 0:未发的牌,即底牌
|
||||
//>0:发牌发到谁手上,从1开始计数,即座位编号+1,座位编号是从0开始计数的
|
||||
pai.playround = -1; //出牌状态
|
||||
//-1:未出的牌
|
||||
// 0:埋牌
|
||||
//>0:牌是第几轮出出去的,从1开始计数
|
||||
pai.playindex = -1; //本轮中的出牌顺序,从1开始计数
|
||||
pai.playowner = -1; //出牌后被谁得到,与座位编号对应
|
||||
|
||||
//方法
|
||||
pai.method = {};
|
||||
|
||||
//牌面花色
|
||||
pai.method.get_flower = function(){
|
||||
return cls_pai.get_flower(pai);
|
||||
}
|
||||
|
||||
//牌面数值
|
||||
pai.method.get_number = function(){
|
||||
return cls_pai.get_number(pai);
|
||||
}
|
||||
|
||||
return pai;
|
||||
},
|
||||
|
||||
//获取牌面花色
|
||||
get_flower: function(o_pai) {
|
||||
var yu = o_pai.id % 54;
|
||||
if (yu == 52 || yu == 53){ //小王大王
|
||||
return 5;
|
||||
}
|
||||
return parseInt(yu / 13) + 1;
|
||||
},
|
||||
|
||||
//获取牌面数值
|
||||
get_number: function(o_pai) {
|
||||
var yu = o_pai.id % 54;
|
||||
if (yu == 52){ //小王
|
||||
return 53;
|
||||
}
|
||||
if (yu == 53){ //大王
|
||||
return 54;
|
||||
}
|
||||
return yu % 13 + 1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user