1 /*------------------------------------------------------------
2 chessboard.c -- 棋盘覆盖
3
4 邝翼飞 2010
5 ------------------------------------------------------------*/
6
7 #include <windows.h>
8 #include <math.h>
9
10 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
11 void chessBoard(HWND hwnd, int tr, int tc, int dr, int dc, int ssize, int windoww);
12 // 控件声明
13 HWND hedit1, hedit2, hedit3;
14 HWND hwndButton1, hwndButton2, hwndButton3, hwndButton4;
15
16 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nCmdShow)
17 {
18 HWND hwnd;
19 MSG msg ;
20 WNDCLASS wndclass ;
21 static CHAR szAppName[]="CHESSBOARD";
22 int cxScreen, cyScreen ; // 用于获得屏幕的大小
23
24 wndclass.style = CS_HREDRAW | CS_VREDRAW ;
25 wndclass.lpfnWndProc = WndProc ;
26 wndclass.cbClsExtra = 0 ;
27 wndclass.cbWndExtra = 0 ;
28 wndclass.hInstance = hInstance ;
29 wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
30 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
31 wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
32 wndclass.lpszMenuName = NULL ;
33 wndclass.lpszClassName = szAppName ;
34
35 if (!RegisterClass (&wndclass))
36 {
37 MessageBox (NULL, TEXT ("注册窗口出错!"), szAppName, MB_ICONERROR) ;
38 return 0 ;
39 }
40
41 cxScreen = GetSystemMetrics (SM_CXSCREEN) ;
42 cyScreen = GetSystemMetrics (SM_CYSCREEN) ;
43
44 hwnd = CreateWindow ( szAppName, // 创建主窗口
45 "棋盘覆盖",
46 WS_OVERLAPPEDWINDOW & (~WS_SIZEBOX) & (~WS_MAXIMIZEBOX),
47 ( cxScreen-820 ) / 2,
48 ( cyScreen-650 ) / 2,
49 820,
50 650,
51 NULL,
52 NULL,
53 hInstance,
54 NULL ) ;
55
56 ShowWindow ( hwnd, nCmdShow ) ;
57 UpdateWindow ( hwnd ) ;
58
59 hwndButton1 = CreateWindow ("BUTTON", // 创建 【开始】 按钮
60 "开始",
61 WS_VISIBLE | WS_CHILD,
62 640,
63 5,
64 75,
65 20,
66 hwnd,
67 NULL,
68 hInstance,
69 NULL);
70 hwndButton2 = CreateWindow ( "BUTTON", // 创建 【重新设置】 按钮
71 "重新设置",
72 WS_VISIBLE | WS_CHILD,
73 640,
74 30,
75 75,
76 20,
77 hwnd,
78 NULL,
79 hInstance,
80 NULL ) ;
81 hwndButton3 = CreateWindow ( "BUTTON", // 创建 【帮助】 按钮
82 "帮助",
83 WS_VISIBLE | WS_CHILD,
84 720,
85 30,
86 75,
87 20,
88 hwnd,
89 NULL,
90 hInstance,
91 NULL ) ;
92 hwndButton4 = CreateWindow ( "BUTTON", // 创建 【退出】 按钮
93 "退出",
94 WS_VISIBLE | WS_CHILD,
95 720,
96 5,
97 75,
98 20,
99 hwnd,
100 NULL,
101 hInstance,
102 NULL ) ;
103 hedit1 = CreateWindow ( "EDIT", // 创建 【棋盘大小】 编辑框
104 "4",
105 WS_VISIBLE | WS_CHILD,
106 720,
107 55,
108 75,
109 20,
110 hwnd,
111 NULL,
112 hInstance,
113 NULL ) ;
114 hedit2 = CreateWindow ( "EDIT", // 创建 【特殊方格X轴】 编辑框
115 "0",
116 WS_VISIBLE | WS_CHILD,
117 675,
118 105,
119 35,
120 20,
121 hwnd,
122 NULL,
123 hInstance,
124 NULL ) ;
125 hedit3 = CreateWindow ( "EDIT", // 创建 【特殊方格Y轴】 编辑框
126 "0",
127 WS_VISIBLE | WS_CHILD,
128 755,
129 105,
130 35,
131 20,
132 hwnd,
133 NULL,
134 hInstance,
135 NULL ) ;
136
137 while (GetMessage (&msg, NULL, 0, 0))
138 {
139 TranslateMessage (&msg) ;
140 DispatchMessage (&msg) ;
141 }
142 return msg.wParam ;
143 }
144
145 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
146 {
147 HDC hdc ;
148 PAINTSTRUCT ps ;
149 RECT rect ;
150 HBRUSH hbrush ;
151 int x=620+50, y=160 ;
152 int dr, dc, ssize ;
153 CHAR lpsEditText[10] ;
154 int i, j ;
155
156 switch (message)
157 {
158 case WM_CREATE:
159 return 0 ;
160
161 case WM_PAINT:
162 hdc = BeginPaint (hwnd, &ps) ;
163 // 画出窗口右方的元素
164 // Sleep(500);
165 GetClientRect (hwnd, &rect) ;
166 MoveToEx (hdc, 620, 0, NULL);
167 LineTo (hdc, 620, 620) ;
168 MoveToEx (hdc, 620, 130, NULL);
169 LineTo (hdc, 820,130) ;
170 TextOut (hdc,640,55,"棋盘大小",8);
171 TextOut (hdc,640,80,"特殊方格位置",12);
172 TextOut (hdc,640,105,"横轴",4);
173 TextOut (hdc,720,105,"纵轴",4);
174 TextOut (hdc,640,135,"四种 L 型牌",11);
175 Rectangle (hdc,10,10,610,610);
176 // 第一种L形牌
177 hbrush = CreateSolidBrush ( RGB ( 255, 0, 0 ) );
178 SelectObject ( hdc, hbrush );
179 Rectangle ( hdc, x, y, x + 50, y + 50 );
180 Rectangle ( hdc, x + 50, y, x + 50 + 50, y + 50 );
181 Rectangle ( hdc, x, y + 50, x + 50, y + 50 + 50 );
182 // 第二种L形牌
183 y=160+100+8;
184 x=620+50;
185 hbrush=CreateSolidBrush( RGB ( 0, 255, 0 ) );
186 SelectObject(hdc,hbrush);
187 Rectangle(hdc,x,y,x+50,y+50);
188 Rectangle(hdc,x,y+50,x+50,y+50+50);
189 Rectangle(hdc,x+50,y+50,x+50+50,y+50+50);
190 // 第三种L形牌
191 y=160+100+8+100+8;
192 x=620+50;
193 hbrush=CreateSolidBrush ( RGB ( 0, 0, 255 ) );
194 SelectObject(hdc,hbrush);
195 Rectangle(hdc,x+50,y,x+50+50,y+50);
196 Rectangle(hdc,x+50,y+50,x+50+50,y+50+50);
197 Rectangle(hdc,x,y+50,x+50,y+50+50);
198 // 第四种L形牌
199 y=160+100+8+100+8+100+8;
200 x=620+50;
201 hbrush=CreateSolidBrush ( RGB ( 255, 255, 0 ) );
202 SelectObject(hdc,hbrush);
203 Rectangle(hdc,x,y,x+50,y+50);
204 Rectangle(hdc,x+50,y,x+50+50,y+50);
205 Rectangle(hdc,x+50,y+50,x+50+50,y+50+50);
206
207 EndPaint (hwnd, &ps) ;
208 return 0 ;
209
210 case WM_COMMAND : // 处理按钮控件产生的消息事件
211 if(lParam==(long)hwndButton4) // 退出按钮
212 {
213 PostQuitMessage (0) ;
214 return 0;
215 }
216 else if(lParam==(long)hwndButton3) // 帮助按钮
217 {
218 hdc = GetDC (hwnd) ;
219 hbrush=CreateSolidBrush ( RGB ( 255, 255, 255 ) );
220 SelectObject(hdc,hbrush);
221 Rectangle(hdc,10,10,610,610);
222 TextOut ( hdc,240,35, "程序使用说明",12 );
223 TextOut ( hdc,20,65, "请在棋盘大小右边的编辑框里输入一个正整数且为2的k次方,程序将会成一个n*n的",73 );
224 TextOut ( hdc,20,100, "棋盘,n为输入的数。然后设置特殊方格在棋盘中的坐标,注意棋盘的横纵坐标都是",73 );
225 TextOut ( hdc,20,135, "从零开始的,特殊方格将被填成黑色。做完上述步骤后按开始按钮可观察到棋盘覆",72 );
226 TextOut ( hdc,20,170, "盖的结果,按重新设置按钮将使编辑框中出现默认值并可重新设置参数。",64 );
227 DeleteObject (SelectObject (hdc, hbrush)) ;
228 ReleaseDC (hwnd, hdc) ;
229 return 0;
230 }
231 else if(lParam==(long)hwndButton1) // 开始按钮
232 {
233 GetWindowText(hedit1,lpsEditText,10);
234 ssize=atoi(lpsEditText);
235 if(ssize>64)
236 {
237 MessageBox(hwnd,"棋盘大小太大,显示效果不好!","提示",MB_OK);
238 return 0;
239 }
240 if(ssize<=0)
241 {
242 MessageBox(hwnd,"棋盘大小不能为非整数!","提示",MB_OK);
243 return 0;
244 }
245 if(ssize!=1 && ssize!=2)
246 {
247 if(ssize%2!=0)
248 {
249 MessageBox(hwnd,"棋盘大小不是2的正次方幂!","提示",MB_OK);
250 return 0;
251 }
252 else
253 {
254 for(i=3;i<ssize;i=i+2)
255 if(ssize%i==0 )
256 {
257 MessageBox(hwnd,"棋盘大小不是2的正次方幂!","提示",MB_OK);
258 return 0;
259 }
260 }
261 }
262 GetWindowText(hedit2,lpsEditText,10);
263 dr=atoi(lpsEditText);
264 GetWindowText(hedit3,lpsEditText,10);
265 dc=atoi(lpsEditText);
266 if(dr<0 || dc<0 || dr>=ssize || dc>=ssize)
267 {
268 MessageBox(hwnd,"特殊方格的坐标参数设置不正确!","提示",MB_OK);
269 return 0;
270 }
271 hdc = GetDC (hwnd) ;
272 hbrush=CreateSolidBrush ( RGB ( 255, 255, 255 ) );
273 SelectObject(hdc,hbrush);
274 Rectangle(hdc,10,10,610,610);
275 // 画出一个ssize*ssize的棋盘,方格颜色为白色
276 for(j=0;j<ssize;j++)
277 for(i=0;i<ssize;i++)
278 Rectangle ( hdc,
279 10+i*(600/ssize),
280 10+j*(600/ssize),
281 10+i*(600/ssize)+600/ssize,
282 10+j*(600/ssize)+600/ssize );
283
284 DeleteObject (SelectObject (hdc, hbrush)) ;
285 SelectObject( hdc, CreateSolidBrush ( RGB ( 0, 0, 0 ) ) );
286 // 画特殊方格,方格颜色为黑色
287 Rectangle(hdc,10+dc*(600/ssize),10+dr*(600/ssize),10+dc*(600/ssize)+600/ssize,10+dr*(600/ssize)+600/ssize);
288 DeleteObject (SelectObject (hdc, hbrush)) ;
289 ReleaseDC (hwnd, hdc) ;
290 chessBoard(hwnd,0,0,dr,dc,ssize,600);///////////////////////////////////////////////////////////
291
292 return 0;
293 }
294 else if(lParam==(long)hwndButton2) // 重新设置按钮
295 {
296 SetWindowText(hedit1,"4");
297 SetWindowText(hedit2,"0");
298 SetWindowText(hedit3,"0");
299 return 0;
300 }
301 return 0;
302
303
304 case WM_DESTROY:
305 PostQuitMessage (0) ;
306 return 0 ;
307 }
308 return DefWindowProc (hwnd, message, wParam, lParam) ;
309 }
310
311 void drawLcard1(HWND hwnd,int tr,int tc,int rectw); // 第一种方格的画法函数
312 void drawLcard2(HWND hwnd,int tr,int tc,int rectw); // 第二种方格的画法函数
313 void drawLcard3(HWND hwnd,int tr,int tc,int rectw); // 第三种方格的画法函数
314 void drawLcard4(HWND hwnd,int tr,int tc,int rectw); // 第四种方格的画法函数
315
316 void chessBoard(HWND hwnd,int tr,int tc,int dr,int dc,int ssize,int windoww) // 递归分治法覆盖棋盘
317 { // (tr,tc): 棋盘左上角坐标; (dr,dc): 特殊方格坐标; ssize: 棋盘大小(一行或一列的方格数); windoww: 棋盘宽度
318 int s; // 用于递归相当于ssize
319 int w; // 用于递归相当于windoww
320 int rectw; // 棋盘中一个方格的宽度
321
322 int flag=0; // 标志特殊方格位于哪个子棋盘区域
323 if(ssize==1)
324 return;
325 rectw=windoww/ssize;
326 if(ssize==2)
327 {
328 if(dr==tr && dc==tc)
329 {
330 Sleep(500);
331 drawLcard3(hwnd,tr,tc,rectw);
332 return;
333 }
334 else if(dr==tr && dc==tc+1)
335 {
336 Sleep(500);
337 drawLcard2(hwnd,tr,tc,rectw);
338 return;
339 }
340 else if(dr==tr+1 && dc==tc)
341 {
342 Sleep(500);
343 drawLcard4(hwnd,tr,tc,rectw);
344 return;
345 }
346 else
347 {
348 Sleep(500);
349 drawLcard1(hwnd,tr,tc,rectw);
350 return;
351 }
352 }
353
354 s=ssize/2;
355 w=windoww/2;
356
357 if(dr<tr+s && dc<tc+s) // 特殊方格位于第一个子棋盘区域
358 {
359 flag=1;
360 chessBoard(hwnd,tr,tc,dr,dc,s,w);
361 }
362 else
363 chessBoard(hwnd,tr,tc,tr+s-1,tc+s-1,s,w);
364
365
366 if(dr<tr+s && dc>=tc+s) // 特殊方格位于第二个子棋盘区域
367 {
368 flag=2;
369 chessBoard(hwnd,tr,tc+s,dr,dc,s,w);
370 }
371 else
372 chessBoard(hwnd,tr,tc+s,tr+s-1,tc+s,s,w);
373
374
375 if(dr>=tr+s && dc<tc+s) // 特殊方格位于第三个子棋盘区域
376 {
377 flag=3;
378 chessBoard(hwnd,tr+s,tc,dr,dc,s,w);
379 }
380 else
381 chessBoard(hwnd,tr+s,tc,tr+s,tc+s-1,s,w);
382
383
384 if(dr>=tr+s && dc>=tc+s) // 特殊方格位于第四个子棋盘区域
385 {
386 flag=4;
387 chessBoard(hwnd,tr+s,tc+s,dr,dc,s,w);
388 }
389 else
390 chessBoard(hwnd,tr+s,tc+s,tr+s,tc+s,s,w);
391
392 if(flag==1)
393 {
394 Sleep(500);
395 drawLcard3(hwnd,tr+s-1,tc+s-1,rectw);
396 return;
397 }
398 else if(flag==2)
399 {
400 Sleep(500);
401 drawLcard2(hwnd,tr+s-1,tc+s-1,rectw);
402 return;
403 }
404 else if(flag==3)
405 {
406 Sleep(500);
407 drawLcard4(hwnd,tr+s-1,tc+s-1,rectw);
408 return;
409 }
410 else if(flag==4)
411 {
412 Sleep(500);
413 drawLcard1(hwnd,tr+s-1,tc+s-1,rectw);
414 return;
415 }
416 return;
417 }
418
419 void drawLcard1(HWND hwnd,int tr,int tc,int rectw)
420 {
421 HDC hdc ;
422 HBRUSH hbrush;
423 int x = 10 + tc * rectw, y = 10 + tr * rectw;
424
425 hdc = GetDC (hwnd) ;
426 hbrush = CreateSolidBrush ( RGB ( 255,0,0 ) ) ;
427 SelectObject ( hdc, hbrush ) ;
428 Rectangle ( hdc, x, y, x + rectw, y + rectw ) ;
429 Rectangle ( hdc, x + rectw, y, x + 2*rectw, y + rectw ) ;
430 Rectangle ( hdc, x, y + rectw, x + rectw, y + 2*rectw ) ;
431 DeleteObject (SelectObject (hdc, hbrush)) ;
432 SelectObject ( hdc, CreatePen(PS_DOT,1, RGB ( 255,0,0 ) ) );
433 MoveToEx(hdc,x+rectw,y,NULL);
434 LineTo(hdc,x+rectw,y+rectw);
435 LineTo(hdc,x,y+rectw);
436 ReleaseDC (hwnd, hdc) ;
437 }
438
439 void drawLcard2(HWND hwnd,int tr,int tc,int rectw)
440 {
441 HDC hdc ;
442 HBRUSH hbrush;
443 int x = 10 + tc * rectw, y = 10 + tr * rectw;
444
445 hdc = GetDC (hwnd) ;
446 hbrush = CreateSolidBrush ( RGB ( 0, 255, 0 ) ) ;
447 SelectObject ( hdc, hbrush ) ;
448 Rectangle ( hdc, x, y, x + rectw, y + rectw ) ;
449 Rectangle ( hdc, x, y + rectw, x + rectw, y + 2*rectw ) ;
450 Rectangle ( hdc, x + rectw, y + rectw, x + 2*rectw, y + 2*rectw ) ;
451 DeleteObject (SelectObject (hdc, hbrush)) ;
452 SelectObject ( hdc, CreatePen(PS_DOT,1, RGB ( 0, 255, 0 ) ) );
453 MoveToEx(hdc,x,y+rectw,NULL);
454 LineTo(hdc,x+rectw,y+rectw);
455 LineTo(hdc,x+rectw,y+2*rectw);
456 ReleaseDC (hwnd, hdc) ;
457 }
458
459 void drawLcard3(HWND hwnd,int tr,int tc,int rectw)
460 {
461 HDC hdc ;
462 HBRUSH hbrush;
463 int x = 10 + tc * rectw, y = 10 + tr * rectw;
464
465 hdc = GetDC (hwnd) ;
466 hbrush = CreateSolidBrush ( RGB ( 0, 0, 255 ) ) ;
467 SelectObject ( hdc, hbrush ) ;
468 Rectangle ( hdc, x + rectw, y, x + 2*rectw, y + rectw ) ;
469 Rectangle ( hdc, x, y + rectw, x + rectw, y + 2*rectw ) ;
470 Rectangle ( hdc, x + rectw, y + rectw, x + 2*rectw, y + 2*rectw ) ;
471 DeleteObject (SelectObject (hdc, hbrush)) ;
472 SelectObject ( hdc, CreatePen(PS_DOT,1, RGB ( 0, 0, 255 ) ) );
473 MoveToEx(hdc,x+2*rectw,y+rectw,NULL);
474 LineTo(hdc,x+rectw,y+rectw);
475 LineTo(hdc,x+rectw,y+2*rectw);
476 ReleaseDC (hwnd, hdc) ;
477 }
478
479 void drawLcard4(HWND hwnd,int tr,int tc,int rectw)
480 {
481 HDC hdc ;
482 HBRUSH hbrush;
483 int x = 10 + tc * rectw, y = 10 + tr * rectw;
484
485 hdc = GetDC (hwnd) ;
486 hbrush = CreateSolidBrush ( RGB ( 255, 255, 0 ) ) ;
487 SelectObject ( hdc, hbrush ) ;
488 Rectangle ( hdc, x, y, x + rectw, y + rectw ) ;
489 Rectangle ( hdc, x + rectw, y, x + 2*rectw, y + rectw ) ;
490 Rectangle ( hdc, x + rectw, y + rectw, x + 2*rectw, y + 2*rectw ) ;
491 DeleteObject (SelectObject (hdc, hbrush)) ;
492 SelectObject ( hdc, CreatePen(PS_DOT,1, RGB ( 255, 255, 0 ) ) );
493 MoveToEx(hdc,x+rectw,y,NULL);
494 LineTo(hdc,x+rectw,y+rectw);
495 LineTo(hdc,x+2*rectw,y+rectw);
496 ReleaseDC (hwnd, hdc) ;
497 }