$4 ゲームを作ってみる

4-2 簡単なパズルの解説

実際のパズル

注意:上の実際のパズルは、実際には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>'

Next: 5-1 ファイルからの入力

Previous: 4-1 簡単なパズル

Contents


Foundation of CGI Page

春風はるか haruka@harukaze.net