actionScript3.0 麻将算法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package
{
import flash.events.Event;
import flash.events.EventDispatcher;
public class Player extends EventDispatcher
{
public static const PLAYER_TOTAL:Number=4; // 玩家数量
public static const STANDARD_CARD_NUM:Number=16; // 玩家手牌数量
public static const GMAE_END:String="GMAE_END"; // 游戏结束事件
private var _handcardList:Array; // 玩家拥有的牌,
private var _outCardList:Array; // 玩家打出的牌
private var _showCardList:Array; // 玩家显示的牌,吃碰杠的牌
private var _position:int // 方位
private var _huaList:Array; // 花牌列表
private var _ai:Boolean; // 当前玩家是否设置为电脑AI
public function Player(pos:int, ai:Boolean)
{
_ai=ai;
_position=pos;
_handcardList=[];
_showCardList=[];
_outCardList=[];
_huaList=[];
}
/**
* 手牌上是否存在指定牌
* @param card
* @return
*/
public function hasCardInHand(card:uint):Boolean
{
return _handcardList.indexOf(card) != -1;
}
public function get handCardNum():int
{
return _handcardList.length;
}
/**
* 当前是否已经摸牌,为等待出牌状态
*/
public function get isOutCardState():Boolean
{
return handCardNum % 3 == 2;
}
/**
* 听牌检测
* @return - 所听牌列表,如果没有听牌则返回空列表
*/
public function waitCard():Array
{
var tempArr:Array=[];
var mahjongList:Array=MahjongManager.MAHJONG_ALL_TYPE;
for each (var card:uint in mahjongList)
{
if (winTest(card) == 1)
{
tempArr.push(card);
}
}
return tempArr;
}
public function gameEnd():void
{
dispatchEvent(new Event(GMAE_END));
}
/**
* 添加手牌
* @param card
*/
public function addToHandList(card:uint):void
{
_handcardList.push(card);
dispatchEvent(new Event(Event.CHANGE));
}
/**
* 添加用户显示的牌
* @param card
*/
public function addToShowList(tmpArr:Array):void
{
tmpArr.sort(Array.NUMERIC);
for (var i:int=0; i < tmpArr.length; i++)
{
_showCardList.push(tmpArr[i]);
}
dispatchEvent(new Event(Event.CHANGE));
}
/**
* 移除一个显示牌
* @param card
* @return
*/
public function removeFromShowList(card:uint):Boolean
{
var index:int=_showCardList.indexOf(card);
var bo:Boolean=false;
if (index != -1)
{
_showCardList.splice(index, 1);
bo=true;
}
dispatchEvent(new Event(Event.CHANGE));
return bo;
}
/**
* 移除一个手牌
* @param card
* @return
*/
public function removeFromHandList(card:uint):Boolean
{
var index:int=_handcardList.indexOf(card);
var bo:Boolean=false;
if (index != -1)
{
_handcardList.splice(index, 1);
bo=true;
}
dispatchEvent(new Event(Event.CHANGE));
return bo;
}
public function catchCard():uint
{
var card:uint=MahjongManager.instance.retrieveMahjong();
while ((card & MahjongManager.MASK_COLOR) == MahjongManager.HUA)
{
_outCardList.push(card); // 放到用户桌牌列表
_huaList.push(card);
card=MahjongManager.instance.retrieveMahjong();
dispatchEvent(new Event(Event.CHANGE));
}
return card;
}
/**
* 补花
*/
public function buHua():void
{
for (var i:int; i < _handcardList.length; i++)
{
var card:uint=_handcardList[i];
if ((card & MahjongManager.MASK_COLOR) == MahjongManager.HUA)
{
_huaList.push(card);
_outCardList.push(card);
_handcardList.splice(i, 1);
var tmpCard:uint=catchCard();
_handcardList.push(tmpCard);
buHua();
}
}
dispatchEvent(new Event(Event.CHANGE));
}
/**
* 出牌
* @param card
*/
public function userOutCard(card:uint):void
{
var index:int=_handcardList.indexOf(card);
if (index != -1) // 判断手牌列表是否存在这个牌
{
_handcardList.splice(index, 1);
sortHandCard();
_outCardList.push(card);
dispatchEvent(new Event(Event.CHANGE));
}
}
//将手里的牌排序
public function sortHandCard():void
{
_handcardList.sort(Array.NUMERIC);
}
/**
* 判断一组数字都不相等
* @param arr
* @return
*/
public function unequal(arr:Array):Boolean
{
var len:int=arr.length;
for (var i:int=0; i < len; i++)
{
for (var j:int=i + 1; j < len; j++)
{
if (arr[i] == arr[j])
{
return false;
}
}
}
return true;
}
/**
* 判断一组数字都相等
* @param arr
* @return
*/
public function equal(arr:Array):Boolean
{
var len:int=arr.length;
for (var i:int=1; i < len; i++)
{
if (arr[0] != arr[i])
{
return false;
}
}
return true;
}
/**
* 补杠或暗杠
* @param card
* @return - arr[0]:0没杠,1暗杠,2补杠 arr[1]杠牌
*/
public function privateKong(card:uint):Array
{
var arr:Array=[0];
var handcardList:Array=_handcardList.concat(card);
var handcardNum:int=handcardList.length;
for (var i:int=0; i < handcardNum; i++) // 暗杠
{
for (var j:int=i; j < handcardNum; j++)
{
for (var k:int=j; k < handcardNum; k++)
{
for (var n:int=k; n < handcardNum; n++)
{
if (unequal([i, j, k, n]) && equal([handcardList[i], handcardList[j], handcardList[k], handcardList[n]]))
{
arr[0]=1; // 暗杠
arr[1]=[handcardList[i], handcardList[i], handcardList[i]];
}
}
}
}
}
handcardList=_showCardList;
handcardNum=handcardList.length;
for (i=0; i < handcardNum; i++) // 补杠
{
for (j=i; j < handcardNum; j++)
{
for (k=j; k < handcardNum; k++)
{
if (k != j && k != i && i != j && handcardList[i] == card && handcardList[j] == card && handcardList[k] == card)
{
arr[0]=2; // 补杠
arr[1]=[card, card, card];
}
}
}
}
return arr;
}
/**
* 碰杠
* 其它玩家打出一个牌,杠
* @param card
* @return
*/
public function pundKong(card:uint):Array
{
var handcardNum:int=_handcardList.length;
for (var i:int=0; i < handcardNum; i++)
{
for (var j:int=i; j < handcardNum; j++)
{
for (var k:int=j; k < handcardNum; k++)
{
if (k != j && k != i && i != j && _handcardList[i] == card && _handcardList[j] == card && _handcardList[k] == card)
{
return [card, card, card];
}
}
}
}
return [];
}
// 判断指定的牌是否为风,箭,花牌
public function isFJH(card:uint):Boolean
{
var temp:Boolean=false;
var cardType:uint=card & MahjongManager.MASK_COLOR;
if (cardType == MahjongManager.JIAN || cardType == MahjongManager.FENG || cardType == MahjongManager.HUA)
{
temp=true;
}
return temp;
}
/**
* 检测当前用户吃牌情况
* @param card - 牌值
* @return - 数组第一个元素标志后面元素可组合吃牌的个数.
*/
public function userChow(card:uint):Array
{
var mj:Array=[];
// 风箭花不吃牌
if (!isFJH(card))
{
var handcardNum:int=_handcardList.length;
for (var i:int=0; i < handcardNum; i++)
{
for (var j:int=i; j < handcardNum; j++)
{
if (i != j)
{
var arr:Array=[card, _handcardList[i], _handcardList[j]];
arr.sort(Array.NUMERIC);
if (arr[2] == arr[1] + 1 && arr[2] == arr[0] + 2)
{
if (mj.length > 0) // 以下,过滤相同的吃牌
{
var temp:Array=mj[mj.length - 1];
if (_handcardList[i] + _handcardList[j] == temp[0] + temp[1])
{
if (temp[0] == _handcardList[i] || temp[0] == _handcardList[j])
{
continue;
}
}
}
mj.push([_handcardList[i], _handcardList[j]]);
}
}
}
}
}
return mj;
}
/**
* 碰牌检测
* 有碰返回几组,否则返回0。
* @param card -
* @return
*/
public function userPung(card:uint):Array
{
var handcardNum:int=_handcardList.length;
for (var i:int=0; i < handcardNum; i++)
{
for (var j:int=i; j < handcardNum; j++)
{
if (i != j && _handcardList[i] == card && _handcardList[j] == card)
{
return [card, card];
}
}
}
return [];
}
/**
* 找闲牌
*/
public function searchIdleCard():uint
{
var handcardNum:int=_handcardList.length; // 手牌的个数
var tempArr:Array=_handcardList.slice(0, handcardNum);
// 找相同的三个牌
for (var i:int=0; i < handcardNum; i++)
{
for (var j:int=i; j < handcardNum; j++)
{
for (var n:int=j; n < handcardNum; n++)
{
if (i != j && j != n && i != n && tempArr[i] == tempArr[j] && tempArr[j] == tempArr[n] && tempArr[i] > 0)
{
tempArr[i]=-4;
tempArr[j]=-4;
tempArr[n]=-4;
}
}
}
}
// 找顺子
for (i=0; i < handcardNum; i++)
{
// 风箭花不吃牌
if (tempArr[i] < 0)
continue;
if (isFJH(tempArr[i]))
{
continue;
}
for (j=i; j < handcardNum; j++)
{
for (n=j; n < handcardNum; n++)
{
if (i != j && j != n && i != n && tempArr[i] > 0 && tempArr[j] > 0 && tempArr[n] > 0)
{
var arr:Array=[tempArr[i], tempArr[j], tempArr[n]];
arr.sort(Array.NUMERIC);
if (arr[2] == arr[1] + 1 && arr[2] == arr[0] + 2)
{
tempArr[i]=-3;
tempArr[j]=-3;
tempArr[n]=-3;
}
}
}
}
}
// 找两个相同的
for (i=0; i < handcardNum; i++)
{
for (j=i; j < handcardNum; j++)
{
if (i != j && tempArr[i] > 0 && tempArr[j] > 0)
{
if (tempArr[i] == tempArr[j])
{
tempArr[i]=-2;
tempArr[j]=-2;
}
}
}
}
// 找两个相邻的牌
for (i=0; i < handcardNum; i++)
{
// 风箭花不吃牌
if (tempArr[i] < 0)
continue;
if (isFJH(tempArr[i]))
{
continue;
}
for (j=i; j < handcardNum; j++)
{
if (i != j && tempArr[i] > 0 && tempArr[j] > 0)
{
if (tempArr[i] == tempArr[j] + 1 || tempArr[j] == tempArr[i] + 1)
{
tempArr[i]=-1;
tempArr[j]=-1;
}
}
}
}
var index:int=0;
for (i=1; i < handcardNum; i++)
{
if (tempArr[i] > tempArr[index])
{
index=i;
}
}
return _handcardList[index];
}
/**
* 胡牌检测
* 基本形胡牌 11,123,111,123,111
* @param handcardList - 玩家拥有牌列表(包括吃碰杠牌)
* @param handcardNum - 玩家手牌张数(不包括吃碰杠牌);
* @return - 返回0为未胡,胡牌返回1.
*/
public function winTest(card:uint=0):int
{
var result:int=0;
var eye:int=0; // 将眼的个数
var abc:int=0; // 顺和三条的个数
var ja:Array=[]; // 将眼A的位置.
var jb:Array=[]; // 将眼B的位置.
var testList:Array=_handcardList.concat();
testList.push(card);
var handcardNum:int=testList.length; // 手牌数量
var mj:Array=testList.concat();
for (var i:int=0; i < handcardNum; i++)
{
for (var j:int=i; j < handcardNum; j++)
{
if (i != j && mj[i] == mj[j] && mj[i] != -1) // 找出所有两张相同的牌
{
ja[eye]=i;
jb[eye]=j;
mj[i]=-1;
mj[j]=-1;
eye++
}
}
}
for (var k:int=0; k < eye; k++)
{
// 除去将眼,先查找三个两同的牌
mj=testList.concat();
mj[ja[k]]=-1;
mj[jb[k]]=-1;
abc=0;
searchThree();
searchStraight();
if (abc == int(handcardNum / 3))
{
result=1; // 符合和牌牌型
break;
}
mj=testList.concat();
mj[ja[k]]=-1;
mj[jb[k]]=-1;
abc=0;
searchStraight();
searchThree();
if (abc == int(handcardNum / 3))
{
result=1;
break;
}
}
return result;
function searchThree():void
{
for (i=0; i < handcardNum; i++)
{
for (j=i; j < handcardNum; j++)
{
for (var n:int=j; n < handcardNum; n++)
{
if (i != j && j != n && i != n && mj[i] == mj[j] && mj[j] == mj[n] && mj[i] != -1)
{
abc+=1;
mj[i]=-1;
mj[j]=-1;
mj[n]=-1;
}
}
}
}
}
function searchStraight():void
{
for (i=0; i < handcardNum; i++)
{
// 风箭花不吃牌
if (mj[i] == -1)
continue;
if (isFJH(mj[i]))
{
continue;
}
for (j=i; j < handcardNum; j++)
{
for (var n:int=j; n < handcardNum; n++)
{
if (i != j && j != n && i != n && mj[i] != -1 && mj[j] != -1 && mj[n] != -1)
{
var arr:Array=[mj[i], mj[j], mj[n]];
arr.sort(Array.NUMERIC);
if (arr[2] == arr[1] + 1 && arr[2] == arr[0] + 2)
{
abc+=1;
mj[i]=-1;
mj[j]=-1;
mj[n]=-1;
}
}
}
}
}
}
} // end of function
public function get handcardList():Array
{
return _handcardList;
}
public function set handcardList(value:Array):void
{
_handcardList=value;
sortHandCard();
}
public function get position():int
{
return _position;
}
public function get showCardList():Array
{
return _showCardList;
}
public function get outCardList():Array
{
return _outCardList;
}
public function get ai():Boolean
{
return _ai;
}
}
}