Visual Studio C+ 2008 Express Editionを使用しています。
内容はまず640×480の絵を縦3横4に切り分け、ランダムに配置。(絵はmediaファイルのpicture.jpgで保存)
その後、①切り分けられたどこかの画像をクリックし、②入れ替えたい画像をクリックすることで①と②場所が入れ替わる
例:(①縦2横3の画像をクリック ②縦3横4の画像をクリック 場所が入れ替わる)
これを繰り返していき、最終的に正しい絵が完成するというものです
不具合の内容は、なぜか②のクリック時に画像が一回り大きくなってしまい、①の画像も同様に大きくなってしまい、その状態で入れ替えが発生するので、繰り返していくと絵自体がぐちゃぐちゃになってしまいます。
説明がへたで本当にすいません。 原因が全くわからない状態です。よろしくお願いします。
以下ソースコードです
pazzle.h
#include <windows.h>
#include <tchar.h>
#include <gdiplus.h>
#include <stdlib.h>
#include <time.h>
//定数の定義
//ウィンドウクラス名
const TCHAR *MYWNDCLASSNAME = _T("__LB_PAZZLE_WINDOW");
//ウィンドウサイズ
const int APPWINDOW_W = 640;
const int APPWINDOW_H = 480;
//カードサイズ
static const int CARDW = 160;
static const int CARDH = 160;
//カードの並べ方
static const int CARDCOL = 4;
static const int CARDROW = 3;
//カードの種類数
static const int CARDNUM = 12;
//置かれたカードの情報
struct CardInfo{
int cardid; //カードの番号
BOOL opened;
};
struct OpenedCardInfo{
int cardid; //カードの番号
int col; //列位置
int row; //行位置
};
//関数プロトタイプ宣言
LRESULT WINAPI MyWinProc(HWND, UINT, WPARAM, LPARAM);
HWND createMyWindow(HINSTANCE);
void render(HWND hWnd);
void clickCheck(HWND, int, int);
#include "pazzle.h"
//パズル画像
Gdiplus::Bitmap *g_puzzle = NULL;
//カード情報
CardInfo g_cardinfosH[CARDROW];
CardInfo g_cardinfosW[CARDCOL];
int move = 0;
int checkx = 0;
int checky = 0;
int checkxx = 0;
int checkyy = 0;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hpInst,
LPSTR lpCmd, int nCmd)
{
//GDI+のスタートアップ処理
Gdiplus::GdiplusStartupInput gdiSI;
ULONG_PTR gdiToken;
if(Gdiplus::GdiplusStartup(&gdiToken, &gdiSI, NULL )!=Gdiplus::Ok)
return 0;
//画像データの読み込み
g_puzzle = new Gdiplus::Bitmap(_T("media\\picture.jpg"));
if( g_puzzle->GetLastStatus() != Gdiplus::Ok )
{
MessageBox(NULL,_T("画像ファイルが開けません"),
_T("パズル"), MB_OK);
return 0;
}
//カード情報初期化
CardInfo hcards[CARDROW];
CardInfo wcards[CARDCOL];
ZeroMemory(g_cardinfosH, sizeof(g_cardinfosH));
ZeroMemory(g_cardinfosW, sizeof(g_cardinfosW));
ZeroMemory(hcards, sizeof(hcards));
ZeroMemory(wcards, sizeof(wcards));
for(int i=0; i<CARDROW; i++){
hcards[i].cardid = i % CARDROW;
}
for(int i=0; i<CARDCOL; i++){
wcards[i].cardid = i % CARDCOL;
}
//シャッフル開始
srand( (unsigned int)time(NULL) ); //乱数の種
for(int x=0; x<CARDROW; x++){
int r;
do{
r = rand() % (CARDROW);
}while(hcards[r].opened==TRUE);
//シャッフル前配列からシャッフル後へ
g_cardinfosH[x].cardid = hcards[r].cardid;
hcards[r].opened = TRUE; //抜いた印
}
for(int y=0; y<CARDCOL; y++){
int r;
do{
r = rand() % (CARDCOL);
}while(wcards[r].opened==TRUE);
//シャッフル前配列からシャッフル後へ
g_cardinfosW[y].cardid = wcards[r].cardid;
wcards[r].opened = TRUE; //抜いた印
}
HWND hWnd = createMyWindow(hInst);
if( hWnd == NULL ) return 0;
//ウィンドウの表示
ShowWindow( hWnd, nCmd );
UpdateWindow( hWnd );
//メッセージループ
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
if (bRet == -1) {
break;
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
//終了処理
UnregisterClass( MYWNDCLASSNAME, hInst );
delete g_puzzle;
Gdiplus::GdiplusShutdown(gdiToken);
return msg.wParam;
}
//クラス登録とウィンドウ作成
HWND createMyWindow(HINSTANCE hInst){
//ウィンドウクラスの登録
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MyWinProc;
wc.cbClsExtra = 0L;
wc.cbWndExtra = 0L;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = MYWNDCLASSNAME;
wc.hIconSm = NULL;
if( RegisterClassEx( &wc ) == 0 ) return 0;
//ウィンドウを中央に表示するための準備
RECT deskRect;
int width = APPWINDOW_W + GetSystemMetrics(SM_CXFIXEDFRAME) * 2;
int height = APPWINDOW_H + GetSystemMetrics(SM_CYFIXEDFRAME) * 2
+ GetSystemMetrics(SM_CYCAPTION);
GetWindowRect(GetDesktopWindow(), &deskRect); //デスクトップサイズを取得
//ウィンドウの作成
return CreateWindowEx( 0, MYWNDCLASSNAME,
_T("パズル"),
WS_OVERLAPPED| WS_SYSMENU | WS_MINIMIZEBOX,
deskRect.right/2 - width /2, deskRect.bottom/2 - height/2,
width, height,
NULL, NULL, hInst, NULL );
}
//ウィンドウプロシージャ
LRESULT WINAPI MyWinProc(HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg){
case WM_DESTROY: //プログラム終了時
PostQuitMessage(0); //WM_QUITを送出
break;
case WM_PAINT:
render(hWnd);
break;
case WM_LBUTTONDOWN:
clickCheck(hWnd, LOWORD(lParam), HIWORD(lParam));
break;
default:
//その他メッセージの処理
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
//クリックチェック
void clickCheck(HWND hWnd, int mx, int my){
//カード位置を調べる
int col = mx / CARDW;
int row = my / CARDH;
if(move == 1){
checkx = col;
checky = row;
move++;}
else if(move == 2){
checkxx = col;
checkyy = row;
InvalidateRect(hWnd, NULL, FALSE);}
}
//画面描画
void render(HWND hWnd){
PAINTSTRUCT ps;
HDC hDC = BeginPaint( hWnd, &ps );
//画像表示
Gdiplus::Graphics g(hDC);
if(move == 0){
int h = 0;
int w = 0;
for(int y=0; y < CARDROW; y++){
for(int x=0; x < CARDCOL; x++){
h = g_cardinfosH[y].cardid;
w = g_cardinfosW[x].cardid;
g.DrawImage(g_puzzle, x * CARDW, y * CARDH,
w * CARDW, h * CARDH, CARDW, CARDH, Gdiplus::UnitPixel);}}
move++;}
else if(move == 2){
CardInfo hcards[CARDROW];
CardInfo wcards[CARDCOL];
int h = g_cardinfosH[checky].cardid;
int w = g_cardinfosW[checkx].cardid;
g.DrawImage(g_puzzle, checkxx * CARDW, checkyy * CARDH,
w * CARDW, h * CARDH, CARDW, CARDH, Gdiplus::UnitPixel);
h = g_cardinfosH[checkyy].cardid;
w = g_cardinfosW[checkxx].cardid;
g.DrawImage(g_puzzle, checkx * CARDW, checky * CARDH,
w * CARDW, h * CARDH, CARDW, CARDH, Gdiplus::UnitPixel);
hcards[checky].cardid = g_cardinfosH[checkyy].cardid;
wcards[checkx].cardid = g_cardinfosW[checkxx].cardid;
g_cardinfosH[checkyy].cardid = g_cardinfosH[checky].cardid;
g_cardinfosW[checkxx].cardid = g_cardinfosW[checkx].cardid;
g_cardinfosH[checky].cardid = hcards[checky].cardid;
g_cardinfosW[checkx].cardid = wcards[checkx].cardid;
move--;
}
//描画終了
EndPaint( hWnd, &ps );
}