4

サイコロゲームを作っています。私がすべての値を持っているサイコロが 5 つあり、それらがフルハウス (1 つの 3 つと別の 2 つ)、スモール ストレート (1-4、2-6、または 3-6) を構成するかどうかを判断する必要があります。大きなストレート (1-5、2-6)。

おそらく、これにアプローチする最善の方法は、正規表現を使用することです。

これらのルールを正規表現で表現する方法を知っている人はいますか?

または、より良い解決策を提供できる場合は、それをいただければ幸いです。

例:

  • フルハウス = 44422 または 11166 または 12212 など。
  • スモール ストレート = 12342 または 54532 など。
  • ラージ ストレート = 12345 または 52643 など

編集
これが私の経験の浅い意見であることを強調するために文言を変更しました。

コードを使用してこれを実現する方法は知っていますが、非常に長い解決策のように思えます。もっと単純なアプローチがあるかどうか疑問に思っています。

4

7 に答える 7

5

すべての数値を減少させてから、int[] であるか文字列であるかに関係なく、それに沿って進むにつれて、各値に対していくつかの線形基準の一致を行います。

于 2011-06-26T10:22:38.090 に答える
4

c#についてはわかりませんが、スクリプト言語では正規表現を使用します。それぞれの側について、それが組み合わせで発生する回数を計算し、結果を結合します。たとえば、組み合わせ12342の場合、カウンタ文字列はになります121100。次に、カウンター文字列を次のパターンと照合します。

/5/         = Five of a kind
/4/         = Four of a kind
/20*3|30*2/ = Full house
/1{5}/      = Large Straight
/[12]{4}/   = Small Straight
/3/         = Three of a kind
/2[013]*2/  = Two pair
/2/         = One pair
于 2011-06-26T10:55:49.863 に答える
0

自分で試してみることにしましたが、正規表現を使用しないことになりました。必要な検索が単純なため、正規表現を使用すると、保存するよりも複雑になると思いました。しかし、私は別の答えと同様のロジックを使用しました。各数値の量を数え、それに基づいてすべてのスコアリングを行います。

  enum RollScoreType
  {
     HighDie,
     Pair,
     TwoPair,
     ThreeOfAKind,
     SmallStright,
     PairSmallStriaght,
     FullHouse,
     LargeStraight,
     FourOfAKind,
     FiveOfAKind
  }

  struct RollScore
  {
     public RollScoreType type;
     public byte highestDie;
     public byte nextHighestDie;
     public RollScore(RollScoreType type, byte highest, byte next)
     {
        this.type = type;
        this.highestDie = highest;
        this.nextHighestDie = next;
     }
     public override string ToString()
     {
        return string.Format("{0} {1} {2}", type, highestDie, nextHighestDie);
     }
  }

  static RollScore GetDiceScore(string input)
  {
     char[] dice = input.ToCharArray();
     byte[] diceCount = new byte[6];

     for (int i = 0; i < dice.Length; i++)
        diceCount[int.Parse(dice[i].ToString())-1]++;

     if (Array.IndexOf(diceCount, (byte)5) >= 0)
        return new RollScore(RollScoreType.FiveOfAKind, (byte)(Array.IndexOf(diceCount, (byte)5) + 1), 0);
     else if (Array.IndexOf(diceCount, (byte)4) >= 0)
        return new RollScore(RollScoreType.FourOfAKind, (byte)(Array.IndexOf(diceCount, (byte)4) + 1), (byte)(Array.IndexOf(diceCount, (byte)1) + 1));
     else if (Array.IndexOf(diceCount, (byte)3) >= 0)
     {
        byte three = (byte)(Array.IndexOf(diceCount, (byte)3) + 1);
        if (Array.IndexOf(diceCount, (byte)2) >= 0)
        {
           byte pair = (byte)(Array.IndexOf(diceCount, (byte)2) + 1);
           return new RollScore(RollScoreType.FullHouse, Math.Max(pair, three), Math.Min(pair, three));
        }
        else
           return new RollScore(RollScoreType.ThreeOfAKind, three, (byte)(Array.LastIndexOf(diceCount, (byte)1) + 1));
     }
     else if (Array.IndexOf(diceCount, (byte)2) >= 0)
     {
        byte pair = (byte)(Array.IndexOf(diceCount, (byte)2) + 1);
        byte highPair = (byte)(Array.LastIndexOf(diceCount, (byte)2) + 1);
        if (highPair != pair)
           return new RollScore(RollScoreType.TwoPair, highPair, pair);
        else
        {
           byte lowMissingDie = (byte)Array.IndexOf(diceCount, (byte)0);
           byte highMissingDie = (byte)Array.LastIndexOf(diceCount, (byte)0);
           switch (lowMissingDie)
           {
              case 0:
                 if (highMissingDie == 5)
                    return new RollScore(RollScoreType.PairSmallStriaght, 5, 4);
                 if (highMissingDie == 1)
                    return new RollScore(RollScoreType.PairSmallStriaght, 6, 5);
                 break;
              case 4:
                 return new RollScore(RollScoreType.PairSmallStriaght, 4, 3);
           }
           return new RollScore(RollScoreType.Pair, pair, (byte)(Array.LastIndexOf(diceCount, (byte)1) + 1));
        }
     }
     byte missingDie = (byte)Array.IndexOf(diceCount, (byte)0);
     switch(missingDie)
     {
        case 0:
           return new RollScore(RollScoreType.LargeStraight, 6, 5);
        case 1:
           return new RollScore(RollScoreType.SmallStright, 6, 5);
        case 4:
           return new RollScore(RollScoreType.SmallStright, 4, 3);
        case 5:
           return new RollScore(RollScoreType.LargeStraight, 5, 4);                  
        default:
           return new RollScore(RollScoreType.HighDie, 6, (byte)(Array.LastIndexOf(diceCount, (byte)1, 3) + 1));
     }
  }

驚いたことに、5ダイスの目で小さなストレートと大きなストレートの確率が等しいことを発見しました。本当!?

編集:修正; ペアを含む小さなストレートを含めると、小さなストレートの確率が大幅に上がることがわかります。

私がそれについて考えるとき、ペアと小さなストレートはおそらくペアを最高のダイとして使用し、ストレートの最大数を次に高いものとして使用する必要があります([両方が小さなストレートのペアである2つのロールを適切に比較するために)。もしそうなら、PairSmallStraightを処理するためのコードブロックを次のように置き換えます。

           switch (lowMissingDie)
           {
              case 0:
                 if (highMissingDie == 5)
                    return new RollScore(RollScoreType.PairSmallStriaght, pair, 5);
                 if (highMissingDie == 1)
                    return new RollScore(RollScoreType.PairSmallStriaght, pair, 6);
                 break;
              case 4:
                 return new RollScore(RollScoreType.PairSmallStriaght, pair, 4);
           }
于 2011-06-26T12:54:59.773 に答える
0

結果を探す方法についてはコメントしませんが、後で検索するために結果を保存する方法について説明します。

可能な組み合わせは 46656 しかなく、結果のハンドの強さを 1 バイトで格納できるため、この問題はポーカー ハンドの問題よりもはるかに簡単です。

インデックスとしてハンドで構成され、そのハンドの結果 (一部のハンドは複数の結果を持つことができます) に関連付けられたルックアップ テーブルを作成できます。各バイトは、すべてのハンド タイプをバイナリ表現として格納できます (short を使用しない場合)。

得られる各数値 (例: 66655 - フルハウス) は 6 進数 (1-6) の数値です。これを 10 進数に変換して、ルックアップ テーブルのインデックスを取得します。

約 46656 バイト (+ CPU アライメント) が必要で、CPU L2 キャッシュに収まります。実行する必要がある唯一の操作は基数の変換と、手の強さを抽出するためのバイナリ OR 操作であるため、速度は非常に高くなります。

あなたが見逃してしまうのは、ハンドの本当の強さです。例えば。66655 は 66644 よりも優れています。簡単に理解できます。結果を格納するには、より大きな型が必要になります:)

于 2011-06-26T11:21:58.547 に答える
0

いつでもLINQ集計クエリを実行して、同じカードの数を数えることができます。次のようなものになります (テストできません):

var query =  from card in hand
             group card by card into groupedCards
             select new { Card = groupedCards.Key, Count = groupedCards.Count() };

このようにして、ストレート (またはまったくない)、ペア、トリプルなどを扱っているかどうかを簡単に知ることができます。

私はLINQ専門家ではなく、現時点ではこのコードをテストすることはできません。そのため、このままコンパイルされるかどうかはわかりませんが、目前の問題に対処する方法について役立つか、アイデアが得られるかもしれません。

例えば:

  1. if count query = 5 : 空のハンド、フラッシュ、またはストレートを扱っています => 特定のフラッシュ/ストレート ロジックを実行します。

  2. if count query = 4 : 単一のペアを扱っています。

  3. if count query = 3 : ダブルペアまたはトリプルを扱っています => if max count =3 then triple

  4. if count query = 2 : フルハウス / ポーカーを扱っています。最大カウント = 4 の場合、ポーカー

于 2011-06-26T11:07:27.517 に答える