WinAPI双人贪吃蛇
生活随笔
收集整理的這篇文章主要介紹了
WinAPI双人贪吃蛇
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
(上學期寫的,確實很冗余的代碼,菜鳥一枚還請大家包涵)
2個文件:snakeList.h和snake.cpp
首先是第一個:
#include <windows.h> #pragma oncetypedef struct tagNODE {POINT apt[4];struct tagNODE * previous, *next; }NODE;typedef struct tagSNAKE {int length;NODE *head, *tail; }SNAKE; 其次: /*********************************************************Wy 05/21/2013 **********************************************************/#include <windows.h> #include <cstdlib> #include <ctime> #include "snakeList.h"#define UNIT 30 #define ID_TIMER_SPEED 1 #define ID_TIMER_TIME 3 enum direction {//記錄蛇移動的方向UP, DOWN, RIGHT, LEFT }dire1,dire2;//判斷是否吃到食物,作為全局變量,是因為如果寫過程函數中,則后面的函數中 //要用到eat,則需要給許多函數傳入eat這個參數,太麻煩,所以設為全局變量。 bool eat1 = false; //定義一個全局變量,當蛇遇到墻壁或者自身時,將其設置為true bool game_over = false;void square (HDC, POINT[]); void border (HDC); void drawSnake (HDC, SNAKE*); bool isBorder (POINT[]); bool isFood (POINT[], POINT[]); bool isSelf (SNAKE*, SNAKE*, POINT[]); void drawUp (SNAKE*, SNAKE*, POINT[]); void drawDown (SNAKE*, SNAKE*, POINT[]); void drawRight (SNAKE*, SNAKE*, POINT[]); void drawLeft (SNAKE*, SNAKE*, POINT[]); void runDef (SNAKE*, SNAKE*, direction*, POINT[]); void creatFood (SNAKE*, SNAKE*, POINT[]); void initializeSnake1(SNAKE*); void initializeSnake2(SNAKE*); void drawFood (HDC,POINT[]); void clearSnake(SNAKE*); void initializeGame (SNAKE*, SNAKE*);LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { //注冊窗口類 static TCHAR szAppName[] = TEXT ("snake");HWND hwnd;MSG msg;WNDCLASS wcls;wcls.cbClsExtra = 0;wcls.cbWndExtra = 0;wcls.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);wcls.hCursor = LoadCursor (NULL, IDC_ARROW);wcls.hIcon = LoadIcon (NULL, IDI_APPLICATION);wcls.hInstance = hInstance;wcls.lpfnWndProc = WndProc;wcls.lpszClassName = szAppName;wcls.lpszMenuName = NULL;wcls.style = CS_HREDRAW | CS_VREDRAW;if (!RegisterClass (&wcls)){MessageBox (NULL, TEXT ("Program requires WinNT!"), szAppName, MB_ICONERROR);} //創建窗口 hwnd = CreateWindow (szAppName, TEXT("snake"),WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX,CW_USEDEFAULT, CW_USEDEFAULT,23*UNIT-13, 15*UNIT,NULL, NULL, hInstance, NULL); //顯示和更新窗口ShowWindow (hwnd, iCmdShow);UpdateWindow (hwnd); //消息循環while (GetMessage (&msg, NULL, 0, 0)){TranslateMessage (&msg);DispatchMessage (&msg);}return msg.wParam; }//過程函數 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static int cxClient, cyClient;HDC hdc;PAINTSTRUCT ps;static SNAKE snake1,snake2;//定義蛇結構體static POINT food[4];//食物static bool isKeyDown = false;//是否有方向鍵按下static int time;TCHAR szBuffer[1000];switch (message){case WM_SIZE:cxClient = LOWORD (lParam);cyClient = HIWORD (lParam);return 0;case WM_CREATE:SetTimer (hwnd, ID_TIMER_SPEED, 200, NULL);//設定游戲速度定時器SetTimer (hwnd, ID_TIMER_TIME, 1000, NULL);//設定游戲時間定時器initializeSnake1(&snake1);//初始化蛇1initializeSnake2(&snake2);//初始化蛇2dire2 = RIGHT;//初始化為向右移動dire1 = RIGHT;//初始化為向右移動creatFood(&snake1,&snake2,food);//創建食物return 0;case WM_TIMER:switch (wParam){case ID_TIMER_SPEED:InvalidateRect (hwnd, NULL, TRUE);//如果設為FALSE,則蛇移動后會留下痕跡return 0;case ID_TIMER_TIME:++time;return 0;default:return 0;}case WM_CHAR:{switch (wParam){case 'w':if (dire2 != DOWN)//防止反向移動,以下類似{isKeyDown = true;dire2 = UP; //將方向更新drawUp(&snake2, &snake1, food);//更行蛇的結點坐標}return 0;case 's':if (dire2 != UP){isKeyDown = true;dire2 = DOWN; drawDown(&snake2, &snake1, food);}return 0;case 'd':if (dire2 != LEFT){isKeyDown = true;dire2 = RIGHT; drawRight(&snake2, &snake1, food);}return 0;case 'a':if (dire2 != RIGHT){isKeyDown = true;dire2 = LEFT; drawLeft(&snake2, &snake1, food);}return 0;}return 0;}case WM_KEYDOWN://按鍵控制{switch (wParam){case VK_UP:if (dire1 != DOWN)//防止反向移動,以下類似{isKeyDown = true;dire1 = UP; //將方向更新drawUp(&snake1, &snake2, food);//更行蛇的結點坐標}return 0;case VK_DOWN:if (dire1 != UP){isKeyDown = true;dire1 = DOWN; drawDown(&snake1, &snake2, food);}return 0;case VK_RIGHT:if (dire1 != LEFT){isKeyDown = true;dire1 = RIGHT; drawRight(&snake1, &snake2, food);}return 0;case VK_LEFT:if (dire1 != RIGHT){isKeyDown = true;dire1 = LEFT; drawLeft(&snake1, &snake2, food);}return 0;case VK_SPACE:KillTimer(hwnd,1);if (IDNO == MessageBox(hwnd,TEXT("回到游戲?"),TEXT("暫停游戲"),MB_YESNO)){PostQuitMessage(0); }else{SetTimer (hwnd, ID_TIMER_SPEED, 200, NULL);//恢復定時器 }return 0; case VK_ESCAPE:KillTimer(hwnd,1);if (IDYES == MessageBox(hwnd,TEXT("退出游戲?"),TEXT("退出游戲"),MB_YESNO)){PostQuitMessage(0); }else{SetTimer (hwnd, ID_TIMER_SPEED, 200, NULL);//恢復定時器 }return 0; default:return 0;}InvalidateRect (hwnd, NULL, TRUE);//使客戶區無效return 0;}case WM_PAINT:hdc = BeginPaint (hwnd, &ps);border(hdc);//畫邊框if (!isKeyDown)//判斷是否有鍵按下{runDef(&snake1,&snake2,&dire1,food);//如果沒有,則按默認方式,即原方向移動runDef(&snake2,&snake2,&dire2,food);//如果沒有,則按默認方式,即原方向移動}if (game_over){KillTimer(hwnd,1);//暫停定時器if (IDNO == MessageBox(hwnd,TEXT("Game Over! Try Again?"),TEXT("Snake!"),MB_YESNO)){PostQuitMessage(0);}else{initializeGame(&snake1,&snake2);time = 0;SetTimer (hwnd, ID_TIMER_SPEED, 200, NULL);//恢復定時器}}drawSnake (hdc, &snake1);//畫蛇1drawSnake (hdc, &snake2);//畫蛇2drawFood(hdc,food);//畫食物TextOut(hdc,10,12*UNIT+3,TEXT("玩家1控制:上W,下S,左A,右D 玩家2控制:上↑,下↓,左←,右→"),50);TextOut(hdc,10,12*UNIT+25,TEXT("空格鍵:暫停游戲"),8);TextOut(hdc,150,12*UNIT+25,TEXT("Esc鍵:退出游戲"),9);TextOut(hdc,300,12*UNIT+25,szBuffer,wsprintf(szBuffer,TEXT("Player1 Score: %d"),snake1.length));TextOut(hdc,450,12*UNIT+25,szBuffer,wsprintf(szBuffer,TEXT("Player2 Score: %d"),snake2.length));TextOut(hdc,600,12*UNIT+25,szBuffer,wsprintf(szBuffer,TEXT("time: %d"),time));EndPaint (hwnd, &ps);isKeyDown = false;//將其恢復為falsereturn 0;case WM_DESTROY:KillTimer (hwnd, ID_TIMER_SPEED);PostQuitMessage (0);return 0;}return DefWindowProc (hwnd, message, wParam, lParam); }void square (HDC hdc, POINT apt[4]) {//paint a square based on 4 pointsMoveToEx (hdc, apt[0].x, apt[0].y, NULL);LineTo (hdc, apt[1].x, apt[1].y);MoveToEx (hdc, apt[1].x, apt[1].y, NULL);LineTo (hdc, apt[2].x, apt[2].y);MoveToEx (hdc, apt[2].x, apt[2].y, NULL);LineTo (hdc, apt[3].x, apt[3].y);MoveToEx (hdc, apt[3].x, apt[3].y, NULL);LineTo (hdc, apt[0].x, apt[0].y);return; }void border (HDC hdc) {//畫出邊框 POINT border[22][4];for (int i=0; i!=22; ++i){//初始化上邊框的每個方格的四個點坐標border[i][0].x = i*UNIT;border[i][0].y = 0;border[i][1].x = (i+1)*UNIT;border[i][1].y = 0;border[i][2].x = (i+1)*UNIT;border[i][2].y = UNIT;border[i][3].x = i*UNIT;border[i][3].y = UNIT;}for (int i=0; i!=22; ++i){//畫出上邊框square (hdc, border[i]);}for (int i=0; i!=22; ++i){//初始化下邊框每個方格的四個點坐標border[i][0].x = i*UNIT;border[i][0].y = 11*UNIT;border[i][1].x = (i+1)*UNIT;border[i][1].y = 11*UNIT;border[i][2].x = (i+1)*UNIT;border[i][2].y = 12*UNIT;border[i][3].x = i*UNIT;border[i][3].y = 12*UNIT;}for (int i=0; i!=22; ++i){//畫出下邊框square (hdc, border[i]);}for (int i=0; i!=10; ++i){//初始化左邊框每個方格的四個點坐標border[i][0].x = 0;border[i][0].y = (i+1)*UNIT;border[i][1].x = UNIT;border[i][1].y = (i+1)*UNIT;border[i][2].x = UNIT;border[i][2].y = (i+2)*UNIT;border[i][3].x = 0;border[i][3].y = (i+2)*UNIT;}for (int i=0; i!=22; ++i){//畫出左邊框square (hdc, border[i]);}for (int i=0; i!=10; ++i){//初始化右邊框每個方格的四個點坐標border[i][0].x = 21*UNIT;border[i][0].y = (i+1)*UNIT;border[i][1].x = 22*UNIT;border[i][1].y = (i+1)*UNIT;border[i][2].x = 22*UNIT;border[i][2].y = (i+2)*UNIT;border[i][3].x = 21*UNIT;border[i][3].y = (i+2)*UNIT;}for (int i=0; i!=22; ++i){//畫出右邊框square (hdc, border[i]);}return; }void drawSnake (HDC hdc, SNAKE* s) {NODE* iter = s->head;for (int i=0; i!=s->length; ++i){square (hdc, iter->apt);iter = iter->next;}iter = NULL;free (iter);return; }bool isBorder (POINT apt[4]) {if (apt[0].x==0 || apt[0].x==21*UNIT || apt[0].y==0 || apt[0].y==11*UNIT)return true;elsereturn false; }bool isFood (POINT food[4], POINT apt[4]) {if (apt[0].x == food[0].x && apt[0].y == food[0].y)return true;elsereturn false; }bool isSelf (SNAKE* s1, SNAKE* s2, POINT apt[4]) {NODE* current = s1->head;for (int i=0; i!=s1->length; ++i){if (current->apt[0].x==apt[0].x && current->apt[0].y==apt[0].y)return true;current = current->next;}current = s2->head;for (int i=0; i!=s2->length; ++i){if (current->apt[0].x==apt[0].x && current->apt[0].y==apt[0].y)return true;current = current->next;}return false; }void drawUp (SNAKE* s1, SNAKE* s2, POINT food[4]) {POINT temp[4];//蛇頭上方的方格temp[0].x = s1->head->apt[0].x;temp[0].y = s1->head->apt[0].y - UNIT;temp[1].x = s1->head->apt[1].x; temp[1].y = s1->head->apt[1].y - UNIT;temp[2] = s1->head->apt[1];temp[3] = s1->head->apt[0];if (isBorder(temp) || isSelf(s1, s2, temp)){//判斷是否為墻或者自身game_over = true;}else if (isFood(food, temp)){//如果是食物,則只添加頭結點NODE* new_head = (NODE*)malloc(sizeof(NODE));//在函數結束時,能否添加進去?new_head->apt[0] = temp[0];new_head->apt[1] = temp[1];new_head->apt[2] = temp[2];new_head->apt[3] = temp[3];new_head->next = s1->head;s1->head->previous = new_head;s1->head = new_head;eat1 = true;s1->length++;if (eat1)creatFood(s1,s2,food);eat1 = false;}else{//為空。則添加頭結點,刪除尾結點NODE* new_head = (NODE*)malloc(sizeof(NODE));//在函數結束時,能否添加進去?new_head->apt[0] = temp[0];new_head->apt[1] = temp[1];new_head->apt[2] = temp[2];new_head->apt[3] = temp[3];new_head->next = s1->head;s1->head->previous = new_head;s1->head = new_head;NODE* temp_tail;temp_tail = s1->tail;s1->tail = s1->tail->previous;s1->tail->next = NULL;free (temp_tail);} }void drawDown (SNAKE* s1, SNAKE* s2, POINT food[4]) {POINT temp[4];//蛇頭下方的方格temp[3].x = s1->head->apt[3].x;temp[3].y = s1->head->apt[3].y + UNIT;temp[2].x = s1->head->apt[2].x; temp[2].y = s1->head->apt[2].y + UNIT;temp[0] = s1->head->apt[3];temp[1] = s1->head->apt[2];if (isBorder(temp) || isSelf(s1,s2,temp)){//判斷是否為墻或者自身game_over = true;}else if (isFood(food, temp)){//如果是食物,則只添加頭結點NODE* new_head = (NODE*)malloc(sizeof(NODE));//在函數結束時,能否添加進去?new_head->apt[0] = temp[0];new_head->apt[1] = temp[1];new_head->apt[2] = temp[2];new_head->apt[3] = temp[3];new_head->next = s1->head;s1->head->previous = new_head;s1->head = new_head;eat1 = true;s1->length++;if (eat1)creatFood(s1,s2,food);eat1 = false;}else{//為空。則添加頭結點,刪除尾結點NODE* new_head = (NODE*)malloc(sizeof(NODE));//在函數結束時,能否添加進去?new_head->apt[0] = temp[0];new_head->apt[1] = temp[1];new_head->apt[2] = temp[2];new_head->apt[3] = temp[3];new_head->next = s1->head;s1->head->previous = new_head;s1->head = new_head;NODE* temp_tail;temp_tail = s1->tail;s1->tail = s1->tail->previous;s1->tail->next = NULL;free (temp_tail);} }void drawRight (SNAKE* s1, SNAKE* s2, POINT food[4]) {POINT temp[4];//蛇頭右方的方格temp[1].x = s1->head->apt[1].x + UNIT;temp[1].y = s1->head->apt[1].y;temp[2].x = s1->head->apt[2].x + UNIT; temp[2].y = s1->head->apt[2].y;temp[0] = s1->head->apt[1];temp[3] = s1->head->apt[2];if (isBorder(temp) || isSelf(s1, s2, temp)){//判斷是否為墻或者自身game_over = true;}else if (isFood(food, temp)){//如果是食物,則只添加頭結點NODE* new_head = (NODE*)malloc(sizeof(NODE));//在函數結束時,能否添加進去?new_head->apt[0] = temp[0];new_head->apt[1] = temp[1];new_head->apt[2] = temp[2];new_head->apt[3] = temp[3];new_head->next = s1->head;s1->head->previous = new_head;s1->head = new_head;eat1 = true;s1->length++;if (eat1)creatFood(s1,s2,food);eat1 = false;}else{//為空。則添加頭結點,刪除尾結點NODE* new_head = (NODE*)malloc(sizeof(NODE));//在函數結束時,能否添加進去?new_head->apt[0] = temp[0];new_head->apt[1] = temp[1];new_head->apt[2] = temp[2];new_head->apt[3] = temp[3];new_head->next = s1->head;s1->head->previous = new_head;s1->head = new_head;NODE* temp_tail;temp_tail = s1->tail;s1->tail = s1->tail->previous;s1->tail->next = NULL;free (temp_tail);} }void drawLeft (SNAKE* s1, SNAKE* s2, POINT food[4]) {POINT temp[4];//蛇頭上方的方格temp[0].x = s1->head->apt[0].x - UNIT;temp[0].y = s1->head->apt[0].y;temp[3].x = s1->head->apt[3].x - UNIT; temp[3].y = s1->head->apt[3].y;temp[2] = s1->head->apt[3];temp[1] = s1->head->apt[0];if (isBorder(temp) || isSelf(s1, s2, temp)){//判斷是否為墻或者自身game_over = true;}else if (isFood(food, temp)){//如果是食物,則只添加頭結點NODE* new_head = (NODE*)malloc(sizeof(NODE));//在函數結束時,能否添加進去?new_head->apt[0] = temp[0];new_head->apt[1] = temp[1];new_head->apt[2] = temp[2];new_head->apt[3] = temp[3];new_head->next = s1->head;s1->head->previous = new_head;s1->head = new_head;eat1 = true;s1->length++;if (eat1)creatFood(s1, s2, food);eat1 = false;}else{//為空。則添加頭結點,刪除尾結點NODE *new_head = (NODE*)malloc(sizeof(NODE));//在函數結束時,能否添加進去?new_head->apt[0] = temp[0];new_head->apt[1] = temp[1];new_head->apt[2] = temp[2];new_head->apt[3] = temp[3];new_head->next = s1->head;s1->head->previous = new_head;s1->head = new_head;NODE* temp_tail;temp_tail = s1->tail;s1->tail = s1->tail->previous;s1->tail->next = NULL;free (temp_tail);} }void runDef (SNAKE* s1, SNAKE* s2, direction* d, POINT food[4]) {//默認移動方式,即按原方向移動switch (*d){case UP:drawUp(s1,s2,food);break;case DOWN:drawDown(s1,s2,food);break;case RIGHT:drawRight(s1,s2,food);break;case LEFT:drawLeft(s1,s2,food);break;default:break;} }void creatFood (SNAKE* snake1, SNAKE* snake2, POINT food[4]) {do{//防止食物出現在蛇身srand((unsigned)time(NULL));//初始化時間種子int seedx = rand()%20 + 1;//設置食物隨即出現的x坐標int seedy = rand()%10 + 1;//設置食物隨即出現的y坐標food[0].x = seedx*UNIT;food[0].y = seedy*UNIT;food[1].x = (seedx + 1)*UNIT;food[1].y = seedy*UNIT;food[2].x = (seedx + 1)*UNIT;food[2].y = (seedy + 1)*UNIT;food[3].x = seedx*UNIT;food[3].y = (seedy + 1)*UNIT;} while (isSelf(snake1,snake2,food)); }void drawFood (HDC hdc,POINT food[4]) {square(hdc,food); }void initializeSnake1(SNAKE* snake1) {NODE* one = (NODE*)malloc(sizeof(NODE));NODE* two = (NODE*)malloc(sizeof(NODE));NODE* three = (NODE*)malloc(sizeof(NODE));//初始化蛇的三個節點鏈接one->next = two;two->next = three;three->next = NULL;three->previous = two;two->previous = one;one->previous = NULL; //初始化蛇的三個節點坐標one->apt[0].x = 6*UNIT;one->apt[0].y = 3*UNIT;one->apt[1].x = 7*UNIT;one->apt[1].y = 3*UNIT;one->apt[2].x = 7*UNIT;one->apt[2].y = 4*UNIT;one->apt[3].x = 6*UNIT;one->apt[3].y = 4*UNIT;two->apt[0].x = 5*UNIT;two->apt[0].y = 3*UNIT;two->apt[1].x = 6*UNIT;two->apt[1].y = 3*UNIT;two->apt[2].x = 6*UNIT;two->apt[2].y = 4*UNIT;two->apt[3].x = 5*UNIT;two->apt[3].y = 4*UNIT;three->apt[0].x = 4*UNIT;three->apt[0].y = 3*UNIT;three->apt[1].x = 5*UNIT;three->apt[1].y = 3*UNIT;three->apt[2].x = 5*UNIT;three->apt[2].y = 4*UNIT;three->apt[3].x = 4*UNIT;three->apt[3].y = 4*UNIT;//初始化蛇snake1->length = 3;snake1->head = one;snake1->tail = three;}void initializeSnake2(SNAKE* snake2) {NODE* one = (NODE*)malloc(sizeof(NODE));NODE* two = (NODE*)malloc(sizeof(NODE));NODE* three = (NODE*)malloc(sizeof(NODE));//初始化蛇的三個節點鏈接one->next = two;two->next = three;three->next = NULL;three->previous = two;two->previous = one;one->previous = NULL; //初始化蛇的三個節點坐標one->apt[0].x = 6*UNIT;one->apt[0].y = 6*UNIT;one->apt[1].x = 7*UNIT;one->apt[1].y = 6*UNIT;one->apt[2].x = 7*UNIT;one->apt[2].y = 7*UNIT;one->apt[3].x = 6*UNIT;one->apt[3].y = 7*UNIT;two->apt[0].x = 5*UNIT;two->apt[0].y = 6*UNIT;two->apt[1].x = 6*UNIT;two->apt[1].y = 6*UNIT;two->apt[2].x = 6*UNIT;two->apt[2].y = 7*UNIT;two->apt[3].x = 5*UNIT;two->apt[3].y = 7*UNIT;three->apt[0].x = 4*UNIT;three->apt[0].y = 6*UNIT;three->apt[1].x = 5*UNIT;three->apt[1].y = 6*UNIT;three->apt[2].x = 5*UNIT;three->apt[2].y = 7*UNIT;three->apt[3].x = 4*UNIT;three->apt[3].y = 7*UNIT;//初始化蛇snake2->length = 3;snake2->head = one;snake2->tail = three; }void clearSnake(SNAKE* snake) {//刪除蛇所有結點NODE* current = snake->head;while (current){NODE* temp = current;current = current->next;delete temp;temp = NULL;} }void initializeGame (SNAKE* snake1, SNAKE* snake2) {//初始化游戲clearSnake(snake1);//刪除原來蛇1所有結點clearSnake(snake2);//刪除原來蛇2所有結點initializeSnake1(snake1);//初始化蛇1initializeSnake2(snake2);//初始化蛇2game_over = false;//恢復游戲dire1 = RIGHT;//初始化方向dire2 = RIGHT;//初始化方向 }總結
以上是生活随笔為你收集整理的WinAPI双人贪吃蛇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【GPGPU编程模型与架构原理】第一章
- 下一篇: 服务器 最新 配置,常见的服务器配置参数