📄 maze.c
字号:
draw_wall(i, j, dir, hDC) /* draw a single wall */
int i, j, dir;
HDC hDC;
{
switch (dir) {
case 0:
MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * j, NULL);
(void) LineTo(hDC, border_x + grid_width * (i+1),
border_y + grid_height * j);
break;
case 1:
MoveToEx(hDC, border_x + grid_width * (i+1), border_y + grid_height * j,
NULL);
(void) LineTo(hDC, border_x + grid_width * (i+1),
border_y + grid_height * (j+1));
break;
case 2:
MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * (j+1),
NULL);
(void) LineTo(hDC, border_x + grid_width * (i+1),
border_y + grid_height * (j+1));
break;
case 3:
MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * j,
NULL);
(void) LineTo(hDC, border_x + grid_width * i,
border_y + grid_height * (j+1));
break;
}
}
static void
begin_solve_maze() /* solve it with graphical feedback */
{
static long grayPattern[] = {
0x55555555,
0xaaaaaaaa,
0x55555555,
0xaaaaaaaa,
0x55555555,
0xaaaaaaaa,
0x55555555,
0xaaaaaaaa
};
static RGBQUAD argbq[] = {
{ 0, 0, 255, 0 },
{ 255, 255, 255, 0 }
};
BITMAPINFO *pbmi;
hDC = GetDC(hWnd);
pbmi = malloc(sizeof(BITMAPINFOHEADER) + sizeof(argbq) + sizeof(grayPattern));
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = 8;
pbmi->bmiHeader.biHeight = 8;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = 1;
pbmi->bmiHeader.biCompression = BI_RGB;
(void) memcpy(pbmi->bmiColors, argbq, sizeof(argbq));
(void) memcpy(pbmi->bmiColors + 2, grayPattern, sizeof(grayPattern));
#if 0
/* FIXME Pattern brushes not yet implemented in ReactOS */
hBrushDead = CreateDIBPatternBrushPt(pbmi, DIB_RGB_COLORS);
#else
hBrushDead = CreateSolidBrush(RGB(255, 0, 0));
#endif
// hBrushDead = CreateHatchBrush(HS_DIAGCROSS, RGB(255, 0, 0));
free(pbmi);
hBrushLiving = CreateSolidBrush(RGB(0, 255, 0));
/* plug up the surrounding wall */
maze[start_x][start_y] |= (WALL_TOP >> start_dir);
maze[end_x][end_y] |= (WALL_TOP >> end_dir);
/* initialize search path */
pathi = 0;
path[pathi].x = end_x;
path[pathi].y = end_y;
path[pathi].dir = -1;
}
static int
solve_maze() /* solve it with graphical feedback */
{
int ret;
int action_done;
do {
action_done = 1;
if ( ++path[pathi].dir >= 4 ) {
pathi--;
draw_solid_square( (int)(path[pathi].x), (int)(path[pathi].y),
(int)(path[pathi].dir), hDC, hBrushDead);
ret = 0;
}
else if ( ! (maze[path[pathi].x][path[pathi].y] &
(WALL_TOP >> path[pathi].dir)) &&
( (pathi == 0) || ( (path[pathi].dir !=
(int)(path[pathi-1].dir+2)%4) ) ) ) {
enter_square(pathi, hDC, hBrushLiving);
pathi++;
if ( maze[path[pathi].x][path[pathi].y] & START_SQUARE ) {
DeleteObject(hBrushLiving);
DeleteObject(hBrushDead);
ReleaseDC(hWnd, hDC);
ret = 1;
} else {
ret = 0;
}
} else {
action_done = 0;
}
} while (! action_done);
return ret;
}
static void
enter_square(int n, HDC hDC, HBRUSH hBrush) /* move into a neighboring square */
{
draw_solid_square( (int)path[n].x, (int)path[n].y,
(int)path[n].dir, hDC, hBrush);
path[n+1].dir = -1;
switch (path[n].dir) {
case 0: path[n+1].x = path[n].x;
path[n+1].y = path[n].y - 1;
break;
case 1: path[n+1].x = path[n].x + 1;
path[n+1].y = path[n].y;
break;
case 2: path[n+1].x = path[n].x;
path[n+1].y = path[n].y + 1;
break;
case 3: path[n+1].x = path[n].x - 1;
path[n+1].y = path[n].y;
break;
}
}
static void
start_timer(HWND hWnd, int iTimeout)
{
waiting = TRUE;
SetTimer(hWnd, 1, iTimeout, NULL);
}
/****************************************************************************
FUNCTION: WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
COMMENTS:
Windows recognizes this function by name as the initial entry point
for the program. This function calls the application initialization
routine, if no other instance of the program is running, and always
calls the instance initialization routine. It then executes a message
retrieval and dispatch loop that is the top-level control structure
for the remainder of execution. The loop is terminated when a WM_QUIT
message is received, at which time this function exits the application
instance by returning the value passed by PostQuitMessage().
If this function must abort before entering the message loop, it
returns the conventional value NULL.
****************************************************************************/
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
HDC hDC;
if (!hPrevInstance) { /* Other instances of app running? */
if (!InitApplication(hInstance)) { /* Initialize shared things */
return (FALSE); /* Exits if unable to initialize */
}
}
/* Perform initializations that apply to a specific instance */
if (!InitInstance(hInstance, nCmdShow)) {
return (FALSE);
}
waiting = FALSE;
state = 1;
/* Acquire and dispatch messages until a WM_QUIT message is received. */
while (0 != state) {
if (waiting) {
(void) WaitMessage();
}
while (0 != state && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (WM_QUIT == msg.message) {
state = 0;
} else {
DispatchMessage(&msg); /* Dispatches message to window */
}
}
switch (state) {
case 1:
initialize_maze();
state = 2;
break;
case 2:
hDC = GetDC(hWnd);
SendMessage(hWnd, WM_ERASEBKGND, (WPARAM) hDC, (LPARAM) 0);
draw_maze_border(hWnd, hDC);
ReleaseDC(hWnd, hDC);
state = 3;
break;
case 3:
create_maze();
state = 4;
break;
case 4:
start_timer(hWnd, pre_solve_delay);
state = 5;
break;
case 5:
if (! waiting) {
state = 6;
}
break;
case 6:
begin_solve_maze();
if (0 != solve_delay) {
start_timer(hWnd, solve_delay);
state = 7;
} else {
state = 8;
}
break;
case 7:
if (! waiting) {
state = 8;
}
break;
case 8:
if (! solve_maze()) {
if (0 != solve_delay) {
start_timer(hWnd, solve_delay);
state = 7;
}
} else {
state = 9;
}
break;
case 9:
start_timer(hWnd, post_solve_delay);
state = 10;
break;
case 10:
if (! waiting) {
state = 11;
}
break;
case 11:
state = 1;
break;
}
}
return (msg.wParam); /* Returns the value from PostQuitMessage */
}
/****************************************************************************
FUNCTION: InitApplication(HINSTANCE)
PURPOSE: Initializes window data and registers window class
COMMENTS:
This function is called at initialization time only if no other
instances of the application are running. This function performs
initialization tasks that can be done once for any number of running
instances.
In this case, we initialize a window class by filling out a data
structure of type WNDCLASS and calling the Windows RegisterClass()
function. Since all instances of this application use the same window
class, we only need to do this when the first instance is initialized.
****************************************************************************/
static BOOL InitApplication(HINSTANCE hInstance)
{
WNDCLASS wc;
// Fill in window class structure with parameters that describe the
// main window.
wc.style = CS_HREDRAW | CS_VREDRAW;// Class style(s).
wc.lpfnWndProc = (WNDPROC)WndProc; // Window Procedure
wc.cbClsExtra = 0; // No per-class extra data.
wc.cbWndExtra = 0; // No per-window extra data.
wc.hInstance = hInstance; // Owner of this class
wc.hIcon = LoadIcon (hInstance, szAppName); // Icon name from .RC
wc.hCursor = LoadCursor(NULL, (LPCTSTR) IDC_ARROW);// Cursor
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);// Default color
wc.lpszMenuName = NULL; // No menu
wc.lpszClassName = szAppName; // Name to register as
// Register the window class and return success/failure code.
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HINSTANCE, int)
PURPOSE: Saves instance handle and creates main window
COMMENTS:
This function is called at initialization time for every instance of
this application. This function performs initialization tasks that
cannot be shared by multiple instances.
In this case, we save the instance handle in a static variable and
create and display the main program window.
****************************************************************************/
static BOOL InitInstance(
HINSTANCE hInstance,
int nCmdShow)
{
/* Save the instance handle in static variable, which will be used in
many subsequence calls from this application to Windows. */
hInst = hInstance; /* Store instance handle in our global variable */
/* Create a main window for this application instance. */
hWnd = CreateWindow(
szAppName, /* See RegisterClass() call. */
szTitle, /* Text for window title bar. */
WS_OVERLAPPEDWINDOW,/* Window style. */
0, 0, CW_USEDEFAULT, CW_USEDEFAULT, /* Use default positioning */
NULL, /* Overlapped windows have no parent. */
NULL, /* Use the window class menu. */
hInstance, /* This instance owns this window. */
NULL /* We don't use any data in our WM_CREATE */
);
// If window could not be created, return "failure"
if (!hWnd) {
return (FALSE);
}
// Make the window visible; update its client area; and return "success"
ShowWindow(hWnd, nCmdShow); // Show the window
UpdateWindow(hWnd); // Sends WM_PAINT message
return (TRUE); // We succeeded...
}
static BOOL
OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
{
RECT rc;
int size;
srand((unsigned) time(NULL));
#if 0
/* FIXME GetPrivateProfileInt not yet implemented in ReactOS */
size = GetPrivateProfileInt("maze", "gridsize", 0, "maze.ini");
pre_solve_delay = GetPrivateProfileInt("maze", "predelay", 5000,
"maze.ini");
post_solve_delay = GetPrivateProfileInt("maze", "postdelay", 5000,
"maze.ini");
solve_delay = GetPrivateProfileInt("maze", "solvedelay", 10,
"maze.ini");
#else
size = 10;
pre_solve_delay = 5000;
post_solve_delay = 5000;
solve_delay = 20;
#endif
if (size < 2) {
size = 7 + (rand() % 30);
}
grid_width = grid_height = size;
bw = (size > 6 ? 3 : (size-1)/2);
GetClientRect(hWnd, &rc);
set_maze_sizes(rc.right - rc.left, rc.bottom - rc.top);
return TRUE;
}
void OnTimer(HWND hwnd, UINT id)
{
waiting = FALSE;
}
/****************************************************************************
FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
PURPOSE: Processes messages
MESSAGES:
WM_DESTROY - destroy window
COMMENTS:
****************************************************************************/
LRESULT CALLBACK WndProc(
HWND hWnd, // window handle
UINT message, // type of message
WPARAM wParam, // additional information
LPARAM lParam) // additional information
{
PAINTSTRUCT ps;
switch (message) {
case WM_CREATE:
OnCreate(hWnd, (LPCREATESTRUCT) lParam);
break;
case WM_PAINT:
BeginPaint(hWnd, &ps);
state = 1;
EndPaint(hWnd, &ps);
case WM_TIMER:
OnTimer(hWnd, wParam);
break;
case WM_DESTROY: // message: window being destroyed
PostQuitMessage(0);
break;
default: // Passes it on if unproccessed
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -