[Win32] 五子棋双人版

2002年,大三的时候,学习Win32SDK,并使用GDI做了一个五子棋的小游戏

最早完成了双人对战版后,想做AI版,以及网路对战版

不过可惜的是之后就没时间去开发了

 

[Win32] 五子棋双人版_第1张图片

 

/* 對戰五子棋,目前開發僅完成1/3,僅可單機雙打。 尚未完成AI功能,以及網路連線對戰功能。 悔棋亦尚未完成,實際上不打算設計悔棋功能,因為這樣下棋沒意思。 若要設定悔棋,一次僅可退一步。 AI決定用陣列儲存已下過的位置,再做判斷。 網路功能則沒書好看。 */ #include <windows.h> #include "resource.h" //----------------------------------------------------------- #define player1 1 //定義玩家1 #define player2 2 #define VS_COM 1 //定義遊戲方式,對電腦 #define VS_PLAYER 2 //單機對戰 #define VS_CONNECT 3 //連線對戰 #define BkColor RGB(0,150,250) //定義棋盤顏色 #define board_width 20 //棋盤格寬度 //----------------------------------------------------------- static int chessman[15][15], //棋盤陣列,判斷是否已下子 who_play, //判斷現在誰玩 play_mode; //判斷遊戲方式 static BOOL play; //判斷是否可下子 static TCHAR *chess[3]={"","黑子","白子"}; //----------------------------------------------------------- struct playerchoice //定義結構儲存棋子的位置 { int x; int y; }; /* struct SetChessman //定義儲存下棋情況的結構 { int index; //紀錄現在為第幾步棋 int set[150][2]; //儲存每一步棋的位置 BOOL live_three; //是否有活三 int four_next[2][2]; //有活三則儲存活四座標 BOOL dead_four; //是否有死四 int five_next[2]; //有死四則儲存勝利座標 }; */ //---------------------------------------------------------- static playerchoice chess_dir[4]; //儲存方向 //static SetChessman sc1,sc2; //宣告結構儲存下棋情況 //---------------------------------------------------------- LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);//視窗訊息處理程式 void PaintBoard(HDC,RECT,POINT);//繪製棋盤的函式 void PaintChessman(HWND,RECT,playerchoice,int);//繪製棋子的函式 void ResetGame();//重新設定遊戲資訊 int WhoIsWinner(int,int,int); //判斷勝負 //void PCAI(int,int);//AI函數 //---------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nShowCmd) { static TCHAR AppName[]=TEXT("Gobang"); HWND hwnd; MSG msg; WNDCLASS wndclass={CS_SAVEBITS,WndProc,0,0,hInstance,//偷懶所以把視窗類別寫成這樣 LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON)),LoadCursor(NULL,IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH),AppName,AppName}; if(!RegisterClass(&wndclass)) { MessageBox(NULL,TEXT("註冊視窗失敗"),AppName,MB_ICONERROR); return 0; } hwnd=CreateWindowEx(WS_EX_TOPMOST,AppName,"對戰五子棋", WS_CAPTION|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX, 130,20,500,480, NULL,LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MENU)),hInstance,NULL); ShowWindow(hwnd,nShowCmd); UpdateWindow(hwnd); while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; HMENU hMenu; static RECT rt_board,//儲存棋盤大小的變數 rt_chessman;//儲存棋子大小的變數 static int cxClient,cyClient;//儲存顯示區域大小的變數 static POINT pt_board;//儲存棋盤格線初始座標的變數 //static SOCKET sock; //宣告socket playerchoice pchoice; int check_win,i,j; TCHAR text[20]; RECT rt_text; switch(msg) { case WM_CREATE: ResetGame(); return 0; case WM_SIZE: cxClient=LOWORD(lParam);//取得顯示區域大小 cyClient=HIWORD(lParam); SetRect(&rt_board,0,0,310,315);//設定棋盤大小 SetRect(&rt_chessman,7,7,24,24); pt_board.x=15;//設定第一調棋盤格線的起始座標位置 pt_board.y=15; return 0; case WM_PAINT: hdc=BeginPaint(hwnd,&ps); PaintBoard(hdc,rt_board,pt_board);//繪製棋盤 for(i=0;i<15;i++) { pchoice.x=i; for(j=0;j<15;j++) { pchoice.y=j; switch(chessman[i][j]) { case player1: PaintChessman(hwnd,rt_chessman,pchoice,player1); break; case player2: PaintChessman(hwnd,rt_chessman,pchoice,player2); break; } } } EndPaint(hwnd,&ps); return 0; case WM_LBUTTONDOWN: if(!play) { MessageBox(hwnd,TEXT("先選擇遊戲開始吧^^"),TEXT("歡迎光臨^0^"),MB_OK|MB_ICONINFORMATION); return 0; } pchoice.x=LOWORD(lParam)-pt_board.x; pchoice.y=HIWORD(lParam)-pt_board.y; pchoice.x=pchoice.x/board_width;//轉換為棋盤格交線位置 pchoice.y=pchoice.y/board_width; switch(play_mode) { case VS_COM: if(chessman[pchoice.y][pchoice.x]==0&&(pchoice.x>=0&&pchoice.x<=14)&&(pchoice.y>=0&&pchoice.y<=14)) { PaintChessman(hwnd,rt_chessman,pchoice,1);//畫棋子 chessman[pchoice.y][pchoice.x]=1; //PCAI(pchoice.y,pchoice.x);//AI } else { MessageBox(hwnd,TEXT("這邊不能下喔..^_^"),TEXT("眼睛脫窗ㄚ^^"),MB_ICONERROR|MB_OK); } break; case VS_PLAYER: if(chessman[pchoice.y][pchoice.x]==0&&(pchoice.x>=0&&pchoice.x<=14)&&(pchoice.y>=0&&pchoice.y<=14)) { PaintChessman(hwnd,rt_chessman,pchoice,who_play);//畫棋子 chessman[pchoice.y][pchoice.x]=who_play; check_win=WhoIsWinner(pchoice.y,pchoice.x,who_play); if(check_win==player1) { MessageBox(hwnd,TEXT("黑子勝利"),TEXT("勝利者"),MB_OK|MB_ICONINFORMATION); play=0; return 0; } if(check_win==player2) { MessageBox(hwnd,TEXT("白子勝利"),TEXT("勝利者"),MB_OK|MB_ICONINFORMATION); play=0; return 0; } if(who_play==player1) { who_play=player2; } else { who_play=player1; } } else { MessageBox(hwnd,TEXT("這邊不能下喔..^_^"),TEXT("眼睛脫窗ㄚ^^"),MB_ICONERROR|MB_OK); } break; case VS_CONNECT: break; } return 0; case WM_MOUSEMOVE: pchoice.x=LOWORD(lParam)-pt_board.x; pchoice.y=HIWORD(lParam)-pt_board.y; pchoice.x=pchoice.x/board_width;//轉換為棋盤格交線位置 pchoice.y=pchoice.y/board_width; if((pchoice.x<0||pchoice.x>14)||(pchoice.y<0||pchoice.y>14)) return 0; SetRect(&rt_text,340,140,450,180); hdc=GetDC(hwnd); SetBkColor(hdc,BkColor); wsprintf(text," ( %2d , %2d ) ",pchoice.x+1,pchoice.y+1); DrawText(hdc,text,-1,&rt_text,DT_CENTER); ReleaseDC(hwnd,hdc); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; case WM_COMMAND: hMenu=GetMenu(hwnd); switch(LOWORD(wParam)) { case IDC_SINGLE: play_mode=VS_COM; MessageBox(hwnd,TEXT("沒有AI啦,不會寫>_<"),TEXT("開發中"),MB_OK|MB_ICONINFORMATION); /*EnableMenuItem(hMenu,IDC_RESET,MF_ENABLED); EnableMenuItem(hMenu,IDC_MULTI,MF_GRAYED); EnableMenuItem(hMenu,IDC_DOUBLE,MF_GRAYED); play=TRUE;*/ return 0; case IDC_DOUBLE: play_mode=VS_PLAYER; EnableMenuItem(hMenu,IDC_RESET,MF_ENABLED); EnableMenuItem(hMenu,IDC_MULTI,MF_GRAYED); EnableMenuItem(hMenu,IDC_SINGLE,MF_GRAYED); play=TRUE; return 0; case IDC_RESET: EnableMenuItem(hMenu,IDC_RESET,MF_GRAYED); EnableMenuItem(hMenu,IDC_SINGLE,MF_ENABLED); EnableMenuItem(hMenu,IDC_DOUBLE,MF_ENABLED); EnableMenuItem(hMenu,IDC_MULTI,MF_ENABLED); InvalidateRect(hwnd,NULL,TRUE); ResetGame(); return 0; case IDC_MULTI: play_mode=VS_CONNECT; MessageBox(hwnd,TEXT("還不會寫連線>_<"),TEXT("開發中"),MB_OK|MB_ICONINFORMATION); return 0; case IDC_SERVER: return 0; case IDC_CONNECT: return 0; case IDC_EXIT: PostMessage(hwnd,WM_CLOSE,wParam,lParam); return 0; case IDC_ABORT: MessageBox(hwnd,TEXT("因為座標設計是採捨去方/n式,所以記得在你想下棋/n的位置的右下方點選喔^^"), TEXT("線上求助"),MB_OK|MB_ICONINFORMATION); return 0; case IDC_VISION: MessageBox(hwnd,TEXT("測試版:1.0"),TEXT("版本資訊"),MB_OK|MB_ICONINFORMATION); return 0; } return 0; } return DefWindowProc(hwnd,msg,wParam,lParam); } void PaintBoard(HDC hdc,RECT rt,POINT pt)//繪製棋盤 { HBRUSH hbr; RECT rt2; int i; TCHAR *szText[5]={"黑子先手","現在為","滑鼠位置", "勝利場數","本機IP"}; hbr=CreateSolidBrush(RGB(255,230,150));//定義棋盤使用畫刷顏色 FillRect(hdc,&rt,hbr);//繪製棋盤 DeleteObject(hbr); hbr=CreateSolidBrush(BkColor); SelectObject(hdc,hbr); SetBkColor(hdc,BkColor); SetTextColor(hdc,RGB(0,0,0)); SetRect(&rt2,350,10,440,30); RoundRect(hdc,rt2.left,rt2.top,rt2.right,rt2.bottom,30,30); //FillRect(hdc,&rt2,hbr); DrawText(hdc,szText[0],-1,&rt2,DT_CENTER); SetTextColor(hdc,RGB(255,255,255)); for(i=1;i<5;i++) { SetRect(&rt2,340,70*i-25,450,30+70*i); RoundRect(hdc,rt2.left,rt2.top,rt2.right,rt2.bottom,70,70); //FillRect(hdc,&rt2,hbr); SetRect(&rt2,340,70*i-30,450,40+70*i); DrawText(hdc,szText[i],-1,&rt2,DT_CENTER); } DeleteObject(hbr); hbr=CreateSolidBrush(RGB(0,0,0));//定義棋盤使用畫刷顏色 SelectObject(hdc,hbr); for(i=0;i<9;i++)//畫棋盤的九個點 { SetRect(&rt2,(72+board_width*(i%3))+60*(i%3),(72+board_width*(i/3))+60*(i/3),(72+board_width*(i%3))+7+60*(i%3),(72+board_width*(i/3))+7+60*(i/3)); Ellipse(hdc,rt2.left,rt2.top,rt2.right,rt2.bottom); } DeleteObject(hbr); for(i=0;i<15;i++)//畫橫線 { MoveToEx(hdc,pt.x,pt.y+board_width*i,NULL); LineTo(hdc,rt.right-14,pt.y+board_width*i); } for(i=0;i<15;i++)//畫縱線 { MoveToEx(hdc,pt.x+board_width*i,pt.y,NULL); LineTo(hdc,pt.x+board_width*i,rt.bottom-20); } } void PaintChessman(HWND hwnd,RECT rt,playerchoice pt,int who)//畫棋子 { HDC hdc; HBRUSH hbr; hdc=GetDC(hwnd); RECT rt_text; if(who==player1) { SetRect(&rt_text,340,70,450,110); SetTextColor(hdc,RGB(255,255,255)); SetBkColor(hdc,BkColor); DrawText(hdc,"白子",-1,&rt_text,DT_CENTER); hbr=CreateSolidBrush(RGB(0,0,0));//黑棋 SelectObject(hdc,hbr); } else { SetRect(&rt_text,340,70,450,110); SetTextColor(hdc,RGB(0,0,0)); SetBkColor(hdc,BkColor); DrawText(hdc,"黑子",-1,&rt_text,DT_CENTER); hbr=CreateSolidBrush(RGB(255,255,255));//白棋 SelectObject(hdc,hbr); } Ellipse(hdc,rt.left+board_width*pt.x,rt.top+board_width*pt.y, rt.right+board_width*pt.x,rt.bottom+board_width*pt.y); DeleteObject(hbr); ReleaseDC(hwnd,hdc); } void ResetGame() //初始化遊戲資料 { int i,j; play=FALSE; who_play=player1; for(i=0;i<15;i++) for(j=0;j<15;j++) chessman[i][j]=0;//陣列設為0,表示尚未放置棋子 chess_dir[0].x=1; chess_dir[0].y=0; chess_dir[1].x=1; chess_dir[1].y=1; chess_dir[2].x=0; chess_dir[2].y=1; chess_dir[3].x=-1; chess_dir[3].y=1; /*sc1.index=0; sc1.live_three=FALSE; sc1.dead_four=FALSE; sc2.index=0; sc2.live_three=FALSE; sc2.dead_four=FALSE;*/ } int WhoIsWinner(int i,int j,int who)//判斷勝負 { int x,LTable,RTable; playerchoice dir; for(x=0;x<4;x++) { LTable=0; RTable=0; dir.x=i; dir.y=j; while(chessman[i][j]==chessman[dir.x][dir.y]&&chessman[i][j]==who) { LTable++; dir.x=dir.x+chess_dir[x].x; dir.y=dir.y+chess_dir[x].y; if(dir.x<0||dir.y<0||dir.x>14||dir.y>14) break; } dir.x=i; dir.y=j; while(chessman[i][j]==chessman[dir.x][dir.y]&&chessman[i][j]==who) { RTable++; dir.x=dir.x-chess_dir[x].x; dir.y=dir.y-chess_dir[x].y; if(dir.x<0||dir.y<0||dir.x>14||dir.y>14) break; } if(LTable+RTable>5) { return who; } } return 0; } void PCAI(int pi,int pj)//電腦AI,傳入參數為玩家最後下的位置 { }

 

执行档及代码下载

你可能感兴趣的:([Win32] 五子棋双人版)