2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

プログラミング上達講座2:テトリスのデータ構造を考える

Last updated at Posted at 2020-07-19

プログラミング上達講座の2回目です。

テトリスを題材にしてプログラムを考えてみましょう。

解説動画はこちら

表示されなかったらすみません

テトリスのデータ構造を考える

テトリスは4つのブロックで構成されたテトリミノ
フィールドに並べていくパズルゲームです。

このようなパズルゲームは
プログラミングの題材には打って付け!!

早速考えてみましょう。

1.テトリスゲームの素材を描画してみよう

1.1フィールドのデータ化

盤面(10 x 20マス)のフィールドと
上方以外を囲むブロック下記のような
フィールドをデータ化してみよう。

■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■□□□□□□□□□□■
■■■■■■■■■■■■

ヒント:

白黒のマスを1つずつ表示させるのは面倒臭いので
繰り返しを用いてみよう。

全体では12マスかける21行となる。

1.1回答

単純に上記になるようにデータを作成して出力するだけ。
データをひとまとめにしておくと再利用しやすくなります。

縦横の揃ったデータはリスト型を用いると
表現しやすく管理しやすくなります。

リストの掛け算は要素の繰り返し足し算は要素の連結となります。

data = [[''] + ['']*10 + ['']]*20 + [['']*12]

for y in data:
    print(''.join(y))

この場合は文字としてデータを出力しますが

パズルゲームの場合文字列でデータを格納すると
あとあと面倒い事もあるので数値で考えるケースが多いです。


data = [[1] + [0]*10 + [1]]*20 + [[1]*12]

for y in data:
    for x in y:
        print('' if x==1 else '',end='')
    print()

■なら1
□なら0としてデータを格納して出力時に変換します。

これで結果は一緒になります。

1.2テトリミノのデータ化

テトリミノ(7つ)
□■□□ □■□□ □■□□ □□■□ □■□□ □□■□ □□□□
□■□□ □■■□ □■□□ □□■□ □■■□ □■■□ □■■□
□■□□ □■□□ □■■□ □■■□ □□■□ □■□□ □■■□
□■□□ □□□□ □□□□ □□□□ □□□□ □□□□ □□□□

上記のような7種類のテトリミノをデータ化してみよう

1.2回答

こちらもゲームで用いる際には数値や文字を値とするリスト型のような
縦横の個数が決まったデータ型を用いると表現しやすくなります。

7つのテトリミノは独立して考え回転などを考慮すると
縦横4x4マスのリスト型で定義するのが再利用しやすい形でしょう。


line = [[0,1,0,0],[0,1,0,0],[0,1,0,0],[0,1,0,0]]
tblo = [[0,1,0,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]]
lr   = [[0,1,0,0],[0,1,0,0],[0,1,1,0],[0,0,0,0]]
ll   = [[0,0,1,0],[0,0,1,0],[0,1,1,0],[0,0,0,0]]
hr   = [[0,1,0,0],[0,1,1,0],[0,0,1,0],[0,0,0,0]]
hl   = [[0,0,1,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]]
sq   = [[0,0,0,0],[0,1,1,0],[0,1,1,0],[0,0,0,0]]

t_minos = [line,tblo,lr,ll,hr,hl,sq]

for mino in t_minos:
    for y in mino:
        for x in y:
            print('' if x==1 else '',end='')
        print()
    print()

□■□□
□■□□
□■□□
□■□□

□■□□
□■■□
□■□□
□□□□

□■□□
□■□□
□■■□
□□□□

□□■□
□□■□
□■■□
□□□□

□■□□
□■■□
□□■□
□□□□

□□■□
□■■□
□■□□
□□□□

□□□□
□■■□
□■■□
□□□□

2.テトリミノを回転させる関数を作ってみよう

先ほど作ったテトリミノのデータを使って
90度ずつ回転を行う関数rotateを作成しよう

def rotate(data , 角度):
    処理
    return data

□■□□
□■■□
□■□□
□□□□

これを90度回転させると

□□□□
□■■■
□□■□
□□□□

2.回答

まずテトリミノのデータを用意します。

data = [[0,1,0,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]]

毎回描画コードを書くのは面倒なので関数化します。

def print_block(block):
    for y in block:
        for x in y:
            print('' if x==1 else '',end='')
        print()
print_block(data)

□■□□
□■■□
□■□□
□□□□

2.回答 [::-1] とzip関数を用いる方法

リストに対して[::-1]を用いると元のリストの浅いコピーを逆順で作成します。
zip関数は各引数の先頭から1つの要素を繰り返し抽出しTupleを作成します。

合わせると要素が90度回転したことになります。

data = [[0,1,0,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]]
print_block(data[::-1])

□□□□
□■□□
□■■□
□■□□

print_block(zip(*data[::-1]))

□□□□
□■■■
□□■□
□□□□

関数にまとめると

def rotate(data,num):
    tmp = data.copy()
    if num==0:
        return tmp
    rotated = list(map(list, zip(*tmp[::-1])))
    for i in range(num//90-1):
        rotated = list(map(list, zip(*rotated[::-1])))
    return rotated

data = [[0,1,0,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]]
block = rotate(data,270)
print_block(block)

□□□□
□■□□
■■■□
□□□□

2.回答 numpyライブラリを用いる方法

numpyライブラリにはこうした行列のようなデータを
操作する機能を備えたものがあります。

numpy.rot90(データ , 回転数)

数値の配列を反時計回りに90度回転させる
回転数は0~を指定 , 1で90度回転
回転数を-の値にすると時計回り

import numpy as np

def rotate2(data,num):
    return np.rot90(data.copy(),-num//90)

data = [[0,1,0,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]]
block = rotate2(data,90)
print_block(block)

□□□□
□■■■
□□■□
□□□□

こちらは2行で出来てしまいますね。

まとめ

データ構造の考え方とデータの操作方法は
パズルゲームがおすすめです。

今後もやっていきますので色々解いてみて下さい。

それでは。

作者の情報

乙pyのHP:
http://www.otupy.net/

Youtube:
https://www.youtube.com/channel/UCaT7xpeq8n1G_HcJKKSOXMw

Twitter:
https://twitter.com/otupython

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?