読者です 読者をやめる 読者になる 読者になる

ゆとりーなの日記

日記的な事を書いて行くと思はれる

麻雀の話

そろそろ麻雀がやりたくなる季節ですのでこの邊りで一度コンピュータ麻雀をC++で作る時の話でもしてなんとか凌ぎませうといふことでこの流れです。
さて、麻雀で大事な事といへば、先づ牌の扱ひ方です。牌捌きの綺麗さは麻雀に於て重用な要素ですね。これをコンピュータ麻雀を作る時に當嵌めると、牌をどういふデータで扱ふかといふ話になる訣です。
麻雀は一萬と九萬、一筒〜九筒、一索〜九索、それに東南西北白發中の27種類の牌を使ふゲームです。これを0~26迄の數字で取り敢ず番號付けしたくなるのは人情ですね。
といふわけで最初に出て來る案が

#define Manzu1 0
#define Manzu9 1
#define Pinzu1 2
.
.
.
#define Chun 26

だつたりしたらこれはまづい訣です。頭をインクリメントして冷靜になる必要があります。しかしインクリメントしすぎて♯になつてしまふと明後日の方向に行つてしまふので程々にしないといけません。何事も限度といふものがあるのです。
次に出て來る案が

const int Manzu1 = 0;
const int Manzu9 = 1;
const int Pinzu1 = 2;
.
.
.
const int Chun = 26;

だとしたらこれは大分C++つぽくなつたと言へるでせう。しかしこれもやや問題があります。といふのもint型は麻雀では0〜26迄の數字しか使はないにも關はらず、それ以外の數字をも無情にも與へることが出來てしまふからです。これだと麻雀牌を引數にとつて何か仕事をする函數がある度に引數をassertで調べないと落ちついて麻雀が打てません。
で、次に出て來る案が

enum Pai {
  Manzu1, Manzu9, Pinzu1, ... Cnun
};

だつたりする訣ですが、これで可也の安全性が擔保されたことになります。キャストといふ害惡さへゐなければ範圍外の數字が入り込む要素はありません。しかしこの害惡がゐることを考慮すれば、心配性の雀士であれば安心出來ない可能性があるので矢張りassertで調べたくなつてしまふかもしれません。
そこで次に出て來る案が

class Pai {
 publc:
  static constexpr Pai Manzu1{0};
  static constexpr Pai Manzu9{1};
  static constexpr Pai Pinzu1{2};
  .
  .
  .
  static constexpr Pai Chun{26};
 private:
  constexpr Pai(int p) : pai(p) {}
  int pai;
};

とクラス作つて縛つてしまはふといふ戰法だつたりします。しかしこれはC++では通りません。自身の型をメンバとして持つことが出來ないのです。テンプレートに頼れば可能なのですが、

template <typename T>
class Pai_ {
 publc:
  static constexpr Pai_ Manzu1{0};
  static constexpr Pai_ Manzu9{1};
  static constexpr Pai_ Pinzu1{2};
  .
  .
  .
  static constexpr Pai_Chun{26};
 private:
  constexpr Pai_(int p) : pai(p) {}
  int pai;
};

template <typename T>
constepxr Pai_<T> Pai_<T>::Manzu1;
template <typename T>
constepxr Pai_<T> Pai_<T>::Manzu9;
template <typename T>
constepxr Pai_<T> Pai_<T>::Pinzu1;
.
.
.
template <typename T>
constepxr Pai_<T> Pai_<T>::Chun;

using Pai = Pai_<void>;

實體を書くのがめんどいです。
で、メンバ函數にしてしまへばといふ話になる訣です。constexprのお陰でメンバ函數でも定數厨の要望を滿足に滿たすことは可能です。

class Pai {
 publc:
  static constexpr Pai Manzu1() {return {0};};
  static constexpr Pai Manzu9() {return {1};};
  static constexpr Pai Pinzu1() {return {2}};
  .
  .
  .
  static constexpr Pai Chun() {return {26}};
 private:
  constexpr Pai(int p) : pai(p) {}
  int pai;
};

この方法の厭な所は定數を參照するのに定數なのにPai::Manzu1()の樣に少々見慣れない函數の形式になつてしまふことですね。
まあ要は0〜26迄しか取らない事が保證出來る整數型が簡單に作れる樣になつてくれれば萬事解決だつたりするのですが中々さうも行かない樣です。