import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
//手中的牌
public class HandBone {
private Bone m_aGangBone[]; //明杠过的牌
private int m_nGang; //明杠过的牌的个数
private Bone m_aAnGangBone[]; //暗杠过的牌
private int m_nAnGang; //暗杠过的牌的个数
private Bone m_aChiBone[]; //吃过的牌
private int m_nChi; //吃过的牌的个数
private Bone m_aPengBone[]; //碰过的牌
private int m_nPeng; //碰过的牌的个数
private Bone m_aHandBone[]; //手中的牌,经过吃碰杠剩下的牌
private int m_nHand; //手中牌的个数
private Bone m_HoldBone; //摸到的牌
private Image m_ArrowImg;
private int m_nSelectIndex; //打牌的位置
private int m_aChiIndex[]; //可以吃的牌的索引数组
//m_nChiIndex是m_aChiIndex中当前选择的索引,因为可能同时存在几种吃法
private int m_nChiIndex;
private int m_aPengIndex[]; //可以碰的牌的索引数组
private int m_aGangIndex[]; //可以杠牌的的索引数组
private int m_aAnGangIndex[]; //可以暗杠牌的的索引数组
private int m_nX; //牌起始位置的X坐标
private int m_nY; //牌起始位置的Y坐标
private boolean m_bPlayer; //true表示为玩家的牌,false表示电脑的牌
//构造方法
//参数arrow为箭头图像
//参数x、y为牌起始位置
//参数bPlayer为true表示为玩家的牌,为false表示电脑的牌
public HandBone( Image arrow, int x, int y, boolean bPlayer ){
m_nX = x;
m_nY = y;
m_ArrowImg = arrow;
m_aGangBone = new Bone[16]; //最多有16张名杠
m_aAnGangBone = new Bone[16]; //最多有16张暗杠
m_aChiBone = new Bone[12]; //最多有12张牌被吃
m_aPengBone = new Bone[12]; //最多有12张牌被碰
m_aHandBone = new Bone[13]; //手中最多有13张牌
m_aChiIndex = new int[6]; //用3组,每组2个数据记录手中与桌面上可组成吃牌的索引
m_aPengIndex = new int[2]; //手中与桌面上可组成碰牌的索引
m_aGangIndex = new int[3]; //手中与桌面上可组成杠牌的索引
m_aAnGangIndex = new int[3]; //手中与桌面上可组成暗杠牌的索引
m_bPlayer = bPlayer;
Reset();
}
//获取是否是玩家的牌的标志
public boolean isPlayer(){
return m_bPlayer;
}
//重新开牌
public void Reset(){
for( int n = 0; n < 16; n ++ ){
m_aGangBone[n] = null;
m_aAnGangBone[n] = null;
if( n < 13 )
m_aHandBone[n] = null;
if( n < 12 ){
m_aChiBone[n] = null;
m_aPengBone[n] = null;
}
}
m_HoldBone = null;
m_nGang = 0;
m_nAnGang = 0;
m_nChi = 0;
m_nPeng = 0;
m_nHand = 0;
}
//向手中增加牌
public boolean AddHandBone( Bone bone ){
if( m_nHand >= m_aHandBone.length )
return false;
m_aHandBone[m_nHand] = bone;
if( m_bPlayer )
m_aHandBone[m_nHand].setState(Bone.BASE_FRONT);
else
m_aHandBone[m_nHand].setState(Bone.BASE_BACK);
m_nHand ++;
return true;
}
//摸牌
public void SetHold( Bone bone ){
m_HoldBone = bone;
m_nSelectIndex = m_nHand;
}
//获取刚摸到的牌
public Bone getHoldBone(){
return m_HoldBone;
}
//移动选择的位置,参数bLeft为true表示向左移动,否则向右移动
public void MoveSelect( boolean bLeft ){
int index = m_nSelectIndex;
if( bLeft )
index --;
else
index ++;
if( index < 0 )
index = m_nHand;
if( index > m_nHand )
index = 0;
//要打的牌的位置,index为m_nHand表示要打刚刚摸到的牌
//index为0~m_nHand-1时为打手中剩余的牌
m_nSelectIndex = index;
}
//打出牌,参数index为手中牌的索引
//返回打出的牌
public Bone OutBone(){
//还没摸牌则不能打牌
if( m_HoldBone == null )
return null;
if( m_nSelectIndex < 0 || m_nSelectIndex > m_nHand )
return null;
Bone bone;
if( m_nSelectIndex == m_nHand )
bone = m_HoldBone; //打摸到的牌
else
{//打手中其他的牌,并将摸到的牌放到手中
bone = m_aHandBone[m_nSelectIndex];
m_aHandBone[m_nSelectIndex] = m_HoldBone;
}
m_HoldBone = null;
OrderHand(); //排列手中牌的顺序
return bone;
}
//排列手中剩余牌的顺序
public void OrderHand(){
Bone temp;
for( int i = 0; i < m_nHand; i ++ )
{
for( int j = i + 1; j < m_nHand; j ++ )
{
if( m_aHandBone[i].getWord() > m_aHandBone[j].getWord() )
{//先按类型排列
temp = m_aHandBone[i];
m_aHandBone[i] = m_aHandBone[j];
m_aHandBone[j] = temp;
}
else if( m_aHandBone[i].getWord() == m_aHandBone[j].getWord() )
{//类型相同则按牌的面值排列
if( m_aHandBone[i].getValue() > m_aHandBone[j].getValue() )
{
temp = m_aHandBone[i];
m_aHandBone[i] = m_aHandBone[j];
m_aHandBone[j] = temp;
}
}
}
}
}
//判断手中的剩余牌与指定的牌是否可以组成“杠”,参数bone为指定的牌
public boolean canGang(Bone bone){
for( int n = 0; n < m_aGangIndex.length; n ++ )
m_aGangIndex[n] = -1;
//有三张面值及种类与bone相同的牌,则可以杠
int word = bone.getWord();
int value = bone.getValue();
int num = 0;
for( int n = 0; n < m_nHand; n ++ )
{
if( m_aHandBone[n].getWord() == word &&
m_aHandBone[n].getValue() == value )
{
if( num < m_aGangIndex.length ){
m_aGangIndex[num] = n;
num ++;
}
}
}
if( m_aGangIndex[2] != -1 )
return true;
//和已经名的碰牌杠
num = 0;
for( int n = 0; n < m_nPeng; n ++ ){
if( m_aPengBone[n].getWord() == word &&
m_aPengBone[n].getValue() == value ){
m_aGangIndex[num] = n + 100;
num ++;
}
}
if( m_aGangIndex[2] != -1 )
return true;
return false;
}
//判断手中的剩余牌与指定的牌是否可以组成“暗杠”,参数bone为指定的牌
public boolean canAnGang(Bone bone){
for( int n = 0; n < m_aAnGangIndex.length; n ++ )
m_aAnGangIndex[n] = -1;
//有三张面值及种类与bone相同的牌,则可以杠
int word = bone.getWord();
int value = bone.getValue();
int num = 0;
for( int n = 0; n < m_nHand; n ++ )
{
if( m_aHandBone[n].getWord() == word &&
m_aHandBone[n].getValue() == value )
{
if( num < m_aGangIndex.length ){
m_aAnGangIndex[num] = n;
num ++;
}
}
}
if( m_aAnGangIndex[2] != -1 )
return true;
return false;
}
//判断手中的剩余牌与指定的牌是否可以组成“碰”,参数bone为指定的牌
public boolean canPeng(Bone bone){
for( int n = 0; n < m_aPengIndex.length; n ++ )
m_aPengIndex[n] = -1;
//有两张面值及种类与bone相同的牌,则可以碰
int word = bone.getWord();
int value = bone.getValue();
int num = 0;
for( int n = 0; n < m_nHand; n ++ )
{
if( m_aHandBone[n].getWord() == word &&
m_aHandBone[n].getValue() == value )
{
if( num < m_aPengIndex.length ){
m_aPengIndex[num] = n;
num ++;
}
}
}
if( m_aPengIndex[1] != -1 )
return true;
return false;
}
//判断手中的剩余牌与指定的牌是否可以组成“吃”,参数bone为指定的牌
public boolean canChi(Bone bone){
for( int n = 0; n < m_aChiIndex.length; n ++ )
m_aChiIndex[n] = -1;
m_nChiIndex = 0;
//aShun存储手中与bone相连的牌的索引(前后能组成吃的最多5张牌)
//aShun[2]代表指定的牌如五万
//aShun[0]代表指定的牌的前2个面值的牌,如三万
//aShun[1]代表指定的牌的前1个面值的牌,如四万
//aShun[3]代表指定的牌的后1个面值的牌,如六万
//aShun[4]代表指定的牌的后2个面值的牌,如七万
int aShun[] = new int[5];
for( int n = 0; n < aShun.length; n ++ )
aShun[n] = -1;
int word = bone.getWord();
if( word == Bone.WORD_ZI )
return false;
int value = bone.getValue();
for( int n = 0; n < m_nHand; n ++ )
{
if( m_aHandBone[n].getWord() == word )
{
int index = m_aHandBone[n].getValue() - value;
if( index >= -2 && index <= 2 )
{//如果在可组成吃牌的范围内
aShun[index+2] = n;
}
}
}
boolean bReturn = false;
if( aShun[0] != -1 && aShun[1] != -1 )
{//存在第一种吃法,如有三万、四万吃五万
m_aChiIndex[0] = aShun[0];
m_aChiIndex[1] = aShun[1];
m_nChiIndex = 0;
bReturn = true;
}
if( aShun[1] != -1 && aShun[3] != -1 )
{//存在第二种吃法,如有四万、六万吃五万
m_aChiIndex[2] = aShun[1];
m_aChiIndex[3] = aShun[3];
m_nChiIndex = 2;
bReturn = true;
}
if( aShun[3] != -1 &&