I. Introduction▲
Code d'un Sokoban en pure Windows API.
Le code est composé de trois fichiers et quatre images mises dans les ressources du programme. Les grilles seront intégrées à l'exécutable afin de n'avoir qu'un seul fichier à distribuer.
II. Code complet▲
Sélectionnez
main.c
#include <windows.h>
#define LARG 32
#define NBC_X 20
#define NBC_Y 18
/* ID de menu */
#define IDM_QUIT 1
#define IDM_NEW 2
#define IDM_RNIV 3
#define IDM_ABOUT 4
/* pièces de jeu */
#define GP_WALL 1
#define GP_SOKO 2
#define GP_STOCK 4
#define GP_BOX 8
HINSTANCE hinst;
extern
char
grilles[88
][18
][20
];
POINT Init
(
char
tab[][NBC_X], int
niv)
{
int
i;
int
j;
POINT soko;
for
(
i=
0
; i<
NBC_X; i++
)
for
(
j=
0
; j<
NBC_Y; j++
)
{
tab[j][i]=
grilles[niv][j][i];
if
(
tab[j][i]==
GP_SOKO)
{
soko.x=
i;
soko.y=
j;
}
}
return
soko;
}
/**
***************************************************************************
*/
BOOL testfin
(
char
tab[][NBC_X])
{
int
i;
int
j;
for
(
i=
0
; i<
NBC_X; i++
)
for
(
j=
0
; j<
NBC_Y; j++
)
if
(
tab[j][i]==
GP_STOCK||
tab[j][i]==(
GP_STOCK|
GP_SOKO)) return
FALSE;
return
TRUE;
}
/**
***************************************************************************
*/
void
move
(
char
tab[NBC_Y][NBC_X], POINT *
soko, WPARAM wParam)
{
int
x =
0
;
int
y =
0
;
if
(
wParam==
VK_RIGHT) x=
1
;
if
(
wParam==
VK_LEFT) x=-
1
;
if
(
wParam==
VK_DOWN) y=
1
;
if
(
wParam==
VK_UP) y=-
1
;
if
(
tab[soko->
y+
y][soko->
x+
x]&
GP_WALL) return
;
if
(
tab[soko->
y+
y][soko->
x+
x]&
GP_BOX)
{
if
(
tab[soko->
y+
y+
y][soko->
x+
x+
x]&(
GP_WALL|
GP_BOX)) return
;
else
{
tab[soko->
y+
y][soko->
x+
x]&=
GP_STOCK;
tab[soko->
y+
y+
y][soko->
x+
x+
x]|=
GP_BOX;
}
}
tab[soko->
y][soko->
x]&=
GP_STOCK;
soko->
y+=
y;
soko->
x+=
x;
tab[soko->
y][soko->
x]|=
GP_SOKO;
}
/**
***************************************************************************
*/
LRESULT CALLBACK MainWndProc
(
HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static
char
tab[NBC_Y][NBC_X];
static
int
niveau;
static
POINT soko;
static
HBRUSH hbSoko;
static
HBRUSH hbWall;
static
HBRUSH hbBox;
static
HBRUSH hbStock;
static
HBRUSH hbPath;
switch
(
uMsg)
{
case
WM_CREATE:
{
niveau =
0
;
hbSoko =
CreatePatternBrush
(
LoadBitmap
(
hinst,"
soko
"
));
hbWall =
CreatePatternBrush
(
LoadBitmap
(
hinst,"
brick
"
));
hbBox =
CreatePatternBrush
(
LoadBitmap
(
hinst,"
box
"
));
hbStock =
CreatePatternBrush
(
LoadBitmap
(
hinst,"
stock
"
));
hbPath =
CreateSolidBrush
(
0x00FFFFFF
);
soko=
Init
(
tab, niveau);
return
0
;
}
case
WM_COMMAND:
if
(
LOWORD
(
wParam) ==
IDM_QUIT)
PostMessage
(
hwnd, WM_CLOSE,0
,0
);
if
(
LOWORD
(
wParam) ==
IDM_ABOUT)
MessageBox
(
hwnd, "
Sokoban by CGi !
"
, "
A Propos !
"
, MB_OK);
if
(
LOWORD
(
wParam) ==
IDM_NEW)
{
ZeroMemory
(
tab, sizeof
(
tab));
niveau =
0
;
soko=
Init
(
tab, niveau);
InvalidateRect
(
hwnd, NULL
, FALSE);
}
if
(
LOWORD
(
wParam) ==
IDM_RNIV)
{
ZeroMemory
(
tab, sizeof
(
tab));
soko=
Init
(
tab, niveau);
InvalidateRect
(
hwnd, NULL
, FALSE);
}
return
0
;
case
WM_KEYDOWN:
if
(
wParam==
VK_DOWN) move
(
tab, &
soko, wParam);
if
(
wParam==
VK_UP) move
(
tab, &
soko, wParam);
if
(
wParam==
VK_LEFT) move
(
tab, &
soko, wParam);
if
(
wParam==
VK_RIGHT) move
(
tab, &
soko, wParam);
InvalidateRect
(
hwnd, NULL
, FALSE);
if
(
testfin
(
tab))
{
MessageBox
(
hwnd, "
Bravo, on continue !
"
, "
Sokoban !
"
, MB_OK);
niveau++
;
if
(
niveau==
88
)
{
MessageBox
(
hwnd, "
Vous êtes un champion !
"
, "
Sokoban !
"
, MB_OK);
niveau=
0
;
}
ZeroMemory
(
tab, sizeof
(
tab));
soko=
Init
(
tab, niveau);
InvalidateRect
(
hwnd, NULL
, FALSE);
}
return
0
;
case
WM_PAINT:
{
int
i, j;
HDC hdc, hdcDB;
HBITMAP bmDB;
PAINTSTRUCT ps;
RECT rect, caserect;
GetClientRect
(
hwnd, &
rect);
hdc =
BeginPaint
(
hwnd, &
ps);
hdcDB =
CreateCompatibleDC
(
hdc);
bmDB =
CreateCompatibleBitmap
(
hdc, rect.right, rect.bottom);
SelectObject
(
hdcDB, bmDB);
for
(
j=
0
; j<
NBC_Y; j++
)
for
(
i=
0
; i<
NBC_X; i++
)
{
int
value =
tab[j][i];
caserect.left =
i*
LARG;
caserect.right =
i*
LARG+
LARG;
caserect.top =
j*
LARG;
caserect.bottom =
j*
LARG+
LARG;
if
(
value&
GP_STOCK) FillRect
(
hdcDB, &
caserect, hbStock);
if
(
value&
GP_BOX) FillRect
(
hdcDB, &
caserect, hbBox);
if
(
value&
GP_SOKO) FillRect
(
hdcDB, &
caserect, hbSoko);
if
(
value==
GP_WALL) FillRect
(
hdcDB, &
caserect, hbWall);
if
(
value==
0
) FillRect
(
hdcDB, &
caserect, hbPath);
}
BitBlt
(
hdc, 0
, 0
, rect.right, rect.bottom, hdcDB, 0
, 0
, SRCCOPY);
DeleteDC
(
hdcDB);
DeleteObject
(
bmDB);
EndPaint
(
hwnd, &
ps);
return
0
;
}
case
WM_DESTROY:
DeleteObject
(
hbWall);
DeleteObject
(
hbBox);
DeleteObject
(
hbStock);
DeleteObject
(
hbSoko);
DeleteObject
(
hbPath);
PostQuitMessage
(
0
);
return
0
;
default
:
return
DefWindowProc
(
hwnd, uMsg, wParam, lParam);
}
}
/**
***************************************************************************
*/
int
WINAPI WinMain
(
HINSTANCE hinstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int
nCmdShow)
{
HWND hwnd;
MSG msg;
HMENU hMenu, hSousMenu;
RECT winRect;
WNDCLASS wc;
hinst =
hinstance;
wc.style =
0
;
wc.lpfnWndProc =
MainWndProc;
wc.cbClsExtra =
0
;
wc.cbWndExtra =
0
;
wc.hInstance =
hinstance;
wc.hIcon =
LoadIcon
(
NULL
, IDI_APPLICATION);
wc.hCursor =
LoadCursor
(
NULL
, IDC_ARROW);
wc.hbrBackground =
(
HBRUSH)(
COLOR_WINDOW+
1
);
wc.lpszMenuName =
NULL
;
wc.lpszClassName =
"
MaWinClass
"
;
if
(!
RegisterClass
(&
wc)) return
FALSE;
hSousMenu =
CreateMenu
(
);
AppendMenu
(
hSousMenu, MF_STRING, IDM_NEW, "
Nouvelle partie
"
);
AppendMenu
(
hSousMenu, MF_STRING, IDM_RNIV, "
Reprendre le niveau
"
);
AppendMenu
(
hSousMenu, MF_MENUBREAK, -
1
, NULL
);
AppendMenu
(
hSousMenu, MF_STRING, IDM_ABOUT, "
A propos
"
);
AppendMenu
(
hSousMenu, MF_STRING, IDM_QUIT, "
Quitter
"
);
hMenu =
CreateMenu
(
);
AppendMenu
(
hMenu,MF_POPUP,(
UINT)hSousMenu,"
Fichier
"
);
SetRect
(&
winRect, 0
, 0
, LARG*
NBC_X, LARG*
NBC_Y);
AdjustWindowRect
(&
winRect, WS_CAPTION, TRUE);
hwnd =
CreateWindow
(
"
MaWinClass
"
, "
Sokoban
"
,
WS_SYSMENU |
WS_CAPTION |
WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT,
winRect.right-
winRect.left, winRect.bottom-
winRect.top,
NULL
, hMenu, hinstance, NULL
);
ShowWindow
(
hwnd, nCmdShow);
UpdateWindow
(
hwnd);
while
(
GetMessage
(&
msg, NULL
, 0
, 0
))
{
TranslateMessage
(&
msg);
DispatchMessage
(&
msg);
}
return
msg.wParam;
}
Le fichier ressources : images.rc
Sélectionnez
brick BITMAP brick.bmp
stock BITMAP stock.bmp
box BITMAP box.bmp
soko BITMAP soko.bmp
III. Téléchargements▲
Les grilles sont dans un fichier nommé grilles.c inclus dans l'archive à télécharger.
Les compilations ont été testées sous MinGW et Visual C.
À vos compilateurs.