繰り返しになりますが、BCCSkelton(ECCSkelton)によるプログラミングは、まず視覚的な完成形をイメージして、リソースを書くことから始まります。(注)

注:「6)発想は「積み上げ型」ではありません。先ず完成形のイメージをもち、BCCFormでリソース部品を作り、そのRCファイルからスケルトン作成ウィザードで基本的なウィンドウの型を作って、後はメニューやコントロールに対応した関数にその部分のコーディングをしていくだけです。」(「SkeltonWizard BCCSkeltonライブラリー」ヘルプファイル、「BCCSkeltonライブラリーとは何か?」から引用)

 

1.完成形のイメージ

今回のハノイの塔の場合、ベトナム(Vietnum-ベトナムではないですが、ヴィェツゥナム、とも一寸違いますね)のハノイには数回出張で行きましたが、あまり仏教由来の印象的建築物はなく、イメージが違いますね。実際、この数学パズルの由来となる伝説ではインドのガンジス川河畔の寺院にあるダイアモンド針と青銅盤なのだそうです。しかし、これも絵的には回避したいですね。

 

ということで、行き着いた背景は「アンコールワット(同じIndchineでもこれはカンボジアですね。でも私にとってのIndchineはココでやはり本店はベトナムのです)」、その寺院を背景に「木柱が3本」立ち、それに「花崗岩の石盤」が嵌っている映像が浮かび上がりました。

 

2.リソース画像の調達

ということで、フリーの画像を探しにインターネットへ。500pixel x 500pixelのフリーの背景画(画中の"M/Y/D/G"は消さないでください。これがフリーの条件となっています)と花崗岩表面の写真を入手します。

 

3.石盤を作る

完成している背景はさておき、ここからの石盤つくりが大変です。

 

まず、ウィンドウ上のイメージ(画像)の表示はBitmap(他の形式でも最終的にはビットマップに変換されるようです)によりますが、そのサイズは表示できる制限内にするために石盤個数も制限がかかります。今回の場合、背景が500pixelなので、柱3本における最大の石盤は2の乗数でもある16の倍数で160 x 3 = 480(残りの20は間隔マージン)としました。一番小さい石盤を16 x 16とすると正方形になるので、最小は32 x 16とし、最大9枚(幅 = 16 + 16 x 1~9枚)にしました。(間隔マージンは左右と柱間の4か所で5となります。)→ということで"#define MAXTIRE 9"の定数定義を思い浮かべますね。

 

次にビットマップは9つの石盤のビットマップを作ればよいわけではなく、描画して次に消去するために「描画部分の背景を切り取ったビットマップ(注)」が必要です。また、石盤を長方形にするととても機械的で面白くないので、角を丸くしてやる必要がありますが、その場合その丸みをつけた部分に背景を残さなければならない為、アイコンのように「描画ビットマップ」と「マスクビットマップ」が必要になります。

注:このビットマップはプログラムの描画位置に応じて動的に生成します。

 

例えば↓の例ではキャラクターの「描画ビットマップ」と描画部分を黒(0)背景部分を白(1)にした「マスクビットマップ」を用意し、背景にマスクビットマップをANDすることで描画部分が黒(0)抜きになり、背景部分は白(1)とのANDなので元のままとなります。次に「描画ビットマップ」をORすることで、描画部分が描かれ、背景部分は黒(0)とのORでそのまま残ります。

 

石盤のビットマップは、まず長方形の9枚のベース画像を作り、それをMS Paintの「角丸四角形」を黒色で上囲み(下はそのまま)します。また、このベースを黒塗りし、今度は同様に「角丸四角形」を白色で上囲みします。

これを9枚分作ることになります。

 

アイコンはコンソール版を作るときに作った↓を流用します。

 

4.ダイアログを作る

前回のMakeGraphで使ったばっかりだったので、今回もCPICBOXクラスを使い、サイズ不変更のダイアログにしました。

石盤の段数入力はコンボボックスを使い、選択時(CB_SELCHANGEメッセージが出ます)に指定段数(m_Tire <= MAXTIREになります)での初期化(石盤を左の第0番柱にPushしてゆきます)を行います。

「ハノイの塔」関数の実行は「開始」ボタンを押します。

プログラムの終了はいつも通り、IDOKボタンを押します。

PICTUREBOXコントロールはまだ登録されていないので"STATIC"で作ってください。後で手作業で"PICTUREBOX"に変えます。(↓は完成形なので"PICTUREBOX"になっていますが、最初はビットマップ貼り付け用"STATIC"にしていました。)

 

なお、これを作っていて、再帰を使ったプログラムなので実行時間が長くなる可能性があり、シングルスレッドのウィンドウズプログラムの場合、タイムアウトで落ちることが懸念されましたが、最初は落ちてもよいのでシングルスレッドのままとします。

 

【TowerOfHanoi.rc】

//-----------------------------------------
//             BCCForm Ver 2.41
//    An Easy Resource Editor for BCC
//  Copyright (c) February 2002 by ysama
//-----------------------------------------
#include    "ResTowerOfHanoi.h"

//----------------------------------
// ダイアログ (IDD_MAIN)
//----------------------------------
IDD_MAIN DIALOG DISCARDABLE 0, 0, 426, 383
EXSTYLE WS_EX_DLGMODALFRAME
STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | DS_SETFONT | DS_MODALFRAME | DS_CENTER
CAPTION "TowerOfHanoi"
FONT 8, "MS 明朝"
{
 CONTROL "", IDC_INIT, "COMBOBOX", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL, 356, 27, 60, 96, WS_EX_CLIENTEDGE
 CONTROL "開始", IDC_START, "BUTTON", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 356, 48, 60, 19
 CONTROL "終了", IDOK, "BUTTON", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 356, 352, 60, 19
 CONTROL "石盤の段数", IDC_LABEL, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY | SS_CENTER, 357, 11, 58, 12
 CONTROL "", IDC_SCREEN, "PICTUREBOX", WS_CHILD | WS_VISIBLE, 9, 9, 336, 366, WS_EX_CLIENTEDGE
}

//--------------------------
// イメージ(IDI_ICON)
//--------------------------
IDI_ICON    ICON    DISCARDABLE    "TowerOfHanoi.ico"

//--------------------------
// イメージ(IDI_BACKGRND)
//--------------------------
IDI_BACKGRND    BITMAP    DISCARDABLE    "アンコールワットフリー絵500x500.bmp"

//--------------------------
// イメージ(IDI_DISK1)
//--------------------------
IDI_DISK1    BITMAP    DISCARDABLE    "石盤32x32.bmp"

//--------------------------
// イメージ(IDI_DISK2)
//--------------------------
IDI_DISK2    BITMAP    DISCARDABLE    "石盤48x32.bmp"

//--------------------------
// イメージ(IDI_DISK3)
//--------------------------
IDI_DISK3    BITMAP    DISCARDABLE    "石盤64x32.bmp"

//--------------------------
// イメージ(IDI_DISK4)
//--------------------------
IDI_DISK4    BITMAP    DISCARDABLE    "石盤80x32.bmp"

//--------------------------
// イメージ(IDI_DISK5)
//--------------------------
IDI_DISK5    BITMAP    DISCARDABLE    "石盤96x32.bmp"

//--------------------------
// イメージ(IDI_DISK6)
//--------------------------
IDI_DISK6    BITMAP    DISCARDABLE    "石盤112x32.bmp"

//--------------------------
// イメージ(IDI_DISK7)
//--------------------------
IDI_DISK7    BITMAP    DISCARDABLE    "石盤128x32.bmp"

//--------------------------
// イメージ(IDI_DISK8)
//--------------------------
IDI_DISK8    BITMAP    DISCARDABLE    "石盤144x32.bmp"

//--------------------------
// イメージ(IDI_DISK9)
//--------------------------
IDI_DISK9    BITMAP    DISCARDABLE    "石盤160x32.bmp"

//--------------------------
// イメージ(IDI_MASK1)
//--------------------------
IDI_MASK1    BITMAP    DISCARDABLE    "Mask32x32.bmp"

//--------------------------
// イメージ(IDI_MASK2)
//--------------------------
IDI_MASK2    BITMAP    DISCARDABLE    "Mask48x32.bmp"

//--------------------------
// イメージ(IDI_MASK3)
//--------------------------
IDI_MASK3    BITMAP    DISCARDABLE    "Mask64x32.bmp"

//--------------------------
// イメージ(IDI_MASK4)
//--------------------------
IDI_MASK4    BITMAP    DISCARDABLE    "Mask80x32.bmp"

//--------------------------
// イメージ(IDI_MASK5)
//--------------------------
IDI_MASK5    BITMAP    DISCARDABLE    "Mask96x32.bmp"

//--------------------------
// イメージ(IDI_MASK6)
//--------------------------
IDI_MASK6    BITMAP    DISCARDABLE    "Mask112x32.bmp"

//--------------------------
// イメージ(IDI_MASK7)
//--------------------------
IDI_MASK7    BITMAP    DISCARDABLE    "Mask128x32.bmp"

//--------------------------
// イメージ(IDI_MASK8)
//--------------------------
IDI_MASK8    BITMAP    DISCARDABLE    "Mask144x32.bmp"

//--------------------------
// イメージ(IDI_MASK9)
//--------------------------
IDI_MASK9    BITMAP    DISCARDABLE    "Mask160x32.bmp"
 

ps. これだけビットマップを内蔵して使っているのでプログラムサイズも半端ない(979KB)です。仕方無いですよね。