2011年5月6日金曜日

python:100マスゲーム

1から100までの数字を1つずつ縦横10×10のマス目にランダムに書いたものを用意します。
そして、1から小さい順に消していき全部消すのにかかる時間を競います。
いわゆる、頭の体操の定番です。


私は最初8分もかかりましたがだんだんタイムを縮め6分でできました。
小中学生だと5分もかからないようです。
似たようなゲームとしては「Count Touch」「数字順探し」などがネット上にあり、マス目でなかったり、制限時間があったり、数字が100個もなかったり、値にマイナス値があったり、といったバリエーションがあります。
「小さい数字を順に探す」などでネット検索するといくつもひっかかります。

さて、このゲームの用紙を作るところをpythonで作ってみました。
ロジックは以下のとおりです。
1から100の連番とこれに対応した乱数の組を発生させます。
この組を乱数の昇順にソートすることでシャッフルします。
シャッフルした組の連番を10個ずつ10行のcsvファイルに出力します。


ここまでをpythonで作成し、この出力csvファイルを表計算ソフトで開いて枠線やフォントサイズを整えて印刷します。
「シャッフルした1から100までの連番の10個ずつ10行のcsvファイル」作成プログラムは以下のとおりです。


# -*- coding: shift_jis -*-
#
# 100masu.py
#
import os,sys,random

def Make100masu(n):
 """ 100マス表作成
 1~100までの数字をすべて1つずつ使用し、
 10行10列にランダムに配置したcsvファイルを作成する。
 args:
  n: 出力ファイル名に付ける番号
 """
 #出力先フォルダ:このスクリプトと同じフォルダ
 sOtFdr = os.path.dirname(sys.argv[0])
 #出力ファイル名:「100masuXX.csv」
 sOt = os.path.join(sOtFdr, "100masu"+str(n).zfill(2)+".csv")
 #出力ファイル既存時は削除しておく
 if os.path.isfile(sOt): os.remove(sOt)

 #[乱数値、連番(1~100)]を要素とするリストを作成
 L0 = [[random.random(),i+1] for i in xrange(100)]

 #乱数値>連番の優先順位で並び替え
 L1 = sorted(L0)

 #出力ファイルを書込み用に開く
 f = open(sOt, "w")
 #100の配列要素を10行10列に出力
 for i in xrange(10): #行番号
  for j in xrange(10): #列番号
   #要素のうち連番を取り出し文字型に変えて出力する。
   f.write(str(L1[i*10+j][1]))
   #要素9個までは半角カンマ、10個目は行末文字を出力する。
   f.write({True:",", False:"\n"}[j<9])
 f.close()
 return None

if __name__=="__main__":
 #とりあえず10個作成します。
 for i in xrange(10):
  Make100masu(i+1)



・random.random()
 乱数の発生。細かい指定もできるが、当プログラムではソートキーにするだけなので特に指定なしで実行する。
・for i in xrange(100):
 0~99までの100個の数字を順に発生させる。
 range関数は発生させる値をメモリーに展開するが、xrange関数はメモリー展開しないのでメモリーを節約できる。当プログラムの100程度ならばどちらでも大差ない。
・{True:",", False:"\n"}[j<9]

 {}内は辞書型(連想配列)で、直後の[]内の式の値をキーにして対応する値を返します。j<9ならばTrueとなり「、」が返り、j≧9ならばFalseとなり「\n」を返します。

 

0 件のコメント:

コメントを投稿