カード・ゲームの制作 VB6
 (4) 役の判定 前へ 目次へ 次へ 

 役の判定は、ゲームの勝敗を決めるときに必要になるが、ほかに、プレーヤー以外がもう一枚引くかどうかを判断するのにも使用する。
 ここでは、役判定の処理をプログラムする。

 1. 役判定

 持ち札は(手札)は、次のとおりである。

  配列 オブジェクト
Tefuda(0) 〜 Tefuda(2) picCard(0) 〜 picCard(2)
場1 Tefuda(3) 〜 Tefuda(5) picCard(3) 〜 picCard(5)
場2 Tefuda(6) 〜 Tefuda(8) picCard(6) 〜 picCard(8)
場3 Tefuda(9) 〜 Tefuda(11) picCard(9) 〜 picCard(11)
場4 Tefuda(12) 〜 Tefuda(14) picCard(12) 〜 picCard(14)

 配列の最初の数字(0,3,6,9,12)のどれかを引数として渡すと、役の値を返却するファンクション(関数)プロシージャHyoukaを作成する。
 例えば、引数として3を渡すと、場1(Tefuda(3) 〜 Tefuda(5))のカードについて役の値が返却される。

◆ 役の返却値の検討

儲け 関数の返却値 リーチ
クッピン(親のみの役)…Aと9 最強 999 ///
シッピン(子のみの役)…Aと4 3倍返し 998 ///
嵐…3枚とも同じ数字(A,3,5,10) 10倍返し 888 800+合計
嵐…3枚とも同じ数字(2,4,6,7,8,9) 5倍返し 777 700+合計
順子(シュンツ)…同じマークの連番 5倍返し 555 500+合計
合計の1の位 2倍返し 9,8,7,6,5,4,3,2,1,0 ///

 リーチの”合計”は1の位の合計のこと。


 2. 役判定の処理

 「新しいプロジェクト」を開いて、役判定の処理をテストするプログラムを作成する。
 作成後に正しく役の判定が行われるかをテストする必要があるので別のプロジェクトとして作成する。(テスト終了後に役判定の処理(プロシージャ)を本来のプロジェクトにコピー&ペーストで追加することにする。)

 判定すべきカードは配列Tefuda(グローバル変数)に格納していたので、ここでも同じようにする。配列Tefudaに格納されているカードの番号は0(スペードのA)から順に割り当てられている。

 *カード番号の一覧
マーク/数字 1 2 3 4 5 6 7 8 9 10 J Q K
スペード 0 1 2 3 4 5 6 7 8 9 - - -
クラブ 13 14 15 16 17 18 19 20 21 22 - - -
ハート 26 27 28 29 30 31 32 33 34 35 - - -
ダイヤ 39 40 41 42 43 44 45 46 47 48 - - -

フォームのプロパティ
Height 4500
Width 6000

 フォームに次のオブジェクトを配置する。
  テキストボックス ・・・ Text1, Text2
  コマンドボタン ・・・ Command1, Command2
  ラベル ・・・ Label1
 各オブジェクトの大きさなどは適当に設定する。

Text1のプロパティ
MultiLine True
ScrollBars 2 - 垂直


 [2枚テスト]ボタンをクリックすると、カード2枚すべての組合せについて判定をし、[3枚テスト]をクリックすると、Text2に入力された番号を1枚目として2,3枚目のすべての組合せについて判定をする。結果はText1に表示される。

・プログラムリスト(役判定の処理)

Dim Tefuda(3) As Integer    'グローバル変数
 
Private Function Hyouka(cnum As Integer) As Integer
'役の評価
'引数 cnum … 持ち札の番号(配列の添字:0=親、3,6,9,12=場)
'グローバル Tefuda() … カード番号(0〜52、0=スペードA)
'                   倍率  返却値1  返却値2
' クッピン(親のみの役)…Aと9     最強   999   ///
' シッピン(子のみの役)…Aと4     3倍返し  998   ///
' 嵐…3枚とも同じ数字(A,3,5,10)    10倍返し  888   800
' 嵐…3枚とも同じ数字(2,4,6,7,8,9)  5倍返し  777   700
' 順子(シュンツ)…同じマークの連番   5倍返し  555   500
' 合計の1の位              2倍返し 9,8,7,6,5,4,3,2,1,0  ///

 
    Dim tf(3) As Integer    '持ち札
    Dim cm(3) As Integer, cn(3) As Integer    'カードのマークcmと数字cn
    Dim goukei As Integer
    Dim n As Integer, n2 As Integer, wk As Integer
 
    tf(1) = Tefuda(cnum)      '※1 カード番号コピー 1枚目
    tf(2) = Tefuda(cnum + 1)  'カード番号コピー 2枚目
    tf(3) = Tefuda(cnum + 2)  'カード番号コピー 3枚目
    For n = 1 To 2    '※2 カード番号のソート(昇順)
        For n2 = n + 1 To 3
            If tf(n) > tf(n2) And tf(n) <> -1 And tf(n2) <> -1 Then
                wk = tf(n)
                tf(n) = tf(n2)
                tf(n2) = wk
            End If
        Next n2
    Next n
    For n = 1 To 3    '※3 マークと数字に分解
        If tf(n) = -1 Then
            cm(n) = -1      'マーク
            cn(n) = -1     '数字
        Else
            CardMark tf(n), cm(n), cn(n)    'マークと数字
        End If
    Next n
 
    '※4 役判定
    If cnum = 0 Then    'クッピン(親のみの役)…Aと9 最強 999
        If cn(1) = 1 And cn(2) = 9 And cn(3) = -1 Then
            Hyouka = 999
            Exit Function
        End If
    Else    'シッピン(子のみの役)…Aと4 3倍返し 998
        If cn(1) = 1 And cn(2) = 4 And cn(3) = -1 Then
            Hyouka = 998
            Exit Function
        End If
    End If
    If cn(1) = cn(2) And cn(2) = cn(3) Then    '嵐
        If cn(1) = 1 Or cn(1) = 3 Or cn(1) = 5 Or cn(1) = 10 Then
            Hyouka = 888    'A,3,5,10-10倍返し 888
            Exit Function
        Else    '2,4,6,7,8,9-5倍返し 777
            Hyouka = 777
            Exit Function
        End If
    ElseIf cn(1) = cn(2) And cn(3) = -1 Then    '嵐リーチ
        If cn(1) = 1 Or cn(1) = 3 Or cn(1) = 5 Or cn(1) = 10 Then
            Hyouka = 800    'A,3,5,10-10倍返し 800
        Else    '2,4,6,7,8,9-5倍返し 700
            Hyouka = 700
        End If
    ElseIf cm(1) = cm(2) And cm(2) = cm(3) Then    '順子(シュンツ)
        If cn(1) = cn(2) - 1 And cn(1) = cn(3) - 2 Then
            Hyouka = 555    '5倍返し 555
            Exit Function
        End If
    ElseIf cm(1) = cm(2) And cm(3) = -1 Then    '順子(シュンツ)リーチ
        If cn(1) = cn(2) - 1 Then
            Hyouka = 500    '5倍返し 500
        End If
    End If
    If cn(3) = -1 Then
        goukei = (cn(1) + cn(2)) Mod 10    '合計の1の位-2倍返し 9,8,7,6,5,4,3,2,1,0 ///
    Else
        goukei = (cn(1) + cn(2) + cn(3)) Mod 10 '合計の1の位-2倍返し 9,8,7,6,5,4,3,2,1,0 ///
    End If
    Hyouka = Hyouka + goukei
End Function

※1 カード番号はソートして順番が変わってしまうのでグローバルのTefudaに影響がないように配列tfにコピーしている。
※2 最もシンプルなソートのアルゴリズムである。
※3 カード番号を13で割り算し、その商がカードのマーク、その余りに1を加算したものがカードの数字となる。
※4 役の判定処理。カード番号のソート後に行う。
 ・クッピンとシッピン・・・カード2枚(cn(3)が-1)である。 cn(1)=1 かつ cn(2)=9シッピンは 4)である。
 ・嵐・・・カード3枚(cn(1),cn(2),cn(3))とも同じ数字である。 リーチはcn(3)が-1である。
 ・順子・・・カード3枚(cm(1),cm(2),cm(3))とも同じマークであり、かつ、連番である。 リーチはcm(3)が-1である。
 ・その他・・・カードの数字をすべて加算した1の位が得点となる。
 カードがないときは配列cn,cmともに-1であるからどちらで判定しても良い。

・プログラムリスト(2枚テストの処理)

Private Sub Command1_Click()
    Dim cnum(40) As Integer    'カード番号(使用分)格納
    Dim n As Integer, cn As Integer
    Dim n1 As Integer, n2 As Integer, n3 As Integer, rr As Integer
 
    cn = 1    '※1 使用するカード番号の設定
    For n = 1 To 10
        cnum(cn) = n - 1
        cn = cn + 1
    Next n
    For n = 14 To 23
        cnum(cn) = n - 1
        cn = cn + 1
    Next n
    For n = 27 To 36
        cnum(cn) = n - 1
        cn = cn + 1
    Next n
    For n = 40 To 49
        cnum(cn) = n - 1
        cn = cn + 1
    Next n
 
    Text1.Text = ""
    For n1 = 1 To 40 - 1    '※2 役判定テスト
        For n2 = n1 + 1 To 40
            DoEvents
            Tefuda(1) = cnum(n1)    '1枚目
            Tefuda(2) = cnum(n2)    '2枚目
            Tefuda(3) = -1    '3枚目 なし
            rr = Hyouka(1)    '役判定処理
            kekka rr
        Next n2
    Next n1
    Text1.Text = Text1.Text & "END"
End Sub

※1 使用するカード40枚のカード番号を配列cnumに順番に記憶させる。
※2 配列(グローバル)Tefudaにカード番号をセットして役判定処理Hyoukaを呼び出す。
  テストするカードは1枚目のカード番号と1枚目のカード番号以降すべてのカード番号との組合せについて調べる。
  Hyoukaプロシージャの引数に1を指定しているので、Tefuda(1)〜Tefuda(3)について判定する。実際には親のカードを調べるときの引数である。

・プログラムリスト(3枚テストの処理)

Private Sub Command2_Click()
    Dim cnum(40) As Integer    'カード番号(使用分)
    Dim n As Integer, cn As Integer
    Dim n1 As Integer, n2 As Integer, n3 As Integer, rr As Integer
 
    cn = 1    '※1 使用するカード番号の設定
    For n = 1 To 10
        cnum(cn) = n - 1
        cn = cn + 1
    Next n
    For n = 14 To 23
        cnum(cn) = n - 1
        cn = cn + 1
    Next n
    For n = 27 To 36
        cnum(cn) = n - 1
        cn = cn + 1
    Next n
    For n = 40 To 49
        cnum(cn) = n - 1
        cn = cn + 1
    Next n
 
    Text1.Text = ""
    n1 = Val(Text2.Text)    '※2 役判定テスト
    For n2 = n1 + 1 To 40 - 1
        For n3 = n2 + 1 To 40
            DoEvents
            Tefuda(1) = cnum(n1)    '1枚目
            Tefuda(2) = cnum(n2)    '2枚目
            Tefuda(3) = cnum(n3)    '3枚目
            rr = Hyouka(1)    '役判定処理
            kekka rr
        Next n3
    Next n2
    Text1.Text = Text1.Text & "END"
End Sub

※1、※2とも2枚テストの処理と同じである。

・プログラムリスト(結果表示)

Private Sub kekka(rr As Integer)
    Dim x1 As Integer, msg As String
 
    msg = ""
    For n = 1 To 3    '※1 マークと数字に分解
        x1 = Int(Tefuda(cnum + n) / 13)    'マーク
        If x1 = 0 Then    'スペード
            msg = msg & "S"
        ElseIf x1 = 1 Then    'クラブ
            msg = msg & "C"
        ElseIf x1 = 2 Then    'ハート
            msg = msg & "H"
        ElseIf x1 = 3 Then    'ダイヤ
            msg = msg & "D"
        Else
            msg = msg & " "
        End If
        msg = msg & Str((Tefuda(cnum + n) Mod 13) + 1)    '数字
        msg = msg & " "
    Next n
 
'                           倍率  返却値1  返却値2
' クッピン(親のみの役)…Aと9        最強    999   ///
' シッピン(子のみの役)…Aと4        3倍返し  998   ///
' 嵐…3枚とも同じ数字(A,3,5,10)    10倍返し 888   800
' 嵐…3枚とも同じ数字(2,4,6,7,8,9) 5倍返し  777   700
' 順子(シュンツ)…同じマークの連番     5倍返し  555   500
' 合計の1の位                  2倍返し 9,8,7,6,5,4,3,2,1,0  ///

    '※2 役判定
    If rr = 999 Then
        msg = msg & "クッピン"
    ElseIf rr = 998 Then
        msg = msg & "シッピン"
    ElseIf rr = 888 Then
        msg = msg & "嵐10倍"
    ElseIf rr = 777 Then
        msg = msg & "嵐5倍"
    ElseIf rr = 555 Then
        msg = msg & "順子"
    ElseIf rr >= 800 Then
        msg = msg & "嵐10倍リーチ"
    ElseIf rr >= 700 Then
        msg = msg & "嵐5倍リーチ"
    ElseIf rr >= 500 Then
        msg = msg & "順子リーチ"
    Else
        msg = msg & "なし" & Str(rr)  '役なしのメッセージを省略するときコメントにする
        'msg = ""            '役なしのメッセージを省略するときコメントを削除
    End If
    If msg <> "" Then
        Text1.Text = Text1.Text & msg & vbCrLf    '結果をText1に表示
    End If
    Text1.SelStart = Len(Text1.Text)
End Sub

※1 マークを記号(S,C,H,D)に変換している。
※2 役判定(Hyoukaプロシージャ)の結果をメッセージに変換している。

・プログラムリスト(初期設定)

Private Sub Form_Load()
    Text1.Text = ""
    Text2.Text = "1"
End Sub

 実行して、おかしな判定がないか自分の目で確かめる。
 40枚から2枚を取り出す組合せなので、780通りある。3枚テストは最大741通りである。
 テスト用のプログラムは適当な名前で保存しておく。

 この後、カードゲームで必要になるのはHyoukaプロシージャだけである。


 3. プロシージャの移動

 Hyoukaプロシージャ(Private Function Hyouka(cnum As Integer) As Integer 〜 End Function)までをゲームプログラムにコピーする。
 注意 宣言の「Dim Tefuda(3) As Integer    'グローバル変数」の行は不要である。

   手順

  1. 必要なHyoukaプロシージャの部分を選択してコピーする。
    Hyoukaプロシージャの部分をドラッグして範囲選択する。次に、メニューバーから[編集(E)]→[コピー(C)]を選択する。
  2. カードゲームkabuのプログラムを読み込み、プログラムを表示する。
  3. プログラムリストの最後にHyoukaプロシージャを貼り付ける。
    カーソルをプログラムリストの最後に移動する。次に、メニューバーから[編集(E)]→[貼り付け(P)]を選択する。


 (4) 役の判定 前へ 目次へ 次へ 
Copyright © 2004 Hiroshi Masuda 

 

 

inserted by FC2 system