首页 > 代码库 > [游戏模版18] Win32 五子棋

[游戏模版18] Win32 五子棋

 

>_<:Learning its AI logic.

>_<:resource

>_<:code:

  1 #include <windows.h>
  2 // C 运行时头文件
  3 #include <stdlib.h>
  4 #include <cstdio>
  5 #include <malloc.h>
  6 #include <memory.h>
  7 #include <tchar.h>
  8 #include <time.h>
  9 #include <string>
 10 #include <cmath>
 11 
 12 #define MAX_LOADSTRING 100
 13 // 全局变量:
 14 HINSTANCE hInst;                                // 当前实例
 15 TCHAR szTitle[MAX_LOADSTRING];                    // 标题栏文本
 16 TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名
 17 HBITMAP cheers[2];
 18 HDC hdc,mdc,bufdc;
 19 HWND hWnd;
 20 DWORD tPre,tNow;
 21 int board[10][10];     //记录棋盘上格子的信息0,1,2分标表示玩家棋子、电脑棋子、空
 22 bool ptab[10][10][192];    //玩家获胜表
 23 bool ctab[10][10][192];    //电脑获胜表
 24 int win[2][192];
 25 int num[2];                //分别计算玩家和计算机下棋个数
 26 bool turn,over;//turn 用来指示是有哪一方下棋,true玩家;false电脑;;over 指示棋局是否结束,ture结束
 27 int begin;
 28 int winner;    //指示当前棋局谁赢0表示玩家赢;1表示电脑赢;2表示平局
 29 
 30 // 此代码模块中包含的函数的前向声明:
 31 ATOM                MyRegisterClass(HINSTANCE hInstance);
 32 BOOL                InitInstance(HINSTANCE, int);
 33 LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
 34 INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
 35 void                MyPaint(HDC hdc);
 36 void                InitGame();//游戏初始操作
 37 void                ComTurn();//计算机下棋时计算分数决定下棋位置
 38 
 39 int APIENTRY _tWinMain(HINSTANCE hInstance,
 40                      HINSTANCE hPrevInstance,
 41                      LPTSTR    lpCmdLine,
 42                      int       nCmdShow){
 43 
 44     MSG msg;
 45     MyRegisterClass(hInstance);
 46     // 执行应用程序初始化:
 47     if (!InitInstance (hInstance, nCmdShow)){
 48         return FALSE;
 49     }
 50     // 主消息循环:
 51     while (GetMessage(&msg, NULL, 0, 0)){
 52         TranslateMessage(&msg);
 53         DispatchMessage(&msg);
 54     }
 55     return (int) msg.wParam;
 56 }
 57 
 58 //  函数: MyRegisterClass()
 59 //
 60 //  目的: 注册窗口类。
 61 ATOM MyRegisterClass(HINSTANCE hInstance){
 62     WNDCLASSEX wcex;
 63 
 64     wcex.cbSize = sizeof(WNDCLASSEX);
 65 
 66     wcex.style            = CS_HREDRAW | CS_VREDRAW;
 67     wcex.lpfnWndProc    = WndProc;
 68     wcex.cbClsExtra        = 0;
 69     wcex.cbWndExtra        = 0;
 70     wcex.hInstance        = hInstance;
 71     wcex.hIcon            = NULL;
 72     wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
 73     wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
 74     wcex.lpszMenuName    = "Beautifulzzzz";
 75     wcex.lpszClassName    = "Beautifulzzzz";
 76     wcex.hIconSm        = NULL;
 77 
 78     return RegisterClassEx(&wcex);
 79 }
 80 
 81 //
 82 //   函数: InitInstance(HINSTANCE, int)
 83 //
 84 //   目的: 保存实例句柄并创建主窗口
 85 //
 86 //   注释:
 87 //
 88 //        在此函数中,我们在全局变量中保存实例句柄并
 89 //        创建和显示主程序窗口。
 90 //        棋盘拼接以及调用InitGame()开始棋局
 91 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){
 92    HBITMAP tile,bmp;
 93    int rowNum,colNum;
 94    int i,x,y;
 95 
 96    hInst = hInstance; // 将实例句柄存储在全局变量中
 97 
 98    begin=9;
 99    hWnd = CreateWindow("Beautifulzzzz","Beautifulzzzz", WS_OVERLAPPEDWINDOW,
100       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
101 
102    if (!hWnd)
103    {
104       return FALSE;
105    }
106 
107    MoveWindow(hWnd,10,10,480,550,true);
108    ShowWindow(hWnd, nCmdShow);
109    UpdateWindow(hWnd);
110 
111    hdc=GetDC(hWnd);
112    mdc=CreateCompatibleDC(hdc);
113    bufdc=CreateCompatibleDC(hdc);
114 
115    bmp=CreateCompatibleBitmap(hdc,450,450);
116    SelectObject(mdc,bmp);
117 
118    tile=(HBITMAP)LoadImageA(NULL,"tile.bmp",IMAGE_BITMAP,45,45,LR_LOADFROMFILE);
119    cheers[0]=(HBITMAP)LoadImageA(NULL,"cheers[0].bmp",IMAGE_BITMAP,38,38,LR_LOADFROMFILE);
120    cheers[1]=(HBITMAP)LoadImageA(NULL,"cheers[1].bmp",IMAGE_BITMAP,38,38,LR_LOADFROMFILE);
121 
122    for(i=0;i<100;i++)//产生棋盘
123    {
124        rowNum=i/10;
125        colNum=i%10;
126        x=colNum*45;
127        y=rowNum*45;
128 
129        SelectObject(bufdc,tile);
130        BitBlt(mdc,x,y,45,45,bufdc,0,0,SRCCOPY);
131    }
132 
133    InitGame();//初始化
134 
135    SetTimer(hWnd,1,200,NULL);
136    MyPaint(hdc);
137 
138    begin=8;
139    return TRUE;
140 }
141 
142 //
143 //  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
144 //
145 //  目的: 处理主窗口的消息。
146 //
147 //  WM_COMMAND    - 处理应用程序菜单
148 //  WM_PAINT    - 绘制主窗口
149 //  WM_DESTROY    - 发送退出消息并返回
150 //
151 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
152     int wmId, wmEvent;
153     PAINTSTRUCT ps;
154     int x,y,m,n,i;
155 
156     switch (message){
157     case WM_TIMER:
158         A:MyPaint(hdc);
159         break;
160     case WM_KEYDOWN://按下见消息
161         switch(wParam){
162         case VK_ESCAPE:
163             PostQuitMessage(0);
164             break;
165         case VK_F1:
166             InitGame();
167             break;
168         }
169         break;
170     case WM_LBUTTONDOWN:
171         if(!over)
172             if(turn)
173             {
174                 x=LOWORD(lParam);
175                 y=HIWORD(lParam);
176 
177                 if(x>10 && x<460 && y>10 && y<460)
178                 {
179                     m=(int)floor((double)((x-10)/45));
180                     n=(int)floor((double)((y-10)/45));
181 
182                     if(board[m][n]==2)
183                     {
184                         board[m][n]=0;
185                         num[0]++;
186 
187                         if(num[0]==50 && num[1]==50)
188                         {
189                             winner=2;
190                             over=true;
191                         }
192                         else for(i=0;i<192;i++)
193                         {
194                             if(ptab[m][n][i])
195                             {
196                                 win[0][i]++;
197                                 ctab[m][n][i]=false;
198                                 win[1][i]=7;
199 
200                                 if(win[0][i]==5)
201                                 {
202                                     winner=0;
203                                     over=true;
204                                 }
205                             }
206                         }
207                     turn=false;//换由计算机下
208                 }
209             }
210         }
211         break;
212     case WM_PAINT:
213         if(begin==8){
214         hdc = BeginPaint(hWnd, &ps);
215         goto A;// TODO: 在此添加任意绘图代码...
216         EndPaint(hWnd, &ps);}
217         break;
218     case WM_DESTROY:
219         DeleteDC(mdc);
220         DeleteDC(bufdc);
221         DeleteObject(cheers[0]);
222         DeleteObject(cheers[1]);
223 
224         ReleaseDC(hWnd,hdc);
225 
226         PostQuitMessage(0);
227         break;
228     default:
229         return DefWindowProc(hWnd, message, wParam, lParam);
230     }
231     return 0;
232 }
233 
234 //初始化棋盘
235 //1、设定棋盘初始状态及获胜表内容
236 //2、决定先下子的一方`
237 void InitGame(){
238     int i,j,k;
239     int count=0;
240 
241     over=false;
242     num[0]=num[1]=0;
243 
244 
245     //设定玩家与计算机在各个获胜组合中的棋子数
246     for(i=0;i<192;i++){

247         win[0][i]=0;
248         win[1][i]=0;
249     }
250 
251     //初始化棋盘状态
252     for(i=0;i<10;i++)
253         for(j=0;j<10;j++)
254             board[i][j]=2;
255 
256     //设定水平方向的获胜组合
257     for(i=0;i<10;i++){
258         for(j=0;j<6;j++){
259             for(k=0;k<5;k++){//5个棋子1个获胜组合
260 
261                 ptab[i][j+k][count]=true;
262                 ctab[i][j+k][count]=true;
263             }
264             count++;
265         }
266     }
267 
268     //设定垂直方向的获胜组合
269     for(i=0;i<10;i++){
270         for(j=0;j<6;j++){
271             for(k=0;k<5;k++){
272                 ptab[j+k][i][count]=true;
273                 ctab[j+k][i][count]=true;
274             }
275             count++;
276         }
277     }
278 
279     //设定正对角线方向上的获胜组合
280     for(i=0;i<6;i++){
281         for(j=0;j<6;j++){
282             for(k=0;k<5;k++){
283                 ptab[j+k][i+k][count]=true;
284                 ctab[j+k][i+k][count]=true;
285             }
286             count++;
287         }
288     }
289 
290     //设定反对角线方向的获胜组合
291     for(i=0;i<6;i++){
292         for(j=9;j>=4;j--){
293             for(k=0;k<5;k++){
294                 ptab[j-k][i+k][count]=true;
295                 ctab[j-k][i+k][count]=true;
296             }
297             count++;
298         }
299     }
300 
301     //随机数决定由哪一方先下棋子
302     srand(GetTickCount());
303     if(rand()%2==0)
304         turn=true;
305     else
306         turn=false;
307 }
308 
309 //计算机下棋函数
310 //1、计算获胜分数
311 //2、选择最佳位置进行下棋
312 void ComTurn(){
313     int grades[2][10][10];
314     int m,n,i,max=0;
315     int u,v;
316 
317     for(m=0;m<10;m++){
318         for(n=0;n<10;n++){
319             grades[0][m][n]=0;
320             grades[1][m][n]=0;
321 
322             if(board[m][n]==2){
323                 for(i=0;i<192;i++){
324                     //计算玩家在空棋格上的获胜分数
325                     if(ptab[m][n][i] && win[0][i]!=7){
326                         switch(win[0][i]){
327                         case 0:
328                             grades[0][m][n]+=1;
329                             break;
330                         case 1:
331                             grades[0][m][n]+=200;
332                             break;
333                         case 2:
334                             grades[0][m][n]+=400;
335                             break;
336                         case 3:
337                             grades[0][m][n]+=2000;
338                             break;
339                         case 4:
340                             grades[0][m][n]+=10000;
341                             break;
342                         }
343                     }
344 
345                     //计算计算机在空格上的获胜分数
346                     if(ctab[m][n][i] && win[1][i]!=7){
347                         switch(win[1][i]){
348                         case 0:
349                             grades[1][m][n]+=1;
350                             break;
351                         case 1:
352                             grades[1][m][n]+=220;
353                             break;
354                         case 2:
355                             grades[1][m][n]+=420;
356                             break;
357                         case 3:
358                             grades[1][m][n]+=2100;
359                             break;
360                         case 4:
361                             grades[1][m][n]+=20000;
362                             break;
363                         }
364                     }
365                 }
366 
367                 if(max==0){
368                     u=m;
369                     v=n;
370                 }
371 
372                 if(grades[0][m][n]>max){
373                     max=grades[0][m][n];
374                     u=m;
375                     v=n;
376                 }else if(grades[0][m][n]==max){
377                     if(grades[1][m][n]>grades[1][u][v]){
378                         u=m;
379                         v=n;
380                     }
381                 }
382 
383                 if(grades[1][m][n]>max){
384                     max=grades[1][m][n];
385                     u=m;
386                     v=n;
387                 }else if(grades[1][m][n]==max){
388                     if(grades[0][m][n]>grades[0][u][v]){
389                         u=m;
390                         v=n;
391                     }
392                 }
393             }
394         }
395     }
396 
397     board[u][v]=1;//设定为计算机的棋子
398     num[1]++;
399 
400     if(num[0]==50 && num[1]==50){
401         winner=2;
402         over=true;
403     }else for(i=0;i<192;i++){
404         if(ctab[u][v][i]){
405             win[1][i]++;
406             ptab[u][v][i]=false;
407             win[0][i]=7;
408 
409             if(win[1][i]==5){
410                 winner=1;
411                 over=true;
412             }
413         }
414     }
415     turn=true;
416 }
417 
418 //MyPaint()
419 void MyPaint(HDC hdc){
420     int m,n;
421     char* str;
422     char* whitestr="                                                                                                 ";
423 
424     if(over){
425         switch(winner){
426         case 0:
427             str="您赢了!按下[F1]键可重新进行游戏..";
428             break;
429         case 1:
430             str="计算机赢了!按下[F1]键可重新进行游戏..";
431             break;
432         case 2:
433             str="不分胜负!按下[F1]键可重新进行游戏..";
434             break;
435         }
436         TextOutA(hdc,10,470,whitestr,strlen(whitestr));
437         TextOutA(hdc,10,470,str,strlen(str));
438     }
439 
440     else if(!turn){   //电脑下棋
441         TextOutA(hdc,10,470,whitestr,strlen(whitestr));
442         str="计算机思考中...";
443         TextOutA(hdc,10,470,str,strlen(str));
444         ComTurn();
445     }else{
446         TextOutA(hdc,10,470,whitestr,strlen(whitestr));
447         str="该您下了...";
448         TextOutA(hdc,10,470,str,strlen(str));
449     }
450 
451     for(m=0;m<10;m++)
452         for(n=0;n<10;n++)
453         {
454             if(board[m][n]==0)//贴上玩家棋子
455             {
456                 SelectObject(bufdc,cheers[0]);
457                 BitBlt(mdc,m*45+3,n*45+3,38,38,bufdc,0,0,SRCCOPY);
458             }
459             else if(board[m][n]==1)//贴上计算机棋子
460             {
461                 SelectObject(bufdc,cheers[1]);
462                 BitBlt(mdc,m*45+3,n*45+3,38,38,bufdc,0,0,SRCCOPY);
463             }
464             else
465             {
466                 SelectObject(bufdc,cheers[1]);
467                 BitBlt(mdc,m*45+3,n*45+3,38,38,bufdc,0,0,WHITENESS);
468             }
469         }
470 
471     BitBlt(hdc,10,10,450,450,mdc,0,0,SRCCOPY);
472 
473     tPre=GetTickCount();
474 }