/** * 手牌 * *@authorzkpursuit */public classHandCards{
/** * 获取牌号最左边的一位数,如果牌为筒、条、万,则返回值为牌类型数值 * *@paramcard 牌号 *@return牌号从左至右第一位数(十位数) */ publicfinalstaticintgetCardLeftValue(intcard){
return card / 10;
}
/** * 获取牌号最右边的一位数,如果牌为筒、条、万,则返回值为牌点数 * *@paramcard 牌号 *@return牌号从右至左第一位数(个位数) */ publicfinalstaticintgetCardRightValue(intcard){
return card % 10;
}
/** * 获取牌号最左边的一位数,如果牌为筒、条、万,则返回值为牌类型数值 * *@paramidx 牌在归类数组中的索引位置 *@return牌号从左至右第一位数(十位数) */ publicfinalstaticintgetCardLeftValueByClusterIndex(intidx){
return idx / 10 + 1;
}
/** * 获取牌号最右边的一位数,如果牌为筒、条、万,则返回值为牌点数 * *@paramidx 牌在归类数组中的索引位置 *@return牌号从右至左第一位数(个位数) */ publicfinalstaticintgetCardRightValueByClusterIndex(intidx){
return idx % 10;
}
/** * 根据牌号取得其所在的牌归类数组中的索引 * *@paramcard 牌号 *@return牌归类数组中的索引 */ publicfinalstaticintgetClusterIndexByCard(intcard){
int left = getCardLeftValue(card);
int right = getCardRightValue(card);
int idx = (left - 1) * 10 + right;
return idx;
}
/** * 根据十位数和个位数确定牌在聚合数组中的索引位置 * *@paramleftValue 十位数 *@paramrightValue 个位数 *@return聚合数组中的索引位置 */ publicfinalstaticintgetClusterIndex(intleftValue,intrightValue){
return (leftValue - 1) * 10 + rightValue;
}
/**
* 归类牌
* 数组索引 / 10 + 1 表示牌类型
* 数组索引 % 10 表示牌点数
* 数组索引位置的值表示牌数量
*/ private int[] cardClusterArray;
/**
* 起始有效的索引位置
* 第一个值不为0的索引位置
*/ private int startIndex;
/**
* 归类牌数组的有效索引位置,因为有可能后面的位置全是0
* 此索引的后续索引位置的值全部为0,即最后一个值不为0的索引位置
*/ private int lastIndex;
/**
* 所有的牌数量
*/ private int cardTotals;
/**
* 构造方法
*/ publicHandCards(){
cardClusterArray = new int[40];
startIndex = 1000;
lastIndex = -1;
cardTotals = 0;
}
/** * 构造方法 * *@paramcards 未归类的牌数组 */ publicHandCards(int[] cards){
this();
if (cards != null) {
setCards(cards);
}
}
/**
* 重置数据
*/ publicvoidreset(){
if (cardTotals != 0) {
int len = getClusterValidLength();
for (int i = 0; i < len; i++) {
cardClusterArray[i] = 0;
}
}
startIndex = 1000;
lastIndex = -1;
cardTotals = 0;
}
/**
* 清除数据
*/ publicvoidclear(){
reset();
}
/** * 重置数据并以传入的牌数据再次初始化数据 * *@paramcards 牌数据 */ publicfinalvoidsetCards(int[] cards){
reset();
for (int card : cards) {
addCard(card);
}
}
/** * 添加num张牌 * *@paramcard 添加的牌号 *@paramnum 添加的数量 *@returntrue添加成功;false添加失败 */ publicbooleanaddCard(intcard,intnum){
int idx = getClusterIndexByCard(card);
int lastNum = cardClusterArray[idx] + num;
if (lastNum > 4) {
return false;
}
cardClusterArray[idx] = lastNum;
if (idx > lastIndex) {
lastIndex = idx;
}
if (idx < startIndex) {
startIndex = idx;
}
cardTotals += num;
return true;
}
/** * 添加一张牌 * *@paramcard 牌号 *@returntrue添加成功;false添加失败 */ publicbooleanaddCard(intcard){
return addCard(card, 1);
}
/** * 添加牌集合 * *@paramcards 牌集合,比如 [11, 23, 33, 33, 33, 34] *@returntrue添加成功,只要有一张添加失败则全部失败 */ publicbooleanaddCards(int... cards){
for (int card : cards) {
int idx = getClusterIndexByCard(card);
int lastNum = cardClusterArray[idx] + 1;
if (lastNum > 4) {
return false;
}
}
for (int card : cards) {
addCard(card);
}
return true;
}
/** * 移除num张牌 * *@paramcard 移除的牌号 *@paramnum 移除的数量 *@returntrue移除成功;false移除失败 */ publicbooleanremoveCard(intcard,intnum){
int idx = getClusterIndexByCard(card);
if (cardClusterArray[idx] < num) {
return false;
}
cardClusterArray[idx] -= num;
if (cardClusterArray[idx] == 0) {
if (idx == startIndex) {
startIndex = 1000;
for (int i = idx; i < cardClusterArray.length; i++) {
if (cardClusterArray[i] > 0) {
startIndex = i;
break;
}
}
}
if (lastIndex == idx) {
int start = startIndex;
if (start >= cardClusterArray.length) {
start = 0;
}
lastIndex = -1;
for (int i = idx; i >= start; i--) {
if (cardClusterArray[i] > 0) {
lastIndex = i;
break;
}
}
}
}
cardTotals -= num;
return true;
}
/** * 移除一张牌 * *@paramcard 牌号 *@returntrue移除成功;false移除失败 */ publicbooleanremoveCard(intcard){
return removeCard(card, 1);
}
/** * 移除牌号对应的所有牌 * *@paramcard 牌号 *@returntrue移除成功;false移除失败 */ publicbooleanremoveCardOfAll(intcard){
int num = getCardNum(card);
if (num >= 0) {
return removeCard(card, num);
}
return true;
}
/** * 移除牌 * *@paramcards 需要移除的牌 *@returntrue表示移除成功,只要有一张牌移除失败则整个失败 */ publicbooleanremoveCards(int... cards){
for (int card : cards) {
int idx = getClusterIndexByCard(card);
if (cardClusterArray[idx] < 1) {
return false;
}
}
for (int card : cards) {
removeCard(card);
}
return true;
}
/** * 是否有指定的牌 * *@paramcard 牌号 *@returntrue表示存在 */ publicbooleanhasCard(intcard){
return getCardNum(card) > 0;
}
/** * 获取牌号对应的数量 * *@paramcard 牌号 *@return牌号对应的数量 */ publicintgetCardNum(intcard){
int idx = getClusterIndexByCard(card);
return cardClusterArray[idx];
}
/** * 获取归类的牌数据,整除10的索引位置为保留位,不参与任何实际运算
* 数组索引从0开始,有效长度(后面全部为0)结束
* 此数组为数据副本,其中的任何数据变动都不会改变原数组
* 数组索引 / 10 + 1 表示牌类型
* 数组索引 % 10 表示牌点数
* *@return归类的牌数据 */ public int[] getCardClusterArray() {
int[] array = new int[getClusterValidLength()];
System.arraycopy(cardClusterArray, 0, array, 0, array.length);
return array;
}
/** * 根据提供的索引位置获取牌数量 * *@paramidx 牌归类数组中的索引位置 *@return牌数量 */ publicintgetCardNumByClusterIndex(intidx){
return cardClusterArray[idx];
}
/** * 根据索引位置定位对应的牌 * *@paramidx 归类牌数组中的索引位置 *@return-1表示找不到对应的牌,否则返回牌号 */ publicintgetCardByClusterIndex(intidx){
if (cardClusterArray[idx] <= 0) {
return -1;
}
int left = getCardLeftValueByClusterIndex(idx);
int right = getCardRightValueByClusterIndex(idx);
return left * 10 + right;
}
/** * 归类牌数组中起始有效索引 * *@return起始有效索引,第一个值不为0的索引位置 */ publicintgetClusterValidStartIndex(){
if (cardTotals == 0) {
return 1;
}
return startIndex;
}
/** * 归类牌数组中最终的有效索引 * *@return最终有效索引,其后的值全为0 */ publicintgetClusterValidEndIndex(){
return lastIndex;
}
/** * 归类牌数组的有效长度
* 有效的起始索引到有效的最后索引之前的长度
* *@return有效长度,因为归类数组中后面可能有很多无效的0 */ publicintgetClusterValidLength(){
return lastIndex + 1;
}
/** * 所有牌的张数 * *@return总张数 */ publicintgetCardTotals(){
return cardTotals;
}
/** * 获取所有的牌数据,未归类 * *@return未归类的牌数据,两位数的牌号数组 */ public int[] getCards() {
if (cardTotals <= 0) {
return null;
}
int len = getClusterValidLength();
int[] cards = new int[cardTotals];
int idx = 0;
for (int i = getClusterValidStartIndex(); i < len; i++) {
int left = getCardLeftValueByClusterIndex(i);
int right = getCardRightValueByClusterIndex(i);
int count = cardClusterArray[i];
int card = left * 10 + right;
for (int j = 0; j < count; j++) {
cards[idx] = card;
idx++;
}
}
return cards;
}
@Override publicHandCardsclone(){
HandCards copy = new HandCards();
copy.cardTotals = this.cardTotals;
copy.lastIndex = this.lastIndex;
copy.startIndex = this.startIndex;
if (cardClusterArray != null) {
int[] copyCardClusterArray = new int[cardClusterArray.length];
System.arraycopy(cardClusterArray, 0, copyCardClusterArray, 0, cardClusterArray.length);
copy.cardClusterArray = copyCardClusterArray;
}
return copy;
}
}