[wst3_C_usr.h] /* ヘッダファイルの中は宣言のみ */ extern USHORT pailist[36]; extern int O; extern int P; extern int B; extern int C; extern int N; extern char O$; extern int I,J,K,L; extern int X,Y,V,W; extern int Z; [wst3glb.c] /* wst3glb.c には変数の実体と、必要なら初期値を記述 */ USHORT pailist[36] = { pinzu1ID, pinzu2ID, pinzu3ID, pinzu4ID, pinzu5ID, pinzu6ID, pinzu7ID, pinzu8ID, pinzu9ID, souzu1ID, souzu2ID, souzu3ID, souzu4ID, souzu5ID, souzu6ID, souzu7ID, souzu8ID, souzu9ID, manzu1ID, manzu2ID, manzu3ID, manzu4ID, manzu5ID, manzu6ID, manzu7ID, manzu8ID, manzu9ID, tonID, nanID, syaID, peiID, hakuID, hatuID, chunID, hanaID, hisiID }; int O = 0; int P = 1; int B = 2; int C = 3; int N = -1; char O$ = '\x0'; char J$[] = "順位 名前 記録 記録日時"; char K$[] = " "; char F$[] = "wst3hsco.TXT"; int I,J,K,L; int X,Y,V,W; int Z;
[wst3_C_usr.h] typedef struct ExecWk_t { APLFORMPTR AplForm; int C[0x8F + 1]; int G[10][20]; /* 2次元配列(y,x)に変更 */ int LX[0x3 + 1]; int LY[0x3 + 1]; int VM[0x9 + 1]; int VS[0x9 + 1]; int VR[0x9 + 1]; int HM[0x13 + 1][0x1 + 1]; int HS[0x13 + 1][0x1 + 1]; int HR[0x13 + 1][0x1 + 1]; int VW[0x13 + 1]; int HW[0x9 + 1][0x1 + 1]; int LC; int T1; int T2; int U1; int U2; int UT; int UB; int XW; int YW; int OK; int SE; int OE; int BF; int MD; int S1X; int S1Y; int S2X; int S2Y; int P1; int HF; int SCH; } ExecWk;【EXECワークの確保・初期化】
[wst3_C_usr.h] extern ExecWk *g_ewk; [wst3glb.c] ExecWk *g_ewk; [wst3main.c] BOOLEAN PIMExecConstruct(PIMEXECWORK *PIMExecWork,MESSAGE *Message) { /* EXECワークを確保しようとする、だめなら起動できない */ if ( (g_ewk = PIMExecWork->PIMUserWork = NewHeapPtr( sizeof(ExecWk) )) == NULL ) { SetFailMessage( Message ); return( false ); } /* 確保できれば良し */ return( true ); } BOOLEAN PIMExecSetup(PIMEXECWORK *PIMExecWork,MESSAGE *Message) { /* ExecWk型の変数領域をヌルクリア */ memset( g_ewk, 0, sizeof(ExecWk) ); /* 乱数系列の初期化 */ RANDOMIZE(); return true; }【EXECワークの使用】
g_ewk->AplForm g_ewk->G[3][5] g_ewk->FA【EXECワークの解放】
void PIMExecEnd(PIMEXECWORK *PIMExecWork,MESSAGE *Message) { /* 確保済みの EXECWK を解放する */ if ( g_ewk ) { DisposeHeapPtr( g_ewk ); g_ewk = NULL; } /* アウト状態に移行するときにプロセス終了 */ Message->CommonMsg.MessageID = AppliProcEndReqID; Message->AppliProcEndReq.AplFilter = AF_THIS_APPLI; }
/* 配列変数 C に牌画像を示す値(0〜35)を4つずつ入れる処理 */ void CINIT( void ) { int j; for( j = 0; j < 18; j++ ) { g_ewk->C[j] = g_ewk->C[j+18] = g_ewk->C[j+36] = g_ewk->C[j+54] = j; } for( j = 18; j < 36; j++ ) { g_ewk->C[j + 54] = g_ewk->C[j + 72] = g_ewk->C[j + 90] = g_ewk->C[j + 108] = j; } } /* 配列変数 C に入った内容をシャッフルする処理 ( 乱数で j,k の位置を求め入れ替える) */ void SHUFFLE( void ) { int i,j,k,l; for( i=O; i<=0x120; i++ ) { j = rand() % 144; /* 0 〜 143 の乱数値を得る */ k = rand() % 144; /* (同上) */ l = g_ewk->C[j]; g_ewk->C[j] = g_ewk->C[k]; g_ewk->C[k] = l; } } /* 配列変数C から画面用の配列変数Gにコピーする処理 */ void CGSET( void ) { int x,y,k,i; for( y = 0; y < 10; y++ ) { for( x = 0; x < 20; x++ ) { g_ewk->G[y][x] = -1; } } k = 0; for( y = 1; y < 9; y++ ) { for ( x = 1; x < 19; x++ ) { g_ewk->G[y][x] = g_ewk->C[k++]; } } for( y=1; y<=0x8; y++ ) { g_ewk->HW[y][0] = 0x3FE; g_ewk->HW[y][1] = 0x1FF; } for( i=1; i<=0x12; i++ ) { g_ewk->VW[i] = 0x1FE; } g_ewk->HW[0][0] = 0; g_ewk->HW[0][1] = 0; g_ewk->HW[9][0] = 0; g_ewk->HW[9][1] = 0; g_ewk->VW[0] = 0; g_ewk->VW[0x13] = 0; }ちょっと長かったですが、 要は CINIT() を呼び出して 配列変数 C[] に牌のシリアル番号を4つずつ入れ、 それを SHUFFLE() でランダムに並び替え、 CGSET() で C[] から G[][] にコピーしようというわけです。 後はこれらを、フォームの初期化などのタイミングで実行しておき、 ユーザーコントロールのコールバック関数から、 牌の再描画処理として呼び出す ALLDRAW() 関数の中身を作れば良いでしょう。
[例] GameFormSetUp() 中に、次のように記述。 CINIT(); SHUFFLE(); g_ewk->SCH = 0; g_ewk->MD = 0; Z = 144; g_ewk->P1 = N; g_ewk->HF = 0; CGSET();実際には、ALLDRAW()は牌全体の描画ということにして、 牌1個用に one_draw() を作ってみます。 この中に選択時の反転処理も組み込んでしまえば、 画面用配列変数 G[][] の値によって、 いつでも選択状態を含めた画面が再現されるようになります。 描画関連を1個所に集められるのでスッキリもしますね。
/* 全ての牌を G[] に従って描画する処理 (なお、G[] は G[y][x] と2次元配列に変更した) */ void ALLDRAW( void ) { int I,J; /* 牌の描画 */ for( I=1; I<=9; I++ ) { for( J=1; J<=8; J++ ) { if ( g_ewk->G[J][I] >= O ) { one_draw( I, J ); } if ( g_ewk->G[9-J][19-I] >= O ) { one_draw( (19-I), (9-J) ); } } } }
#define LEFTMGN (8*4) #define TOPMGN (40*4) #define PAI_X_SIZE (17*4) #define PAI_Y_SIZE (28*4) #define PAI_Y_MINI (23*4) /* 牌を1つ描画する処理 in x,y : 配列変数G[][]の添字としての x,y を渡すと、そこの牌を描画する。 (つまり、x: 1〜18, y:1〜8 が有効という事) その際、bit8 を見て 1 ならば反転(セレクト)状態にする。 */ int one_draw( int x, int y ) { RESOURCE myres; RECTANGLE myrect; RECTANGLE mask; POINT Start,End; COLOR fg; myrect.left = mask.left = LEFTMGN + (x-1) * PAI_X_SIZE; myrect.top = mask.top = TOPMGN + (y-1) * PAI_Y_MINI; if ( g_ewk->G[y+1][x] >= 0 ) { mask.width = PAI_X_SIZE - 1; mask.height = PAI_Y_MINI - 1; }else{ mask.width = PAI_X_SIZE - 1; mask.height = PAI_Y_SIZE - 1; } if ( g_ewk->G[y][x] >= 0 ) { /* 牌がある場合:牌をリソースより描画する */ strcpy( myres.ResFile, "WST3IM00" ); /* リソースブロック */ myres.ResID = pailist[ g_ewk->G[y][x] & 0xff ]; DrawImageRes( g_ewk->AplForm->FormWnHandle, &myrect, FRAME_MASK_ON, &myres, NORM_SCALE, &mask ); /* 反転している場合の表示( bit8 をフラグに使用 ) */ if ( g_ewk->G[y][x] & 0x100 ) { Start.x = End.x = mask.left; Start.y = End.y = mask.top; End.x += PAI_X_SIZE - 1; End.y += PAI_Y_MINI - 1; SetColorV( &fg, BLACK ); BoxPaint( g_ewk->AplForm->FormWnHandle, &Start, &End, &fg, &fg, FSET, P_GRAY, NULL ); } }else{ /* 牌がない場合:背景色で塗りつぶす */ SetColorRGB( &fg, 0, 102, 51 ); SetColorInfo( &fg, 0 ); Start.x = mask.left; Start.y = mask.top; End.x = mask.left + mask.width; End.y = mask.top + mask.height; /* 狭めた矩形領域の塗りつぶし */ AreaClear( g_ewk->AplForm->FormWnHandle, &Start, &End, &fg, FSET, NULL ); } }さあ、これでとりあえず起動するたびに並びの違う牌が画面一杯に表示されるようになりました。 何でしたら、何かボタンを押したところで再びシャッフルして表示し直すというのはどうでしょう? そんなに難しい物でもないので、色々と書き換えて試してみてください。