定义

「手牌」是个歧义词,有时包括副露,有时不包括。 在 Libsaki 中,「手牌」指代包括副露的广义的手牌。

代表手牌的类是Hand,定义在libsaki/form/hand.h

Hand主要由三部分组成:closed, barks, drawn

  • Closed 包含 1, 4, 7, 10, 或 13 张牌, 代表不包括副露及自摸牌的纯手牌部分
  • Barks 用于记录鸣牌与暗杠
  • Drawn 代表摸上来的牌


常用方法

通过closed()barks()方法可以随时取得Closed或Barks部分。

通过hasDrawn()方法可判断当前是否有自摸牌(是否轮到自己出牌)。 当hasDrawn()返回true时,可通过drawn()方法读取当前的自摸牌; 当hasDrawn()返回false时,调用drawn()的后果是未定义的。

Hand有一堆检测当前是否可鸣牌的方法,如canPon(); 也有一堆实际执行鸣牌的方法,如pon()。 这些方法的作用都很直白。

TileCount类似地,Hand也有一系列向听数和有效牌计算方法。 计算手牌的向听数或有效牌时,直接使用这些方法会更方便—— 它们会自动将当前副露数、是否有自摸牌这些因素考虑进去。

Hand也支持预计算一个行动以后的向听数和有效牌, 也就是「切了这张就是x向听,听y种……」这种操作。 这些方法都是以peek开头的, 例如peekSwap就是预计算手切某一张牌以后的状况。

// 计算「切掉1p以后的向听数」
int s = hand.peekSwap(1_p, &Hand::step);

peek系列的东西是用变长参数的模板函数和指向成员函数的指针实现的。 除了向听数和有效牌以外,其实任何Hand的方法都能成为预测对象。