[游戏模版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 }