チュートリアルStep2

![スクリーンショット 2024-10-09 22.05.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900427/65a7571c-31f0-5621-f055-bb7d33979d0f.png)


![puyopuyo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900427/1fdf8221-96c5-fcfa-3a52-383422a6fdc3.gif)
　ぷよぷよプログラミングAI学習システムは、中高生の自己調整学習に向けて開発されました。
　どうやって、Chromebookで、１０分で、素敵な人工知能を作れるのでしょうか？
　秘密は、３つ。
　１　jupyter liteで、webクライアントがpythonコードを実行
　２　超軽量な機械学習フレームワークdezeroを採用
　３　ぷよぷよのstageとactionがコンパクト

### Github&X

https://github.com/Lunanaedu/jupyterlite-puyopuyo

https://github.com/Lunanaedu/puyopuyo-kai

https://x.com/educationai_ai

### ぷよぷよプログラミングAI学習用まとめ

https://qiita.com/educational-ai/items/50c0fa689c01794d145e

### チュートリアルまとめ

https://qiita.com/educational-ai/items/88feaf91bdda0b5e0d25

# Step2 blocks

# 2 puyoを作ってみる。

　今回は、puyoを作ってみます。落下してくるpuyoは、中心ぷよと動くぷよから構成されます。位置情報は、ゲーム画面上では、本来は整数ではないのですが、機械学習のために整数として扱うことにします。


```python
import numpy as np
import random

class Puyopuyo:
    def __init__(self):
        self.x = 2
        self.y = 0
        self.dx = [1,  0, -1, 0]
        self.dy = [0, -1,  0, 1]
        self.centerPuyo = random.randint(1,4)
        self.movablePuyo = random.randint(1,4)
        self.rotation = 1
```

* movablePuyoは、座標としては、初期状態では、上向きです。また、必ず左から3番目の列を落下し始めることにします。
* 回転は、0から270まで、90刻みです。
* dxとdyは、movablePuyoのcenterPuyoからの相対座標です。
* 公式javascriptでは、rotationは0,90,180,270です。それぞれ0,1,2,3とします。
* dx[rotation]のように使います。例えば、rotation=1の時は、dx[1]となります。
* self.centerPuyo = random.randint(1,4) 色を4色からランダムに指定します。

そこで、初期状態でboard[2,0]にすでにぷよが存在すればゲームオーバーになるかどうかの判定をします。


```python
def create_new_puyo(board):
    new_puyo = Puyopuyo()
    done = False
    if board[2, 0] > 0:
        done = True
    return new_puyo, done    
```

create_new_puyo関数は、新しいぷよ生成と終了判定をします。

次に、ぷよをサンプルボードに配置してみます。もしも、movablepuyoが上に位置（rotation=1）で、puyo.y=0固定された場合、movablepuyoは消えます。


```python
def set_puyo_to_board(board, puyo):
    new_board = np.copy(board)
    new_board[puyo.y, puyo.x ] = puyo.centerPuyo
    puyo_dy = puyo.y + puyo.dy[puyo.rotation]
    puyo_dx = puyo.x + puyo.dx[puyo.rotation]
    if puyo_dy >= 0:
        new_board[puyo_dy, puyo_dx ] = puyo.movablePuyo
    return new_board
```


使ってみます。


```python
import numpy as np
import random
from puyo_utils import *

board = utils.create_sample_board()

puyo2 = Puyopuyo()
puyo2.y = 3

for i in range(4):
    puyo2.rotation = i
    new_board= set_puyo_to_board(board, puyo2)
    print(new_board)

```

    [[0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 1 3 0 0]
     [0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 1 0 0 0]
     [0 0 2 0 3 0]
     [0 1 1 0 2 0]
     [3 2 1 0 3 0]
     [4 3 1 2 2 0]]
    [[0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 3 0 0 0]
     [0 0 1 0 0 0]
     [0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 1 0 0 0]
     [0 0 2 0 3 0]
     [0 1 1 0 2 0]
     [3 2 1 0 3 0]
     [4 3 1 2 2 0]]
    [[0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 3 1 0 0 0]
     [0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 1 0 0 0]
     [0 0 2 0 3 0]
     [0 1 1 0 2 0]
     [3 2 1 0 3 0]
     [4 3 1 2 2 0]]
    [[0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 1 0 0 0]
     [0 0 3 0 0 0]
     [0 0 0 0 0 0]
     [0 0 0 0 0 0]
     [0 0 1 0 0 0]
     [0 0 2 0 3 0]
     [0 1 1 0 2 0]
     [3 2 1 0 3 0]
     [4 3 1 2 2 0]]


これらの関数も使いたいので、fb_utilsに保存しておきます。


```python
%%writefile puyo_utils.py
import numpy as np
import random

class Puyopuyo:
    def __init__(self):
        self.x = 2
        self.y = 0
        self.dx = [1,  0, -1, 0]
        self.dy = [0, -1,  0, 1]
        self.centerPuyo = random.randint(1,4)
        self.movablePuyo = random.randint(1,4)
        self.rotation = 1    


class utils:
    def create_sample_board(height=12, width=6):
        sample_list = np.arange(width)
        random.shuffle(sample_list)
        board = np.zeros(height * width, dtype = np.int32).reshape(height, width)

        for j in range(width):
            if sample_list[j]:
                for i in range(sample_list[j]):
                    board[height - 1 - i, j] = random.randint(1, 4)

        return board

    def create_new_puyo(board):
        new_puyo = Puyopuyo()
        done = False
        if board[2, 0] > 0:
            done = True
        return new_puyo, done    

    def set_puyo_to_board(board, puyo):
        new_board = np.copy(board)
        new_board[puyo.y, puyo.x ] = puyo.centerPuyo
        puyo_dy = puyo.y + puyo.dy[puyo.rotation]
        puyo_dx = puyo.x + puyo.dx[puyo.rotation]
        if puyo_dy >= 0:
            new_board[puyo_dy, puyo_dx ] = puyo.movablePuyo
        return new_board

```

    Overwriting puyo_utils.py


* class utils : 関数をまとめて、utilsにしました。名前がぶつからないようにします。