「15パズル」の確認

学習の目的

  • 1.前回の「15パズル」を確認する

  • 2.今回の追加機能

まずは、前回作成した「15パズル」について確認しましょう。

このスライド学習では、Google Colabを使用します。

Google Colabへは、次のリンクをクリックして移動しましょう。

前回作成した、「IP02-13」を開き、改変を加えることでもこの回は完了できますが、新しいノートブックを作成することをおすすめします。

新しいノートブックを作成する場合は、「IP02-14」という名前をつけてください。

1.前回の「15パズル」を確認する

まずは、前回の「15パズル」のプログラムを再現しながら、内容を確認しましょう。

プログラムを一つずつ、セルに入力して実行していってください。


プログラム1:盤面モデルの作成

盤面モデルとして、「15パズル」の4×4のマスを、二次元配列で表現します。

クリアの状態の盤面モデルを作成する関数です。

# プログラム1
def init():
    global tiles
    tiles = [
        [1,2,3,4],
        [5,6,7,8],
        [9,10,11,12],
        [13,14,15,0]
    ]

プログラム2:空きマスの位置を確認する関数

呼び出すことで、空きマスの位置を戻り値として返す関数です。

# プログラム2
def find_blank():
    for i in range(4):
        for j in range(4):
            if tiles[i][j] == 0:
                return i, j

プログラム3:移動できるか確認する関数

引数で指定した位置が、移動できるか(空きマスが隣接しているか)を確認する関数です。

# プログラム3
def can_move(i, j):
    bi, bj = find_blank()
    # 同じ行で横に1マス差 or 同じ列で縦に1マス差
    return (
        (i == bi and (j == bj + 1 or j  == bj - 1)) or
        (j == bj and (i == bi + 1 or i  == bi - 1))
    )

プログラム4:マスのスライドをする関数

指定したマスと空きマスの内容を交換します。

# プログラム4
def move_tile(i, j):
    bi, bj = find_blank()
    temp = tiles[i][j]
    tiles[i][j] = tiles[bi][bj]
    tiles[bi][bj] = temp

プログラム5:クリアの状態を判定する関数

現在、クリアの状態かを確認する関数です。

クリアの状態なら、"true"を戻り値として返します。

# プログラム5
# ゴール状態か確認
def is_goal():
    last_tiles = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,0]]
    return tiles == last_tiles

プログラム6:盤面モデルをシャッフルする関数

盤面モデルをシャッフルします。

空きマスへランダムに移動をおこないます。

# プログラム6
import random
# 盤面モデルをシャッフル
def shuffle(num = 500):
    for _ in range(num):
        bi, bj = find_blank()
        options = []
        #空きマスの上が盤面モデルの中
        if bi - 1 >= 0:
            options.append([bi-1, bj])
        #空きマスの下が盤面モデルの中
        if bi + 1 < 4:
            options.append([bi+1, bj])
        #空きマスの左が盤面モデルの中
        if bj - 1 >= 0:
            options.append([bi, bj-1])
        #空きマスの右が盤面モデルの中
        if bj + 1 < 4:
            options.append([bi, bj+1])

        ni, nj = random.choice(options)
        move_tile(ni, nj)

プログラム7:ボタン設定・配置

画面のボタンの配置などを設定します。

# プログラム7
import ipywidgets as widgets
from IPython.display import display, clear_output
import random
# 表示を更新
def update_display():
    clear_output(wait=True)
    grid = []
    for i in range(4):
        row = []
        for j in range(4):
            num = tiles[i][j]
            label = str(num) if num != 0 else ""
            btn = widgets.Button(description=label, layout=widgets.Layout(width='50px', height='50px'))
            def on_click(b, i=i, j=j):
                if can_move(i, j):
                    move_tile(i, j)
                    update_display()
            btn.on_click(on_click)
            row.append(btn)
        grid.append(row)

    # ステータス表示
    if is_goal():
        status = widgets.HTML(value="You Win!")
    else:
        status = widgets.HTML(value="")

    # リセットボタン
    reset_btn = widgets.Button(description="Reset", layout=widgets.Layout(width='100px'))
    def on_reset(b):
        shuffle()
        update_display()
    reset_btn.on_click(on_reset)

    #「」、数字ボタンの表示
    display(widgets.VBox([
        widgets.GridBox(sum(grid, []), layout=widgets.Layout(grid_template_columns="repeat(4, 50px)")),
        status,
        reset_btn
    ]))

プログラム8:実行

盤面モデルをシャッフルし、実行します。

# プログラム8
# 初期シャッフル&表示
init()
shuffle()
update_display()

セルが8個つくられていることを確認しましょう。

プログラム1~8をすべて実行して、エラーがなければ前回の完成形と同じになります。

反応が遅れることがあるので、一度クリックしたら、反応がなくても少し待ってみましょう。

2.今回の追加機能

今回行うことは、「15パズル」の機能追加です。

以下の機能を追加していきます。

①移動回数のカウント

②クリアまでの時間計測

③ランキングの表示

今回は、上記の三つの機能を「15パズル」に実装させていきます。

完成したら、以下のようになりますよ。

それでは、張り切っていきましょう!!

Well done!

次のステップに進みましょう!

次のステップに進む

← 前のステップにもどる