日本麻将记点器:日麻Saki
一个小小的日本麻将记点器,仅以陶冶节操(终于上班摸鱼摸出来了…)
之前看到NGA论坛上有位大神做了个日麻面基APP
,感觉有很多改进的空间,于是自己忍不住写了一个,很多界面和功能都借鉴了原版(没错,是借鉴!),代码就重新撸了一遍,和朋友一边玩一边完善功能,断断续续一年多了,功能都完成得差不多,上传来给大家分享一下。
不过功能太多,界面按钮有点小,如果用惯了以前大按钮的,可能会不适应,不喜勿喷!
本APP是免费开源软件,任何人可以免费使用、随意修改、传播该APP,但必须注明原作者。
核心代码简析
日本麻将主要涉及的核心就是如何算番算符,搞掂了这些问题,程序剩下的就可以随便搞了,下面来简单介绍一下方法。
1.和牌判定
首先,要实现自动算番,当然要先判断这副牌能不能和牌,这里使用最简答粗暴但是最快的方法:直接把所有和牌的样式列出来,然后来匹配[手动狗头]
/**
* 索引方法
*/
public class AgariIndex {
static final int[] n_zero;
static final TreeMap<Integer, int[]> tbl;
static {
n_zero = new int[34];
Arrays.fill(n_zero, 0);
tbl = new TreeMap<Integer, int[]>();
init(tbl);
}
public static boolean done(List<Tile> tiles, int added, List<Group[]> groups) {
int[] n = null;
int[] pos = new int[14];
int[] ret = null;
n = analyse(tiles);
int key = calc_key(n, pos);
ret = agari(key);
if (ret == null || ret.length == 0) {
// System.out.println("番名:混水摸鱼");
return false;
} else {
for (int r : ret) {
// System.out.println("r=" + r);
// if ((r&0x4000000) == 0x4000000) {
// System.out.println("七对子");
// } else if ((r&0x8000000) == 0x8000000) {
// System.out.println("九莲宝灯");
// } else if ((r&0x10000000) == 0x10000000) {
// System.out.println("一气通贯");
// } else if ((r&0x20000000) == 0x20000000) {
// System.out.println("二杯口");
// } else if ((r&0x40000000) == 0x40000000) {
// System.out.println("一杯口");
// } else if ((r&0x80000000) == 0x80000000) {
// System.out.println("国士无双");
// }
if ((r&0x4000000) != 0x4000000 && (r&0x80000000) != 0x80000000) {
// 七对子 和 国士无双 除外
List<Group> tmpList = new ArrayList<Groups.Group>();
boolean hasHePai = false;
GroupState state = GroupState.MenQing;
int value = pos[(r>>6)&0xF];
// System.out.println("雀頭=" + value);
state = (hasHePai = (added == value)) ? GroupState.HePai : GroupState.MenQing;
tmpList.add(new Groups.Pair(value, state));
int num_kotsu = r&0x7;
int num_shuntsu = (r>>3)&0x7;
for (int i = 0; i < num_kotsu; i++) {
value = pos[(r>>(10+i*4))&0xF];
if (hasHePai) state = GroupState.MenQing;
else state = (hasHePai = (added == value)) ? GroupState.HePai : GroupState.MenQing;
tmpList.add(new Groups.Pung(value, state));
// System.out.println("刻子=" + value);
}
for (int i = 0; i < num_shuntsu; i++) {
value = pos[(r>>(10+num_kotsu*4+i*4))&0xF];
if (hasHePai) state = GroupState.MenQing;
else state = (hasHePai = (added == value || added == value + 1 || added == value + 2)) ?
GroupState.HePai : GroupState.MenQing;
if (state == GroupState.HePai) {
tmpList.add(new Groups.Junko(value, state, calc_addedIndex(added, value)));
} else {
tmpList.add(new Groups.Junko(value, state));
}
// System.out.println("順子=" + value);
}
Group[] tmpArray = new Group[tmpList.size()];
groups.add(tmpList.toArray(tmpArray));
}
}
return true;
}
}
private static int calc_addedIndex(int added, int value) {
int addedIndex = -1;
if (added == value) {
addedIndex = 0;
} else if (added == value + 1) {
addedIndex = 1;
} else if (added == value + 2