かめよこある記

~カメもタワシも~
To you who want to borrow the legs of a turtle

トランプで遊ぼう!「41」

2020-11-01 22:46:32 | もしもゲームがつくれたなら

 すぐにでも消えいりそうなプログラミング熱を絶やさない為、出来そうなヤツを総合的、俯瞰的に選考してみた結果、数あるトランプゲームの中から「41」に決定。
思いつくままに行き当たりばったりに組んでいたら、単純なルールのはずが、細かい決まり事もあったりで、途中こんがらがったりもしたけど、なんとか完成。
変数だと使用する関数ごとにグローバル宣言しなければならないので、すべてリストで管理するようにしてみた。いいかどうかはわからんけど。

【41の遊び方】 ※「夢中になる!トランプの本」主婦の友社刊に拠る。
ジョーカーをのぞく52枚を使用。親と子の2人でプレイ。
山札から手札を6枚ずつ配り、場札に一枚。
子からはじめ、場札の合計が1、11、21、31になった時、1チップもらえる。(41は2チップ)
場札の1枚目が1(A)なら親に1チップ。
合計が41を超えてはダメで、出せる手札がなければパス。(出せる札があるのにパスすることは出来ない)
この時、相手が先にパスしていなければ相手方に1チップ。
両者パスするか手札が無くなれば1ラウンド終了、ラウンドごとに親を交代。
4ラウンドで1ディール終了、チップが多いほうが勝ち。
それを4ディール繰り返してゲーム終了。勝ちディールの多いほうが勝ち。
Jは-1、Qは0、Kは直前の数字をコピー。(前のカードが7なら7に)
場札の最初の札がKの場合や更にKが続いた場合は、次に出した数字がKにコピーされる。
たとえば、最初からKが2枚続いた後に7を出せば合計は21に。
41の時にQ(0)を出してもOK。その後ならK(Qがコピーされるので0)を出してもよい。

【操作方法】
上の段がCOM、下の段がプレイヤーの手札で中段が場札。
ディール毎にランダムで親が決まり、ラウンドごとに親を交代。
手札をクリックして選択。パスはパス枠をクリック。
赤丸の中に表示されているのが場札の合計。何もコピーされてないKは0として計算。
各自のチップは手札の左側に表示。
ラウンド等の終了時は、「次へ」をクリック。

【リスト】 ※pythonです。インデントは必要分空けてください。
import tkinter
import random

FNT  = ["Time New Roman", 32]
FNT2 = ["Time Nwe Roman", 16]
C    = ["black", "red","white"]
SYM  = ["J", "Q", "K", "♠", "♣", "♦", "♥"]
MSG  = ["あなたの負けです",
        "引き分けです",
        "あなたの勝ちです"]
card = [] # 山札52枚 card[0~51]
for i in range(0, 13*4): card.append(i)
cd = [[0]*13 for i in range(2)] # 場札13枚 cd[0:表示用 1:計算用][0~12]
hd = [[[0] * 6 for i in range(2)] for j in range(2)] # 手札 6枚ずつ hd[0:表示用 1:計算用][0:COM 1:プレイヤー][0~5]

ct = [0]*17 # 0:山札用 1:場札用 2:COM用 3:プレイヤー用 4~5:チップ 6~7:パス 8:場札トータル 9:ターン 10:親 11:ディール 12:ラウンド 13~15:スコア 16:ポーズ
ct[11] = 1
ms = [ 0, 0, 0] # マウス[ x, y, クリック]

def ms_move(e): # マウス関係
    ms[0] = e.x
    ms[1] = e.y

def ms_click(e):
    ms[2] = 1

def ms_release(e):
    ms[2] = 0
      
def init_deal(): # ディール初期化
    for i in range(1+52*3): # カードをシャッフル
        a = random.randint(0,51)
        b = random.randint(0,51)
        card[a], card[b] = card[b], card[a]
    ct[12] = 1
    ct[ 0] = 0
    ct[10] = random.randint(0,1)
    ct[ 4] = 0
    ct[ 5] = 0

def init_round(): # ラウンド初期化
    for i in range(6):
        hd[0][(ct[10]+1) % 2][i] = card[ct[0] + i*2  ]
        hd[1][(ct[10]+1) % 2][i] = cvt(card[ct[0] + i*2])
        hd[0][ct[10]][i] = card[ct[0] + i*2+1]
        hd[1][ct[10]][i] = cvt(card[ct[0] + i*2+1])
    cd[0][0] = card[ct[0] + 12]
    cd[1][0] = cvt(card[ct[0] + 12])
    ct[8] = (cd[1][0] != 13) * cd[1][0]
    ct[0] += 13
    ct[1] = 0
    ct[9] = (ct[10] + 1) % 2
    ct[2] = 5
    ct[3] = 5
    ct[6] = 0
    ct[7] = 0
    ct[4 + ct[10]] += (cd[1][0] == 1)

def cvt(a): # 変換サブ
    b = 1 + (a % 13)
    if b > 10 and b < 13: b -= 12
    return b  

def total(n): # カード トータル計算
    s = hd[1][ct[9]][n]
    if s == 13:
        if cd[1][ct[1]] != 13: s = cd[1][ct[1]]
        else: s = 0
    t = s
    for j in range(1 + ct[1]):
        a = cd[1][j]
        if a == 13: a = s
        t += a
    return t

def com_pro(n): # com、プレイヤー共通処理
    ct[1] += 1
    cd[0][ct[1]] = hd[0][ct[9]][n]
    cd[1][ct[1]] = hd[1][ct[9]][n]    
    if cd[1][ct[1]] != 13:
        for i in range(ct[1] , 0, -1):
            if cd[1][i-1] == 13: cd[1][i-1] = cd[1][i]
    else:
        if cd[1][ct[1] - 1] != 13: cd[1][ct[1]] = cd[1][ct[1] - 1]
    if n < ct[2 + ct[9]]:
        for i in range(n, ct[2 + ct[9]]):
            hd[0][ct[9]][i] = hd[0][ct[9]][i + 1]
            hd[1][ct[9]][i] = hd[1][ct[9]][i + 1]            
    ct[2 + ct[9]] -= 1
    ct[6 + ct[9]] = (ct[2 + ct[9]] < 0)
    dsp_card()
    ct[9] = (ct[9] + 1) % 2
    
def dsp_card(): # カード表示
    cvs.delete("all")
    cvs.create_rectangle(495, 275, 585, 325, outline=C[0], width=2)
    cvs.create_text(540, 300, text="パス", fill=C[0], font=FNT)
    if ct[16] == 1:
        cvs.create_rectangle(495, 335, 585, 385, outline=C[0], width=2)
        cvs.create_text(540, 360, text="次へ", fill=C[0], font=FNT)
    if ct[6] == 1 and ct[2] >=0: cvs.create_text(540, 60, text="パス", fill=C[0], font=FNT)
    for i in range(2):
        if ct[10] == i: cvs.create_text(35,40+i*240,text="親" ,fill=C[0], font=FNT)
        cvs.create_text(35,80+i*240,text="{:02}".format(ct[4 + i]),fill=C[0],font=FNT)       
    for j in range(1 + ct[2]):
        dsp_sub(0,j, ct[16])
    for j in range(1 + ct[3]):
        dsp_sub(1, j, 1)               
    for i in range(0, 1 + ct[1]):
        a, b, c =  sym_sub(cd[0][i])
        e = i % 2
        cvs.create_rectangle(515-i*40, 120+e*40, 515-i*40+50, 200+e*40,fill=C[2], outline=C[0], width=2)
        cvs.create_text(515-i*40+25,140+e*40,text=SYM[3+a],fill=C[c], font=FNT)
        cvs.create_text(515-i*40+25,175+e*40,text=b,fill=C[c], font=FNT)
    cvs.create_oval(530, 215, 590, 265, outline=C[1], width=4)
    cvs.create_text(560, 240, text="{:02}".format(ct[8]), fill=C[0], font=FNT)
    T = "ディール {} ラウンド {} {:02}勝 {:02}敗 {:02}分".format(ct[11], ct[12], ct[15], ct[13], ct[14])
    cvs.create_text(300, 360, text = T, fill=C[0], font=FNT2)
    cvs.update()  

def dsp_sub(n, m, o): # 表示サブ
    cvs.create_rectangle(75+m*60, 20+n*240, 75+m*60+50, 100+n*240,fill="white", outline=C[0], width=2)
    if o == 1:
        a, b, c = sym_sub(hd[0][n][m])
        cvs.create_text(75+m*60+25,20+n*240+20,text=SYM[3+a],fill=C[c], font=FNT)
        cvs.create_text(75+m*60+25,20+n*240+55,text=b,fill=C[c], font=FNT)

def sym_sub(l): # 表示サブ2
    a = int(l / 13)
    d = 1 + (l % 13)
    b = str(d)
    c = int(a / 2)
    if d > 10: b = SYM[d-11]
    elif d ==1 : b = "A"
    return a, b, c

def com(): # com処理
    if ct[2] >= 0:
        ct[6] = 0
        c = -1
        for i in range(1 + ct[2]):
            t = total(i)
            if t < 42:
                b = (t % 10)
                if b == 1:
                    c = i
                    ct[4] += 1 + (t == 41)
                    break
                if c < 0: c = i
                else:
                    if random.randint(1,10) < 5: c = i
        if c < 0:
            ct[6] = 1
            ct[5] += (ct[7] == 0)
            ct[9] = 1
            dsp_card()
            return    
        t = total(c)
        ct[8] = t   
        com_pro(c)
    else: ct[9] = 1

def player(): # プレイヤー処理
    if ct[3] >= 0:
        ct[7] = 0
        if ms[2] == 1:
            if ms[0] > 75 and ms[0] < 75+(ct[3] + 1)*60 and ms[1] > 260 and ms[1] < 340:
                x = (ms[0] - 75) % 60
                if x < 50:
                    x = int((ms[0] - 75) / 60)
                    t = total(x)              
                    if t < 42:
                        ct[8] = t
                        b = (t % 10)
                        if b == 1: ct[5] += 1 + (t == 41)
                        com_pro(x)
            elif ms[0] > 495 and ms[0] < 585 and ms[1] > 275 and ms[1] < 325:
                f = 1
                for i in range(1 + ct[3]):
                    t = total(i)
                if t < 42: f = 0
                if f == 1:    
                    ct[7] = 1
                    ct[4] += (ct[6] == 0)
                    ct[9] = 0
    else: ct[9] = 0
        
def game_main(): # メイン処理
    if ct[16] == 1:
        if ms[0] > 495 and ms[0] < 585 and ms[1] > 335 and ms[1] < 385 and ms[2] ==1:
            ct[16] = 0
            dsp_card()       
    else:      
        if ct[6] == 1 and ct[7] == 1:     
            ct[16] = 1
            if ct[12] == 4:
                s = (ct[5] > ct[4]) - (ct[5] < ct[4])
                ct[14 + s] += 1
                dsp_card()
                if ct[11] == 4:
                    s = (ct[15] > ct[13]) - (ct[15] < ct[13])
                    cvs.create_text(300, 380, text = "ゲーム終了 " + MSG[1 + s], fill=C[0], font=FNT2)
                    ct[11] = 1
                    ct[13] = 0
                    ct[14] = 0
                    ct[15] = 0
                else:
                    dsp_card()
                    cvs.create_text(300, 380, text = str(ct[11]) + " ディール終了", fill=C[0], font=FNT2)
                    ct[11] += 1
                init_deal()
                init_round()
            else:
                dsp_card()
                cvs.create_text(300, 380, text = str(ct[12]) + " ラウンド終了" , fill=C[0], font=FNT2)
                ct[12] += 1
                ct[10] = (ct[10] + 1) % 2
                init_round()
        else:    
            if ct[9] == 0: com()
            elif ct[9] == 1: player()
    root.after(50, game_main)
    
root = tkinter.Tk() # 初期設定
root.title("41")
root.resizable(False, False)
root.bind("Motion", ms_move)
root.bind("ButtonPress", ms_click)
root.bind("ButtonRelease", ms_release)
cvs = tkinter.Canvas(root, width=600, height=400, bg="white")
cvs.pack()
init_deal()
init_round()
dsp_card()
game_main()


ゲーム制作ランキング


コメント    この記事についてブログを書く
  • Twitterでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 源氏の君と「私」 | トップ | グーグルアースを歩いていた »
最新の画像もっと見る

コメントを投稿

もしもゲームがつくれたなら」カテゴリの最新記事