先看运行效果吧:
使用mingw编译,语言为C++,下面开始源代码,分为两个文件:
以下是header.h:
- /* LiZhuohua
- 2010/7/6 */
- #ifndef _SNAKE_HEADER_H_
- #define _SNAKE_HEADER_H_
- #define N 16
- struct SNAKE
- {
- int x[N];//横坐标
- int y[N];//纵坐标
- int direct;//方向:1、上 2、下 3、左 4、右
- int node;//节数
- int life;//生命
- } snake;
- struct FOOD
- {
- int x;
- int y;
- } food;
- void foodset(struct FOOD*,struct SNAKE*);
- #endif // _SNAKE_HEADER_H_
以下是main.cpp:
- /* LiZhuohua
- 2010/7/6 */
- #include <windows.h>
- #include <stdlib.h>
- #include <time.h>
- #include "header.h"
- /* Declare Windows procedure */
- LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
- /* Make the class name into a global variable */
- char szClassName[ ] = "LiZhuohuaWindowsApp";
- int WINAPI WinMain (HINSTANCE hThisInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpszArgument,
- int nCmdShow)
- {
- HWND hwnd; /* This is the handle for our window */
- MSG messages; /* Here messages to the application are saved */
- WNDCLASSEX wincl; /* Data structure for the windowclass */
- /* The Window structure */
- wincl.hInstance = hThisInstance;
- wincl.lpszClassName = szClassName;
- wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
- wincl.style = CS_DBLCLKS; /* Catch double-clicks */
- wincl.cbSize = sizeof (WNDCLASSEX);
- /* Use default icon and mouse-pointer */
- wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
- wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
- wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
- wincl.lpszMenuName = NULL; /* No menu */
- wincl.cbClsExtra = 0; /* No extra bytes after the window class */
- wincl.cbWndExtra = 0; /* structure or the window instance */
- /* Use Windows's default colour as the background of the window */
- wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
- /* Register the window class, and if it fails quit the program */
- if (!RegisterClassEx (&wincl))
- return 0;
- /* The class is registered, let's create the program*/
- hwnd = CreateWindowEx (
- 0, /* Extended possibilites for variation */
- szClassName, /* Classname */
- "贪吃蛇", /* Title Text */
- WS_DLGFRAME|WS_SYSMENU, /* default window */
- CW_USEDEFAULT, /* Windows decides the position */
- CW_USEDEFAULT, /* where the window ends up on the screen */
- 506, /* The programs width */
- 428, /* and height in pixels */
- HWND_DESKTOP, /* The window is a child-window to desktop */
- NULL, /* No menu */
- hThisInstance, /* Program Instance handler */
- NULL /* No Window Creation data */
- );
- /* Make the window visible on the screen */
- ShowWindow (hwnd, nCmdShow);
- /* Run the message loop. It will run until GetMessage() returns 0 */
- while (GetMessage (&messages, NULL, 0, 0))
- {
- /* Translate virtual-key messages into character messages */
- TranslateMessage(&messages);
- /* Send message to WindowProcedure */
- DispatchMessage(&messages);
- }
- /* The program return-value is 0 - The value that PostQuitMessage() gave */
- return messages.wParam;
- }
- /* This function is called by the Windows function DispatchMessage() */
- LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- switch (message) /* handle the messages */
- {
- case WM_CREATE: /*窗口创建时初始化snake结构,计时器和食物坐标*/
- {
- int i,j;
- snake.direct=4;
- snake.node=4;
- snake.life=1;
- for(i=0,j=200; i<snake.node; ++i,j-=25)
- {
- snake.x[i]=j;
- snake.y[i]=100;
- }
- SetTimer(hwnd,1,300,NULL); //计时器每300毫秒发出一次WM_TIMER消息,可以自己调
- foodset(&food,&snake);
- }
- break;
- case WM_PAINT:
- {
- int i;
- PAINTSTRUCT ps;
- HDC hdc;
- HPEN hpen;
- HBRUSH hbrush;
- hdc=BeginPaint(hwnd,&ps);
- hpen=CreatePen(PS_SOLID, 1, RGB (255, 0, 0)) ; //红色边框
- hbrush=CreateSolidBrush(RGB(255,0,0)); //红色填充
- SelectObject(hdc,hpen);
- SelectObject(hdc,hbrush);
- Rectangle(hdc,food.x,food.y,food.x+25,food.y+25); //绘制食物
- hbrush=CreateSolidBrush(RGB(0,0,255)); //蓝色填充
- SelectObject(hdc,hbrush);
- for(i=0; i<snake.node; ++i) /*绘制矩形作为蛇身*/
- Rectangle(hdc,snake.x[i],snake.y[i],snake.x[i]+25,snake.y[i]+25);
- EndPaint(hwnd,&ps);
- }
- break;
- case WM_KEYDOWN:
- {
- switch(wParam)
- {
- case VK_LEFT: /*不能反方向拐弯*/
- if(snake.direct!=4)
- snake.direct=3;
- break;
- case VK_RIGHT:
- if(snake.direct!=3)
- snake.direct=4;
- break;
- case VK_UP:
- if(snake.direct!=2)
- snake.direct=1;
- break;
- case VK_DOWN:
- if(snake.direct!=1)
- snake.direct=2;
- break;
- }
- }
- break;
- case WM_TIMER: //计时器到时的时候
- {
- int i;
- for(i=snake.node-1; i>0; i--) //关键代码,实现蛇身跟着蛇头走
- {
- snake.x[i]=snake.x[i-1];
- snake.y[i]=snake.y[i-1];
- }
- switch(snake.direct)
- {
- case 1:
- {
- snake.y[0]-=25;
- }
- break;
- case 2:
- {
- snake.y[0]+=25;
- }
- break;
- case 3:
- {
- snake.x[0]-=25;
- }
- break;
- case 4:
- {
- snake.x[0]+=25;
- }
- break;
- }
- if(snake.x[0]==food.x&&snake.y[0]==food.y) //判断是否吃到食物
- {
- snake.node++;
- snake.x[snake.node-1]=snake.x[snake.node-2];
- snake.y[snake.node-1]=snake.y[snake.node-2];
- foodset(&food,&snake);
- }
- if(snake.x[0]==500||snake.x[0]==-25||snake.y[0]==400||snake.y[0]==-25) //判断是否撞墙
- {
- snake.life=0; //蛇死了
- KillTimer(hwnd,1);
- MessageBox(hwnd,TEXT("撞墙了!"),TEXT("贪吃蛇"),MB_OK);
- }
- for(int i=3; i<snake.node; ++i) /*判断是否吃到自己,从第4节开始判断,因为第三节无论如何也转不过来*/
- {
- if(snake.x[0]==snake.x[i]&&snake.y[0]==snake.y[i])
- {
- snake.life=0; //蛇死了
- KillTimer(hwnd,1);
- MessageBox(hwnd,TEXT("巨能啊!自己吃自己?"),TEXT("贪吃蛇"),MB_OK);
- }
- }
- if(snake.life==1) //如果没死就重绘屏幕
- {
- InvalidateRect(hwnd,NULL,1);
- UpdateWindow(hwnd);
- }
- if(snake.node==16) //蛇长到16节就赢了,这个可以自己调
- {
- KillTimer(hwnd,1);
- MessageBox(hwnd,TEXT("你赢了!"),TEXT("贪吃蛇"),MB_OK);
- }
- }
- break;
- case WM_DESTROY:
- PostQuitMessage (0); /* send a WM_QUIT to the message queue */
- break;
- default: /* for messages that we don't deal with */
- return DefWindowProc (hwnd, message, wParam, lParam);
- }
- return 0;
- }
- void foodset(struct FOOD *a,struct SNAKE *b) //这是设置食物的函数
- {
- while(1)
- {
- int i,boolfood=1;
- srand((unsigned)time(NULL));
- a->x=rand()%451;
- a->y=rand()%351;
- while((a->x%25)!=0) //必须被25整除才可,否则蛇吃不到
- (a->x)++;
- while(a->y%25!=0)
- (a->y)++;
- for(i=0; i<b->node; ++i) //食物不能与蛇身重合
- if((b->x[i]==a->x)&&(b->y[i]==a->y))
- {
- boolfood=0;
- break;
- }
- if(boolfood)
- {
- break;
- }
- }
- }
自我感觉不足的地方就是筛选食物坐标的算法,很慢,在游戏的时候会有卡的感觉,请大家帮忙改一下!