2117940 ランダム
 ホーム | 日記 | プロフィール 【フォローする】 【ログイン】

くぴんのブログ

くぴんのブログ

【毎日開催】
15記事にいいね!で1ポイント
10秒滞在
いいね! --/--
おめでとうございます!
ミッションを達成しました。
※「ポイントを獲得する」ボタンを押すと広告が表示されます。
x

PR

プロフィール

くぴん74

くぴん74

フリーページ

カレンダー

カテゴリ

バックナンバー

お気に入りブログ

DOW 38239.66 +153.8… New! どらりん0206さん

主力株候補のアイデ… New! みきまるファンドさん

楽天ラッキーくじ更… じゃっかすさん

UV K5(8)が現在アリ… jashiさん

またしても訃報 Maryu21さん

ニューストピックス

キーワードサーチ

▼キーワード検索

2024年01月07日
XML
カテゴリ:プログラミング
pythonでテトリスを作ろうとするとどうなるのか、検索すると以下のサイトが見つかった。
https://kusakarism.info/?p=11314

python標準モジュールのtkinterを使用し、わずか140行ほどで書かれていて感動した。
リンク先の動画でも丁寧に説明されていて勉強になった。

コーディングのキーポイントは、横12、縦21のマス目の状態を空間とブロックに識別し、横の両端1列ずつと下端1列をブロックとして白で表示、その内側を空間として黒で表示することにある。
7種類のテトロミノ(T字やL字のブロック)が積み上がるとその場所はブロックとなり、テトロミノがブロックと当たると移動や回転ができないようになっている。
1列がすべてブロックとなると、その段を消去して、順次上のブロックが落ちるようになっている。
操作性もよくて、快適に遊べる。
コードをみると操作方法がわかるが、カーソルキーで左右と下への移動、スペースキーで回転になっている。

せっかくなので、Timerと次のブロックが表示されるように改変してみた。


-----以下コード、コピー&ペーストで動作したので、よかったらお試しください。
#################### Rough TETRIS ####################
# https://kusakarism.info/?p=11314
#
import tkinter as tk
import random
from tkinter import messagebox

SIZE = 30       #ブロックのサイズ
moveX = 4       #テトロミノ表示位置(横)
moveY = 0       #テトロミノ表示位置(縦)
type1 = random.randint(0, 6)        #テトロミノのタイプ
next1 = random.randint(0, 6)        #次のテトロミノ

timer = 800     #ゲームスピードコントロール
score = 0       #スコア

color = ["magenta", "blue", "cyan", "yellow", "orange", "red", "green", "black", "white"]

#テトロミノデータ
tetroT = [-1, 0, 0, 0, 1, 0, 0, 1]
tetroJ = [-1, 0, 0, 0, 1, 0, 1, 1]
tetroI = [-1, 0, 0, 0, 1, 0, 2, 0]
tetroO = [ 0, 0, 1, 0, 0, 1, 1, 1]
tetroL = [-1, 0, 0, 0, 1, 0,-1, 1]
tetroZ = [-1,-1, 0,-1, 0, 0, 1, 0]
tetroS = [ 0, 0, 1, 0, 0, 1,-1, 1]
tetro = [tetroT, tetroJ, tetroI, tetroO, tetroL, tetroZ, tetroS]

#フィールドデータ
field=[]
for y in range(22):
    sub=[]
    for x in range(12):
        if x==0 or x==11 or y==21:
            sub.append(8)
        else:
            sub.append(7)
    field.append(sub)
    
#落ちるテトロミノを表示する関数
def drawTetris():
    for i in range(4):
        x=(tetro[type1][i*2]+moveX)*SIZE
        y=(tetro[type1][i*2+1]+moveY)*SIZE
        can.create_rectangle(x, y, x+SIZE, y+SIZE, fill=color[type1])

#次のテトロミノを表示する関数
def nextTetro():
    can_next.delete("all")
    for i in range(4):
        x=(tetro[next1][i*2]+1)*SIZE
        y=(tetro[next1][i*2+1]+1)*SIZE
        can_next.create_rectangle(x, y, x+SIZE, y+SIZE, fill=color[next1])

#フィールドを表示する関数 1が壁、0が空間
def drawField():
    for i in range(21):
        for j in range(12):
            outLine=0 if color[field[i+1][j]]=="white" else 1
            can.create_rectangle(j*SIZE, i*SIZE, (j+1)*SIZE, (i+1)*SIZE, fill=color[field[i+1][j]], width=outLine)

#テトロミノを動かす関数
def keyPress(event):
    global moveX, moveY
    afterX=moveX
    afterY=moveY
    afterTetro=[]
    afterTetro.extend(tetro[type1])
    if event.keysym=="Right":
        afterX+=1
    elif event.keysym=="Left":
        afterX-=1
    elif event.keysym=="Down":
        afterY+=1
    elif event.keysym=="space":
        afterTetro.clear()
        for i in range(4):
            afterTetro.append(tetro[type1][i*2+1]*(-1))
            afterTetro.append(tetro[type1][i*2])
    judge(afterX, afterY, afterTetro)  #アタリ判定関数呼び出し

def judge(afterX, afterY, afterTetro): #アタリ判定をする関数
    global moveX, moveY
    result=True
    for i in range(4):
        x=afterTetro[i*2]+afterX
        y=afterTetro[i*2+1]+afterY
        if field[y+1][x]!=7:
            result=False
    if result==True:
        moveX=afterX
        moveY=afterY
        tetro[type1].clear()
        tetro[type1].extend(afterTetro)
    return result

def dropTetris():
    global moveX, moveY, type1, next1, timer
    afterTetro=[]
    afterTetro.extend(tetro[type1])
    result=judge(moveX, moveY+1, afterTetro)
    if result==False:
        for i in range(4):
            x=tetro[type1][i*2]+moveX
            y=tetro[type1][i*2+1]+moveY
            field[y+1][x]=type1
        deleteLine()
        type1=next1 #次のテトロミノを落とす
        next1=random.randint(0,6)
        #can_next.delete("all")
        moveX=4
        moveY=0
    can.after(timer, dropTetris)
    timer-=2
    if timer<140:
        timer=180

def deleteLine():
    global score
    for i in range(1, 21):
        if 7 not in field[i]:
            for j in range(i):
                for k in range(12):
                    field[i-j][k]=field[i-j-1][k]
            score+=800-timer
    for i in range(1, 11):
        if 7!=field[1][i]:
            messagebox.showinfo("information", "GAME OVER!")
            exit()

####################  ゲームループ  ####################    
win=tk.Tk()
win.geometry("340x760")
win.title("TETRIS")
can=tk.Canvas(win, width=12*SIZE, height=21*SIZE)
can.place(x=-10, y=130)
can_next=tk.Canvas(win, width=4*SIZE, height=4*SIZE, bg="black") #次のテトロミノ表示位置
can_next.place(x=110, y=0)

var=tk.StringVar()
lab_score = tk.Label(win, textvariable=var, fg="blue", bg="white", font=("", "12"))   #得点表示
lab_score.place(x=0, y=730)
var1=tk.StringVar()
lab_timer = tk.Label(win, textvariable=var1, fg="blue", bg="white", font=("", "12"))   #タイマー表示
lab_timer.place(x=200, y=730)
lab_next = tk.Label(win, text="Next", fg="black", bg="white", font=("", "15"))   #Next
lab_next.place(x=50, y=50)

win.bind("<Any KeyPress>", keyPress)

def gameLoop():
    can.delete("all")
    var.set(f"score: {score}")
    var1.set(f"timer: {timer}")
    drawField()
    drawTetris()
    nextTetro()
    can.after(10, gameLoop)

gameLoop()
dropTetris()

win.mainloop()
-----ここまで


にほんブログ村 サラリーマン日記ブログ 戦うサラリーマンへ
にほんブログ村





お気に入りの記事を「いいね!」で応援しよう

最終更新日  2024年01月08日 13時13分22秒
コメント(0) | コメントを書く
[プログラミング] カテゴリの最新記事



© Rakuten Group, Inc.