すぐにでも消えいりそうなプログラミング熱を絶やさない為、出来そうなヤツを総合的、俯瞰的に選考してみた結果、数あるトランプゲームの中から「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()
※コメント投稿者のブログIDはブログ作成者のみに通知されます