goo blog サービス終了のお知らせ 

財団日報

月4回が目標です

押下

2010-08-14 11:32:16 | プログラム
以下、覚書。

・Radikoで「爆笑問題の日曜サンデー」を録音したくなった。ここはエリア外のはずだが、会社のPCだとなぜか聴取可能(自宅は不可)。日曜に会社に出てくるのはわびしいので、なんとかタイマー録音したい。

・いろんな都合で、定時に「午後のこ~だ」を起動し、「録音開始ボタン」を押すのが一番安全で簡単ということになった。それくらいのプログラムなら、と甘く見て無料開発環境のactive basicをダウンロード。最新版はなぜかエラーが起きるので、V4.24を使う。

・やることは、以下の5つ
 ①TBSを流しているradikoのサイトを起動
 ②午後のこ~だを起動
 ③午後のこ~だの「ライン入力録音MP3録音」タブを開く
 ④指定の時間になったら午後のこーだの「録音開始」ボタンをクリック
 ⑤3時間後、同じボタンをクリック

・①、②はShellExecuteを使う。

・③は、まず午後のこ~だのメインウィンドウのハンドルをFindWindowで調べて、そのハンドルに対してSendMessage([ハンドル], WM_KEYDOWN, VK_RIGHT, 1)してみるが、うんともすんとも言わない。

・そこでメインウィンドウの子ウィンドウ(?)である別のハンドルをFindWindowExで探して、SendMessageしたらうまくいった。

・FindWindowExはActiveBasicのV4にはないので、MainWnd.sbpにDeclare文を書き加えて使用可能にした。

・④は「録音開始」ボタンの位置を調べてmouse_eventでクリックしようと考えたのだが、どうもうまくいかないので、ボタンのハンドルを調べてSendMessage([ハンドル],BM_CLICK,0,0)することに。ところが、これもうまくいかない。③で使ったFindWindowExを使ってみたが、ボタンのハンドルがわからなかった。

・そこで指定されたウィンドウの子ウィンドウを列挙するEnumChildWindowsProcを使うことに。これもActiveBasicのV4にはないので、この開発環境に関するホームページの記述を参考にDeclare文を書き加えた。

・EnumChildWindowsProcから呼び出される関数のなかで、テキストが「録 音 開 始」があれば、そのハンドルを記録しておく。このさいにWM_GETTEXをSendMessageしてもうまくいかず、はまった。ほかのアプリのウィンドウのテキストを調べる場合には、GetWindowTextが正解だそうな。

・なんやかんやでうまくボタンを自動的に押せるようになった。

・ActiveBasicのサイトが落ちているらしく、所蔵されているであろう大量の情報が読めない。グーグルのキャッシュから「テキストのみのバージョン」をクリックすると情報が得られることもある。

・Enumとはエニュマエル夫人の略ではない。

課題

2008-08-14 21:24:28 | プログラム
 外出先から帰ってきた妻が、家で仕事の続きをしていた私にチョコレートのようなものを差し出した。明治の"BLACK"。チョコレートに似せたパズルだ。

 パズルを手作業で解くのは5分もしないうちにあきらめ、このパズルを解くためのプログラムを作ってみることにした。このようなちょっとしたパズルのためのプログラムを過去に何度か作ったことがある。たしか1998年ごろに作ったペントミノ(「凹」型など5つの正方形を組み合わせて作る12ピースを組み合わせて長方形の枠にあてはめるパズル)は、このチョコパズルにかなり近い。

 この数年はこのようなパズル系のプログラムからすっかり遠のいていたので、自宅のPentiumIIIパソコンにはフリーの開発環境が入っていない。昔はTurbo Pascalと決めていたが、日本語が入ってしかもWindowsで使えるDelphiはこのパソコンやディスクの空き容量ではちと不安ということで、もっと昔、中学生のころまで遡ってN88-BASIC互換のActive Basicを使ってみることにした。LOCATE文やPRINT文などで、Delphiのコンソールプログラムよりも画面が自由に使えるのもありがたい。なお、偶然だが最近私はたしか中学生のころに聞いた「カナダからの手紙」や「ルビーの指輪」をMP3プレーヤーで聞いている。

 早速Active Basicを使ってみて、いろいろと違いがあることに気が付いた。備忘録として書いておくと

・BasicでもPascal同様に構造体が使えるが、サブルーチンのパラメータとして構造体型の変数を使う場合には、ByRefを指定しておかなければならない
・Pascalで言うBoolean型がBasicにはない。Char型(8ビット符号付整数)を代りに使おうとしたら、-1で真、0で偽という判定がうまくできなかった。Boolean型の代りにはinteger型を使ったほうがいい
・input文でファイルから文字列1行を読み込むさい、行頭の半角空白は無視されるようだ。Pascalでもあまりファイルは扱ったことがないので私は知らなかったが、上の項目を含め、このあたりは実は「常識」なのかもしれない。

 上記の違いを理解した(つもりになった)上で、ペントミノのプログラムを作っていたころの不確かな記憶をもとに、昨日の朝から書き始めた。従来、駒の形は全部ソース上で指定していたが、めんどうなのでエディタでテキストファイルに図形を書き、それを読み込んで使いやすい形のデータ形式にする方法を選んだ。上記の行頭半角空白無視の問題は、全角にすることで解決、というよりも回避した。

 昨日の午後にはほぼ書き上げて、実行してみたら、明らかにおかしい動作だったので、何ヶ所か修正した。

 こういうパズル解法プログラムは、膨大な選択肢に逐一あたってみるため、答えを得るまでに長い時間がかかる。私のプログラムも、画面の動きこそ早いとはいえ、正解を得るためにはかなりの時間がかかりそうだった。ところが、これは画面表示に時間を費やしているため。1000ステップに1度だけ最新の状況を表示するようにすると、飛躍的に速くなった。

 と同時に、致命的なプログラムの欠陥が明らかになった。すべての可能性を探索したあとで「ひとつも正解がみつかりませんでした」という結果が出てしまったのだ。チョコパズルはケースにきれいにおさまった状態で出荷されるので、正解がないということは、プログラムのほうが間違っている。

 私はチョコパズルの正解例や、チョコパズルを解くためのソフトがインターネット上で公開されていることを知っているが、しばらくは苦労してみることにする、とここで宣言してしまえば、あきらめるまでの時間がちょっと長くなるだろう。

(追記)…と書いた直後に、90度、180度、270度回転したコマの形状データを生成するあたりに間違いがあることに気が付き、修正したら、互いに180度回転した関係にある2つの正解がみつかった。

 画面を見ながら、妻から手渡されたパズルのコマを枠に全部はめてから返した。こういうのはプログラムを作るより、手作業で正解を見つける人のほうがすごいと思うので、プログラムのことは一言も言わなかった。