注意:上の実際のパズルは、実際にはRubyで作られてます。
このプログラムは40行ほどですが、まず、本質的な部分を解説します。
その前に、Pythonプログラムで重要なことが2つあります。
「番号は0から始まる」と「文字列型と数値型の区別」ということです。
前者は Perlとかと同じですけど、後者は注意が必要です。
具体的には「文字列型と数値型の加算はできない」「配列の番号には数値型しか使えない」ということです。
注意:以下、行番号「1」が実際のプログラムの1行目というわけではありません
1: BallPict = ('../siromaru.gif', '../akamaru.gif', '../aomaru.gif')
2: Col = [0,0,0,0,0,0]
3:
4: Data = os.environ['QUERY_STRING']
5: if re.match('^[012]{6}[0-5]$', Data) == None:
6: Data = '0200020'
7:
8: Push = int(Data[-1])
9:
10: for i in range(6):
11: if abs(Push - i) == 1 or abs(Push - i) == 5:
12: Col[i] = (int(Data[i]) + 1) % 3
13: else:
14: Col[i] = int(Data[i])
15: NewData = NewData + str(Col[i])
16:
17: for i in range(6):
18: Ball[i] = '<A HREF="hexpy.cgi?' + NewData + str(i) + '"><IMG SRC="' + BallPict[Col[i]] + '" BORDER=0></A>'
ここまでで、前回説明した、リンクがついた画像のHTMLを作ります。
プログラムの流れは、
ということになります。
1行目で、画像ファイル名をリストにしておきます。
2行目で、各コマの色を表すリストを用意しておきます。
4行目で、送られたデータを取り込んで、6行目でデータのチェックをしてます。
このパズルでは簡単な数値を送るだけなので、cgiライブラリは使わずに os の環境変数を使ってます。
チェックには正規表現を使って「0か1か2が6個並んで、次に0から5までの数字が1個ある」というパターンで調べます。
このパターンに合わないときは、6行目でデータは「0200020」となります
(このデータで最後には「全て白丸」となります)。
8行目で、データの最後の文字(数字)を変数「Push」に入れます。これが「どのマルがクリックされたか?」を表してます。 ただし、データの「Data」は文字列型ですが、あとで「Push」を使うときは数値として使うので、int 関数で数値型に変換しておきます。
10行目からのループで、クリックされた番号(ここでは変数Push)によって、データの置き換えをします。
置き換えが必要なのは Push の前後の数です。単純に考えれば「Push ±1」ということになりますが、
例外として番号0のときは1と5、番号5のときは4と0にならなくてはいけません。
場合分けが複雑になりそうですが、実際は Pushの値がなんだろうと「Push ±1」と「Push ±5」の場合だけを調べればすみます
(だって、ゼロやマイナスの番号のマルは存在しないので、置き換えられることもないのです)。
これでも良いですけど
「i == Push +1 or i == Push -1 ・・・」と4つの比較で長くなるので、
ちょっと数学的に「差の絶対値が1か5である」という方針で、比較を2つだけにしてみました。
さて、置き換えが必要な場合は、12行目でマルの色を表す数字をひとつ増やします。
配列の要素「Col[i]」が番号iのマルの色を表す数です。置き換える場合は、元の数、つまりDataのi番目の数に1を足します。
ただし、0→1→2→0 と、2の次は0に戻ります。これも場合分けが必要に見えますが、
こういうときは定番の方法で、割った余りを計算する「%」を使います。
「X +1 % 3」とすることで、2+1の時は0になります。
この計算が出来るように、あらかじめData[i] を計算できるように int関数で数値型に変換します。
置き換えが必要ないときは、14行目で、そのまま元データの値を数値型に変換して配列に入れます。
15行目で、リンクに付けるための新しいデータを作ります。 ここでは文字列が欲しいので、str関数で Col[i]を文字型に変換して「NewData」に追加します。
こうして必要なデータがそろったので、18行目でマル画像部分のHTMLを作ります。
あとは、前回説明した、全体のHTMLを表示する部分や、Python、CGIのお約束を書いて完成です。 プログラム全体は以下のとおりです。
1: #! /usr/bin/python
2:
3: import os, re
4:
5: BallPict = ('../siromaru.gif', '../akamaru.gif', '../aomaru.gif')
6:
7: TR = '</TD></TR>\n<TR><TD>'
8: TD = '</TD><TD>'
9:
10: Ball = [0,0,0,0,0,0]
11: Col = [0,0,0,0,0,0]
12: NewData = ''
13:
14: Data = os.environ['QUERY_STRING']
15:
16: if re.match('^[012]{6}[0-5]$', Data) == None:
17: Data = '0200020'
18:
19: Push = int(Data[-1])
20:
21: for i in range(6):
22: if abs(Push - i) == 1 or abs(Push - i) == 5:
23: Col[i] = (int(Data[i]) + 1) % 3
24: else:
25: Col[i] = int(Data[i])
26: NewData = NewData + str(Col[i])
27:
28: for i in range(6):
29: Ball[i] = '<A HREF="hexpy.cgi?' + NewData + str(i) + '"><IMG SRC="' + BallPict[Col[i]] + '" BORDER=0></A>'
30:
31: print 'Content-type: text/html\n\n'
32:
33: print '<HTML><TABLE><TR><TD>', \
34: TD, Ball[0], TD, TR, \
35: Ball[5], TD, TD, Ball[1], TR, \
36: Ball[4], TD, TD, Ball[2], TR, \
37: TD, Ball[3], TD, \
38: '</TD></TR></TABLE><H2><A HREF="hexpy.cgi">Restart</A></H2></HTML>'