main.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
/*WinAPI版本的貪食蛇 : 版本:v1.4 遊戲流程 : 按方向鍵開始遊戲,按滑鼠左鍵可以暫停遊戲 碰到邊界或撞到尾巴都會導致遊戲結束,結束時顯示分數 並可選擇是否結束遊戲 如果未讀取到B1.bmp,則以灰色畫面進入遊戲 實作日期 : 2007.3.18 */ #include "Snake_Function.cpp" //程式進入點 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG Msg; char pic[10]; //SetBkMode(hMyDC, ); int wnd_W; int wnd_H; wnd_W=403; wnd_H=300; //亂入結束 wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance ; //wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hIcon = (HICON)LoadImage(NULL,"7.ico", IMAGE_ICON,32,32,LR_LOADFROMFILE); wc.hCursor = LoadCursor(NULL, IDC_ARROW); //以下建立背景圖片 LOGBRUSH background; background.lbStyle = BS_PATTERN; background.lbHatch = (long) LoadImage(hInstance,//實體代碼 BACKGROUND_PIC,//圖像名稱 IMAGE_BITMAP,//圖像種類 0, //期望的寬度 0,//期望的高度 LR_LOADFROMFILE);//讀取選項); //建立結束 if (background.lbHatch != 0) wc.hbrBackground = CreateBrushIndirect(&background); else //如果同資料夾中沒有名為B1.bmp的背景圖,則以白色背景取代 wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); //如果改成NULL_BRUSH,背景就會變透明 wc.lpszMenuName = NULL; wc.lpszClassName = szAppName; wc.hIconSm = (HICON)LoadImage(NULL, "7.ico", IMAGE_ICON, 16, 16,LR_LOADFROMFILE); if (!RegisterClassEx(&wc)) { MessageBox(NULL, "視窗類別登記失敗!", "發生錯誤!", MB_ICONEXCLAMATION | MB_OK); return 0; } hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, szAppName, "歡 迎 來 到 貪 食 蛇 世 界 ! !", WS_OVERLAPPEDWINDOW, nTopXY(wnd_W, GetSystemMetrics(SM_CXSCREEN)), nTopXY(wnd_H, GetSystemMetrics(SM_CYSCREEN)), wnd_W,wnd_H, NULL, NULL, hInstance, NULL); if (hwnd == NULL) { MessageBox(NULL, "視窗建立失敗!", "發生錯誤!", MB_ICONEXCLAMATION | MB_OK); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while (GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hMyDC; PAINTSTRUCT ps; WNDCLASSEX wc; char Text[] = "文字顯示測試!!"; int nLen = sizeof(szText)-1; int i,x,y; int SnakeHand = 5*nTick; //蛇頭移動的設定變數 char gameOverStr[100]; //遊戲結束的文字敘述 HBRUSH hBrush; //變換方格顏色用 nTickX = nTick; switch (msg) { case WM_CREATE: SetTimer(hwnd,1,cpuTime,NULL); break; case WM_TIMER: if (bFlag == 0 ){ nTick ++; if (point == 0) nTick = 0; wsprintf(szTick,"時間:%d",nTick); InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); } break; case WM_KEYDOWN: //keydown可以讀取到字鍵和系統鍵 wsprintf(szTextKey,"按鍵:%s",TEXT("按")); wsprintf(szCharKey,"字鍵為:%s",&wParam); nowKeyNumber = wParam ; //把捕捉到的值記錄起來 InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); break; case WM_KEYUP: wsprintf(szTextKey,"按鍵:%s",TEXT("開")); InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); break; //end case WM_LBUTTONDOWN: if (bFlag == 0){ bFlag = 1; wsprintf(szText,"%s",TEXT("按滑鼠左鍵繼續")); InvalidateRect(hwnd, NULL, TRUE); } else { bFlag = 0; wsprintf(szText,"%s",TEXT("按滑鼠左鍵暫停")); InvalidateRect(hwnd, NULL, TRUE); } break; case WM_PAINT: wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); //撥放音樂....還未學會 //PlaySound("1.wav",NULL,SND_FILENAME | SND_ASYNC); hMyDC=BeginPaint(hwnd, &ps); SetBkMode(hMyDC, TRANSPARENT); //設定為背景通透 //畫出邊界 MoveToEx(hMyDC,10,10,NULL); LineTo(hMyDC,380,10); MoveToEx(hMyDC,380,10,NULL); LineTo(hMyDC,380,220); MoveToEx(hMyDC,380,220,NULL); LineTo(hMyDC,10,220); MoveToEx(hMyDC,10,220,NULL); LineTo(hMyDC,10,10); speed(hwnd); //控制速度 randStar(); //看看有沒有碰到星星 starAndSnakeHand(hwnd,hMyDC,hBrush); //畫出星星和蛇頭 walked(); //計算走幾步,過去走過的路 hBrush = CreateSolidBrush(RGB(132,255,77)); SelectObject(hMyDC,hBrush); wsprintf(gameOverStr," 頭尾相撞 !! \n\n 總分:%d \n\n 繼續遊戲 ? ",point); PrintTail(hwnd,hMyDC,gameOverStr, msg, wParam, lParam); //畫出尾巴 並判斷有沒有頭尾相撞 keyClicked(); //上下左右移動 wsprintf(gameOverStr," 出界 !! \n\n 總分:%d \n\n 繼續遊戲 ? ",point); outLine(hwnd,hMyDC,gameOverStr, msg, wParam, lParam); //檢查是否出界 如果出界就結束 printOther(hwnd,hMyDC); //畫出其他有的沒的資料 SetTextColor(hMyDC,RGB(255,111,33)); TextOut(hMyDC,140,100,szText,lstrlen(szText));//顯示暫停與否(按滑鼠左鍵) strcpy(szText,""); //這樣才不會殘留在畫面上 DeleteObject(hBrush); EndPaint(hwnd, &ps); break; case WM_CLOSE: KillTimer(hwnd,1); DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } int nTopXY(UINT wnd_XY, UINT wnd_Dim) { int resl; resl=((wnd_Dim/2)-(wnd_XY/2)); return resl; } //-----------------end---------------------
Function.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
#include <windows.h> #include <Winuser.h> //GDI相關的函式與資料結構宣告於Winuser.h #include <stdlib.h> #include <time.h> // NEW #define RADIUS 7 //蛇頭和星星的碰撞容許距離 #define MOVE_DISTANCE 6 //一次移動的距離 #define SNAKE_SIZE 15//蛇的大小 #define STAR_SIZE 15 //星星大小 #define BACKGROUND_PIC "B1.bmp" //背景圖片 #define SNAKE_DISTANCE 10 //蛇身每一段相隔的距離 // OLD #define EQU == #define RIGHT 365 #define LEFT 10 #define UP 10 #define DOWN 205 #define WALKED 15000 //走超過15000格就會重頭放入array #define TAIL_NUM 50 //尾巴超過50個就會當掉 //從主程式搬過來的 const char* szAppName = "MyWndClass"; int nTick = 0; int nTickX = 1; int nTickY = 1; BOOL bFlag =0; char szText[5] = ""; char szTextKey[10] =""; //用來顯示狀態的字元陣列 char szTick[100] ; //顯示時間 char szCharKey[10]; //用來顯示按鍵的字元 char szOut[10] = "出界!!"; char szPoint[100]; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int nTopXY(UINT, UINT); // NEW int cpuTime = 60; //控制蛇的速度 //目前的(X,Y)位置 int nowX = 160; int nowY = 100; char nowXYStr[20]; //上次移動的位移 int moveX = 0; int moveY = 0; //星星的位置 int starX = 0; int starY = 0; int nowKeyNumber = 0; //目前按下的鍵盤對應數值 int beforeKeyNumber = 0; //前一個方向 int nowXYPlace = 0; //目前位置 int tailNumber = 0; //尾巴數目 int walkedNumber = 0; //總共走了多少步 // 上 下 左 右 int aspectX[4] = { 0 ,0 ,SNAKE_DISTANCE,-SNAKE_DISTANCE }; int aspectY[4] = { SNAKE_DISTANCE,-SNAKE_DISTANCE,0 ,0 }; // OLD int point = 0; //得分 int currentAspect = 0; //目前方向 int walkX[WALKED] = {0}; //走過的 int walkY[WALKED] = {0}; //WinAPI貪食蛇版本加入的 void randStar(); //讓星星被撞到後隨機跑 void keyClicked(); //上下左右移動 void walked(); //走過的路 void outLine(HWND ,HDC ,char ); //檢查是否出界 如果出界就結束 void PrintTail(HWND ,HDC ,char); //畫出蛇的尾巴 void starAndSnakeHand(HWND ,HDC ,HBRUSH); //畫出星星和蛇頭 void speed(); //隨分數調整速度 void reStart(); //重新開始的歸零動作 //DOS貪食蛇版本有的 int Move(int,int,int); //移動位置 void Star(int*,int*,int,int,int*); //畫出星星並讓其軌跡隨機 void PrintBorder(int ); //畫出外框 void Play(); //遊戲主要套件 void PrintSnake(); //畫出蛇的軌跡 void Start(); //開始處理 int End(); //結束處理 void PrintTail(); //畫出蛇的尾巴 void PrintAspect(); //標出目前的方向 void Restart(); //重新玩的歸零動作 int IsAgain(); //是否重新玩 int Walked(); //走過的路 int IsBumpTail(); //頭撞到尾巴 void Speed(); //依分數調節速度 void EndView(); //最後的等待畫面 // 以下為WinAPI貪食蛇版本加入的 void randStar() //讓星星被撞到後隨機移動 { if (starX == 0 && starY == 0 ){//第一次 srand(time(NULL)); starX = rand()%330 + 20; starY = rand()%180 + 20; } else if ( ((nowX-starX) <= RADIUS && (nowX-starX) >= -RADIUS) && ((nowY-starY) <= RADIUS && (nowY-starY) >= -RADIUS) ){ //蛇碰到星星 srand(time(NULL)); starX = rand()%200+rand()%160 + 15 ; starY = rand()%100+rand()%55 + 20; point += 10; //碰到星星所以加分 } } void starAndSnakeHand(HWND hwnd,HDC hMyDC,HBRUSH hBrush) //畫出星星和蛇頭 { hBrush = CreateSolidBrush(RGB(255,255,48)); SelectObject(hMyDC,hBrush); Ellipse(hMyDC,starX,starY,starX+STAR_SIZE,starY+STAR_SIZE); //星星 DeleteObject(hBrush); hBrush = CreateSolidBrush(RGB(0,255,0)); SelectObject(hMyDC,hBrush); Ellipse(hMyDC,nowX,nowY,nowX+SNAKE_SIZE+3,nowY+SNAKE_SIZE+3); //蛇頭 DeleteObject(hBrush); } void keyClicked() //上下左右移動 並紀錄方向 { if (nowKeyNumber == 38 ){ //上 nowY = nowY - MOVE_DISTANCE ; moveX = 0; moveY = -MOVE_DISTANCE; currentAspect = 0; } else if (nowKeyNumber == 40){ //下 nowY = nowY + MOVE_DISTANCE ; moveX = 0; moveY = MOVE_DISTANCE; currentAspect = 1; } else if (nowKeyNumber == 37){ //左 nowX = nowX - MOVE_DISTANCE ; moveX = -MOVE_DISTANCE; moveY = 0; currentAspect = 2; } else if (nowKeyNumber == 39){ //右 nowX = nowX + MOVE_DISTANCE ; moveX = MOVE_DISTANCE; moveY = 0; currentAspect = 3; } else{ nowX = nowX + moveX; nowY = nowY + moveY; } } void walked() //紀錄走過的路 { nowXYPlace = (walkedNumber+WALKED-1) % WALKED; //紀錄走過的路 (0-49一循環) tailNumber = point / 10 ; //計算目前蛇的尾巴有多長 walkedNumber ++; int i = nowXYPlace; walkX[i] = nowX; walkY[i] = nowY; } void PrintTail(HWND hwnd,HDC hMyDC,char gameOverStr[10],UINT msg, WPARAM wParam, LPARAM lParam) //畫出蛇的尾巴 { int distance = 1; //蛇身每一段的相隔距離 int handDistance = 3; int first = 0; //解決頭和第一個身體靠太近的問題 int id = 0; //判斷是與否 while ( tailNumber > 0){ if (nowXYPlace > 10 ){ //走十步以上才開始計算 if (distance == 1) first = -2; else first = 0; Ellipse(hMyDC, walkX[nowXYPlace-2*distance+first], walkY[nowXYPlace-2*distance+first], walkX[nowXYPlace-2*distance+first]+SNAKE_SIZE, walkY[nowXYPlace-2*distance+first]+SNAKE_SIZE ); //蛇尾 //檢查是否撞到尾巴 if (nowX == walkX[nowXYPlace-2*distance+first] && nowY == walkY[nowXYPlace-2*distance+first] || nowX == walkX[nowXYPlace-2*distance-1] && nowY == walkY[nowXYPlace-2*distance-1] ){ KillTimer(hwnd,1); //讓時間計算停止 id = MessageBox(hwnd,gameOverStr,"遊戲結束", MB_YESNO | MB_ICONINFORMATION); if (id == IDNO) PostQuitMessage(0); //關閉程式 else{ reStart(); //把全域變數歸零 DefWindowProc(hwnd, msg, wParam, lParam); //重新開始 } } tailNumber--; nowXYPlace--; distance++; //增加這個是為了把每一節之間的距離拉長 } } } void reStart() //歸零動作 { nTick = 0; nTickX = 1; nTickY = 1; bFlag =0; strcpy(szText,""); strcpy(szTextKey,""); strcpy(szTick,""); strcpy(szCharKey,""); strcpy(szOut,""); strcpy(szPoint,""); // NEW cpuTime = 60; //控制蛇的速度 //目前的(X,Y)位置 nowX = 160; nowY = 100; strcpy(nowXYStr,""); //上次移動的位移 moveX = 0; moveY = 0; //星星的位置 starX = 0; starY = 0; nowKeyNumber = 0; //目前按下的鍵盤對應數值 beforeKeyNumber = 0; //前一個方向 nowXYPlace = 0; //目前位置 tailNumber = 0; //尾巴數目 walkedNumber = 0; //總共走了多少步 // OLD point = 0; //得分 currentAspect = 0; //目前方向 for (int i = 0 ; i < WALKED ; i++){ walkX[i] = 0; //走過的 walkY[i] = 0; } } void outLine(HWND hwnd,HDC hMyDC,char gameOverStr[10],UINT msg, WPARAM wParam, LPARAM lParam) //檢查是否出界 如果出界就結束 { LPOPENFILENAME lpofn ; int id = 0; //判斷按下是還是否 HBRUSH hBrush; //變換方格顏色用 hBrush = CreateSolidBrush(RGB(132,255,77)); SelectObject(hMyDC,hBrush); if ( nowX > RIGHT || nowX < LEFT || nowY > DOWN || nowY < UP){ KillTimer(hwnd,1); //讓時間計算停止 id = MessageBox(hwnd,gameOverStr,"遊戲結束", MB_YESNO | MB_ICONINFORMATION); if (id == IDNO) PostQuitMessage(0); //關閉程式 else{ GetOpenFileName(lpofn); DeleteObject(hBrush); reStart(); //把全域變數歸零 DefWindowProc(hwnd, msg, wParam, lParam); //重新開始 } } } void printOther(HWND hwnd,HDC hMyDC) { int nLen = sizeof(szText)-1; SetTextColor(hMyDC,RGB(230,95,230)); TextOut(hMyDC,10,245,szTick,lstrlen(szTick)); //顯示目前秒數 SetTextColor(hMyDC,RGB(110,95,230)); wsprintf(szPoint,"分數 : %d",point); //目前分數 TextOut(hMyDC,170,245,szPoint,strlen(szPoint));//顯示目前分數 SetTextColor(hMyDC,RGB(0,0,0)); wsprintf(nowXYStr," ( %d , %d )",nowX,nowY); TextOut(hMyDC,80,245,nowXYStr,lstrlen(nowXYStr)); //顯示目前位置 SetTextColor(hMyDC,RGB(45,95,115)); TextOut(hMyDC,320,245,szCharKey,lstrlen(szCharKey));//顯示按下的字元 SetTextColor(hMyDC,RGB(111,0,115)); TextOut(hMyDC,260,245,szTextKey,lstrlen(szTextKey));//顯示有沒有按下 } void speed(HWND hwnd) //隨分數調整速度 { if (point > 300) cpuTime = 20; else if (point > 200) cpuTime = 25 ; else if (point > 140) cpuTime = 30 ; else if (point > 90) cpuTime = 40; else if (point > 40) cpuTime = 50; SetTimer(hwnd,1,cpuTime,NULL); //重新設制速度 }
No response to “WinAPI版本的貪食蛇” ;
張貼留言