【Python講座】Pythonで作るパズルゲーム#4_揃っただんごを消してみよう

こんにちは、koheiです。
Pythonでパズルゲームを作ろうの第4回目です。
動画解説もあります。記事と合わせてどうぞ!
今回のゴール
今回は、3つ以上揃っただんごを消すという処理を作っていきます。
練習素材は以下からダウンロードできますので、ぜひダウンロードしてやってみてください。
だんごを消す処理のイメージ
だんごを消す処理のイメージです。以下の流れで制御していきます。
1.判定用リストを用意し、dangoリストを判定用リスト(checkリスト)にコピーする

2.判定用リスト(checkリスト)を使って、縦、横、斜めにだんごが3つ並んでいるかをチェックし、並んでいる場合は、dangoリストの値を串(値5)に変更する

それを全マスチェックしていく

3.dangoリストの値をチェックし、串(値5)だったら、空(値0)に変更する。

なぜ、判定用リスト(checkリスト)をわざわざ用意するかというと、そのままdangoリストをチェックして値を変更していくと、すでに3つ揃っている箇所は串の値5に変わっているので、4つ以上並んでいる場合の判定できなくなってしまうからです。
実装
それでは、先程のイメージに沿って、だんごが揃ったかどうかの判定処理を作っていきましょう。
pygame_dango_game.pyに以下を実装しましょう。(黄色い部分)
import pygame
import random
import sys
dango = [] #マス目の配列
check = [] #判定用の配列
for i in range(10):
dango.append([0,0,0,0,0,0,0,0])
check.append([0,0,0,0,0,0,0,0])
#団子を表示する関数
def disp_dango():
screen.blit(bg,[0,0]) #背景画像描画
for y in range(10):
for x in range(8):
if dango[y][x] > 0:
screen.blit(img_dango[dango[y][x]],[x*72+20, y*72+20])
# だんごを落下させる関数
def drop_dango():
for y in range(8,-1,-1):
for x in range(8):
if dango[y][x] !=0 and dango[y+1][x] == 0:
dango[y+1][x] = dango[y][x]
dango[y][x] = 0
# 団子が揃ったかをチェックする関数
def check_dango():
for y in range(10):
for x in range(8):
check[y][x] = dango[y][x] # 盤面をcheckにコピーする
for y in range(1,9):
for x in range(8):
if check[y][x] > 0:
if check[y-1][x] == check[y][x] and check[y+1][x] == check[y][x]:
dango[y-1][x] = 5
dango[y][x] = 5
dango[y+1][x] = 5
for y in range(10):
for x in range(1,7):
if check[y][x] > 0:
if check[y][x-1] == check[y][x] and check[y][x+1] == check[y][x]:
dango[y][x-1] = 5
dango[y][x] = 5
dango[y][x+1] = 5
for y in range(1,9):
for x in range(1,7):
if check[y][x] > 0:
if check[y-1][x-1] == check[y][x] and check[y+1][x+1] == check[y][x]:
dango[y-1][x-1] = 5
dango[y][x] = 5
dango[y+1][x+1] = 5
if check[y+1][x-1] == check[y][x] and check[y-1][x+1] == check[y][x]:
dango[y+1][x-1] = 5
dango[y][x] = 5
dango[y-1][x+1] = 5
5-9行目は、dangoリストと判定用リスト(check)の初期化処理です。
前回まで暫定で設定していたdangoリストをオール0で初期化しています。appendは、リストの末尾に要素を追加するメソッドです。
29行目からのcheck_dango()処理では、だんごが縦、横、斜めに3つ並んでいるかをチェックする処理です。
34〜40行目が、縦に3つ並んでいるかをチェックする処理、
42〜48行目が、横に3つ並んでいるかをチェックする処理、
50〜61行目が、斜めに3つ並んでいるかチェックする処理となります。3つ揃っていたら、dangoリストの値を串(値:5)に変更しています。
次に、揃っただんごを消す処理を実装しましょう。
以下の関数を追加しましょう。
# 揃っただんごを消す関数
def delete_dango():
num = 0
for y in range(10):
for x in range(8):
if dango[y][x] == 5:
dango[y][x] = 0
num = num + 1
return num
dangoリストの中身をチェックしていき、串の値:5の場合、空白:0に変更します。
また、空白に変更した数を戻り値で返します。
これは、後ほどスコア計算で使用するため、戻り値で消した数を返すようにしています。
さて、これらの関数をメインモジュールからコールするようにします。
以下を追加します。
#ゲームメイン処理
def main():
cursor_x=0
cursor_y=0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
mouse_x,mouse_y = pygame.mouse.get_pos() #マウス位置
mouse_click = pygame.mouse.get_pressed() #マウスクリック
mouse_c = mouse_click[0] #マウス左クリック状態を設定
drop_dango() # だんご落下させる
# マウスが盤上内であれば
if 20 <= mouse_x and mouse_x < 20+72*8 and 20 <= mouse_y and mouse_y < 20+72*10:
cursor_x = int((mouse_x-20)/72)
cursor_y = int((mouse_y-20)/72)
if mouse_c == True and dango[cursor_y][cursor_x] == 0:
mouse_c = False
dango[cursor_y][cursor_x] = random.randint(1,4)
check_dango() #だんごが揃ったか判定
delete_dango() #揃っただんごを消す
disp_dango() # だんご表示
disp_score() # スコア表示
screen.blit(cursor,[cursor_x*72+20,cursor_y*72+20]) #カーソル表示
pygame.display.update()
clock.tick(10)
さて、ここまでできたら、ファイルを保存して実行してみましょう。
3つ以上揃っただんごが消えていけば、OKです。
スコア表示処理
続いて、だんごを消した数からスコアを計算し、表示させてみましょう。
まずは、スコア用の変数、文字表示用の色定義を用意します。
変数は、複数の関数で参照するため、グローバル変数で定義します。
※グローバス変数・・・関数の外部で宣言した変数。グローバル変数の値はプログラムが終了するまで値が保持される。
関数内でグローバル変数の値を変更するには、その変数をglobal宣言する必要がある。
以下を実装します。
import pygame import random import sys # 色定義 BLUE = (0,0,255) # 変数 score = 0 #スコア用変数 hisc = 1000 #ハイスコアを保持する変数
初期化関連の処理内で、pygameのフォント指定処理を追加しておきます。
if __name__ == '__main__':
#初期化、画像ロード処理など
pygame.init()
pygame.display.set_caption("だんごパズル(pygame ver)")
screen = pygame.display.set_mode((912,768))
font = pygame.font.Font(None,60)
clock = pygame.time.Clock()
bg = pygame.image.load("dango_back.png") #背景画像をロード
cursor = pygame.image.load("cursor.png") #カーソル画像をロード
img_dango = [ #だんご画像をロード
None,
pygame.image.load("dango1.png"),
pygame.image.load("dango2.png"),
pygame.image.load("dango3.png"),
pygame.image.load("dango4.png"),
pygame.image.load("dango_kushi.png")
]
#ゲームメイン処理
main()
スコア表示用の関数、メインモジュール等に以下を実装します。
# スコア表示
def disp_score():
global score,hisc
txt = font.render(str(score),True,BLUE)
screen.blit(txt,[650,300])
txt2 = font.render(str(hisc),True,BLUE)
screen.blit(txt2,[650,400])
#ゲームメイン処理
def main():
cursor_x=0
cursor_y=0
global score,hisc
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
mouse_x,mouse_y = pygame.mouse.get_pos() #マウス位置
mouse_click = pygame.mouse.get_pressed() #マウスクリック
mouse_c = mouse_click[0] #マウス左クリック状態を設定
drop_dango() # だんご落下させる
# マウスが盤上内であれば
if 20 <= mouse_x and mouse_x < 20+72*8 and 20 <= mouse_y and mouse_y < 20+72*10:
cursor_x = int((mouse_x-20)/72)
cursor_y = int((mouse_y-20)/72)
if mouse_c == True and dango[cursor_y][cursor_x] == 0:
mouse_c = False
dango[cursor_y][cursor_x] = random.randint(1,4)
check_dango() #だんごが揃ったか判定
sc = delete_dango() #揃っただんごを消す
score = score + sc*10
if score > hisc:
hisc = score
disp_dango() # だんご表示
disp_score() # スコア表示
screen.blit(cursor,[cursor_x*72+20,cursor_y*72+20]) #カーソル表示
pygame.display.update()
clock.tick(10)
disp_score()は、スコア表示する関数です。
計算したスコアを文字列に変換し、render()命令で表示文字列を作ります。
blit()命令で画面に文字列を貼り付けます。座標は、スコア表示用の座標を指定しています。
メインモジュールでは、スコアを計算します。
delete_dango()で消しただんごの数をscへ設定し、10倍した値をscore変数に格納します。
33行目の判定は、ハイスコア(hisc)を超えたら、ハイスコアを更新する処理です。
ここまでできたら、ファイルを保存してpython実行してみましょう。
揃っただんごが消えて、スコアが加算されていけばOKです。
最後に
今回は、揃っただんごを消して、スコアを計算する処理を作ってみました。
だんだんゲームらしくなってきました。
次は、ゲームのタイトル画面やゲームオーバー、効果音などを追加してゲームとして完成させたいと思います。
それでは!

