コンテンツにスキップ

Pythonアプリ(8):神経衰弱を作ろう

トランプゲームの神経衰弱を作ってみましょう。

tentoapp-08-01.png

ふたつの札(ふだ)をめくって、絵柄が同じだとめくった状態になり、間違えると元に戻ります。

まずは画像を使わないバージョンを作ってみます。

1. 札(ふだ)を並べよう

札はボタンで表現します。 電卓のときと同じ要領で4×4のタイル状に並べましょう。 b.grid(i % 4, i // 4) の部分の意味がわからなかったら「Pythonアプリ(6):電卓を作ろう」を読んで下さい。

from tentoapp import *
app = App()
for i in range(16):
b = Button(app)
b.text = "オモテ"
b.grid(i % 4, i // 4)
app.start()

tentoapp-08-02.png

2. 「ウラ」を作ろう

次に、札をクリックすると札がめくれて裏の数字が表示されるようにしましょう。 数字は、0から7とします。札が16枚あるので、裏の数字の種類は8個になります。

from tentoapp import *
from random import shuffle
app = App()
def click(e):
button = e.widget
button.text = button.ura
ura_list = [0,1,2,3,4,5,6,7] * 2
shuffle(ura_list)
for i in range(16):
b = Button(app)
b.text = "オモテ"
b.ura = ura_list[i]
b.onclick = click
b.grid(i % 4, i // 4)
app.start()

tentoapp-08-03.png

2.1 裏の数字をランダムにする

裏の数字は、0~7ですが、それぞれ2個ずつ計16個になります。これをリスト ura_list に入れます。 [0,1,2,3,4,5,6,7] * 2 は、リスト [0,1,2,3,4,5,6,7] を2つ重ねるといういみです。毎回同じ順番ではゲームにならないので、 random モジュールの shuffle() (シャッフル)を使って中身をシャッフルしています。

一部
ura_list = [0,1,2,3,4,5,6,7] * 2
shuffle(ura_list)

次に、それぞれのボタンに ura_list の数字を割り当てます。ここでは、 b.ura として、ボタンに ura という変数を新しく作ってそこに数字を代入しています。

一部
for i in range(16):
...
b.ura = ura_list[i]

2.2 クリックされたら文字を変える

ボタンがクリックされたら、数字を表示して札が「裏返った」ことを表現します。ここで先程設定したボタンの変数 ura を用います。

click関数
def click(e):
button = e.widget
button.text = button.ura

3. 札を比べよう

次にいよいよ、神経衰弱の仕組みの部分を作ります。札をクリックしたとき、すでに裏返っている札があったらそれと比較するようにします。

from tentoapp import *
from random import shuffle
app = App()
saisho = None
def click(e):
global saisho
button = e.widget
button.text = button.ura
if saisho == None:
saisho = button
else:
if saisho.ura != button.ura:
saisho.text = "オモテ"
button.text = "オモテ"
saisho = None
ura_list = [0,1,2,3,4,5,6,7] * 2
shuffle(ura_list)
for i in range(16):
b = Button(app)
b.text = "オモテ"
b.ura = ura_list[i]
b.onclick = click
b.grid(i % 4, i // 4)
app.start()

tentoapp-08-04.png

3.1 札をクリックした時の動作

札をクリックしたらこのような流れになります。

  • まず札を裏返す
  • 最初に裏返っている札があるかどうか調べる
    • 最初に裏返っている札がなければ
      • 今回の札を最初の札にする
    • 最初に裏返っている札があったら
      • 同じ数字だったらなにもしない(両方とも裏返ったままにする)
      • 同じ数字ではなかったら両方とも元に戻す
click関数
saisho = None
def click(e):
global saisho
button = e.widget
button.text = button.ura
if saisho == None:
saisho = button
else:
if saisho.ura != button.ura:
saisho.text = "オモテ"
button.text = "オモテ"
saisho = None

saisho = None ではすでに裏返っている札を代入するための saisho という変数を作り、 None を代入しています。 None(ナン) はなにもない、と言う意味です。 そのあとは、 saisho が設定されていなければ今の札を代入し、設定されていれば今の札と比較します。設定されている場合は、次の比較に移るので saisho をふたたびNoneにするのを忘れないでください。

4. 時間差をつけよう

ここまでで、二つの札の数字が同じだったらひっくり返すことはできるようになりましたが、二枚目の札が間違っていた場合すぐにもとに戻ってしまい、二枚目の札がなんなのか見ることができません。そこで、 app.after() を使って、1秒後にもとに戻すようにします。

from tentoapp import *
from random import shuffle
app = App()
saisho = None
def click(e):
global saisho
button = e.widget
button.text = button.ura
if saisho == None:
saisho = button
else:
if saisho.ura != button.ura:
app.after(1000,clear,saisho)
app.after(1000,clear,button)
saisho = None
def clear(button):
button.text = "オモテ"
ura_list = [0,1,2,3,4,5,6,7] * 2
shuffle(ura_list)
for i in range(16):
b = Button(app)
b.text = "オモテ"
b.ura = ura_list[i]
b.onclick = click
b.grid(i % 4, i // 4)
app.start()

4.1 click関数の修正

button.text = "オモテ" を1秒後に実行するために、 clear() 関数を作って app.after() から呼び出しています。

def click(e):
global saisho
button = e.widget
button.text = button.ura
if saisho == None:
saisho = button
else:
if saisho.ura != button.ura:
app.after(1000,clear,saisho)
app.after(1000,clear,button)
saisho = None
def clear(button):
button.text = "オモテ"

やってみよう!

1. 裏返っている札のクリック☆

今のままでは、裏返っている札もクリックできてしまうので以下のような不具合が出てしまいます。裏返った札をクリックしても何も起こらないように修正して下さい。

(1) 同じ画像を連続でクリックすると裏返しのままになってしまう

(2) すでに正解した札もクリックできてしまう。(正解した札ももとに戻せてしまう)

2. 文字の代わりに画像を表示しよう☆☆

ボタンに文字ではなく、画像を表示して下さい。

オモテ用画像

tentoapp-08-05.png

tentoapp-08-06.png

ウラ用画像

tentoapp-08-07.png

tentoapp-08-08.png

tentoapp-08-09.png

tentoapp-08-10.png

tentoapp-08-11.png

tentoapp-08-12.png

tentoapp-08-13.png

tentoapp-08-14.png

3. 対戦できるようにしよう☆☆☆

二人で対戦できるようにして下さい。先手番か後手番かを表示し、また点数を表示して下さい。

tentoapp-08-15.png