【源码】用Win32 SDK写的贪吃蛇,欢迎交流

先看运行效果吧:


使用mingw编译,语言为C++,下面开始源代码,分为两个文件:

以下是header.h:

Code:
  1. /* LiZhuohua 
  2.    2010/7/6  */  
  3. #ifndef _SNAKE_HEADER_H_  
  4. #define _SNAKE_HEADER_H_  
  5. #define N 16  
  6. struct SNAKE  
  7. {  
  8.     int x[N];//横坐标  
  9.     int y[N];//纵坐标  
  10.     int direct;//方向:1、上 2、下 3、左 4、右  
  11.     int node;//节数  
  12.     int life;//生命  
  13. } snake;  
  14.   
  15. struct FOOD  
  16. {  
  17.     int x;  
  18.     int y;  
  19.   
  20. } food;  
  21.   
  22. void foodset(struct FOOD*,struct SNAKE*);  
  23. #endif // _SNAKE_HEADER_H_  

以下是main.cpp:

Code:
  1. /* LiZhuohua 
  2.    2010/7/6  */  
  3. #include <windows.h>  
  4. #include <stdlib.h>  
  5. #include <time.h>  
  6. #include "header.h"  
  7. /*  Declare Windows procedure  */  
  8. LRESULT CALLBACK WindowProcedure (HWNDUINTWPARAMLPARAM);  
  9.   
  10. /*  Make the class name into a global variable  */  
  11. char szClassName[ ] = "LiZhuohuaWindowsApp";  
  12.   
  13. int WINAPI WinMain (HINSTANCE hThisInstance,  
  14.                     HINSTANCE hPrevInstance,  
  15.                     LPSTR lpszArgument,  
  16.                     int nCmdShow)  
  17. {  
  18.     HWND hwnd;               /* This is the handle for our window */  
  19.     MSG messages;            /* Here messages to the application are saved */  
  20.     WNDCLASSEX wincl;        /* Data structure for the windowclass */  
  21.   
  22.     /* The Window structure */  
  23.     wincl.hInstance = hThisInstance;  
  24.     wincl.lpszClassName = szClassName;  
  25.     wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */  
  26.     wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */  
  27.     wincl.cbSize = sizeof (WNDCLASSEX);  
  28.   
  29.     /* Use default icon and mouse-pointer */  
  30.     wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);  
  31.     wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);  
  32.     wincl.hCursor = LoadCursor (NULL, IDC_ARROW);  
  33.     wincl.lpszMenuName = NULL;                 /* No menu */  
  34.     wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */  
  35.     wincl.cbWndExtra = 0;                      /* structure or the window instance */  
  36.     /* Use Windows's default colour as the background of the window */  
  37.     wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;  
  38.   
  39.     /* Register the window class, and if it fails quit the program */  
  40.     if (!RegisterClassEx (&wincl))  
  41.         return 0;  
  42.   
  43.     /* The class is registered, let's create the program*/  
  44.     hwnd = CreateWindowEx (  
  45.                0,                   /* Extended possibilites for variation */  
  46.                szClassName,         /* Classname */  
  47.                "贪吃蛇",       /* Title Text */  
  48.                WS_DLGFRAME|WS_SYSMENU, /* default window */  
  49.                CW_USEDEFAULT,       /* Windows decides the position */  
  50.                CW_USEDEFAULT,       /* where the window ends up on the screen */  
  51.                506,                 /* The programs width */  
  52.                428,                 /* and height in pixels */  
  53.                HWND_DESKTOP,        /* The window is a child-window to desktop */  
  54.                NULL,                /* No menu */  
  55.                hThisInstance,       /* Program Instance handler */  
  56.                NULL                 /* No Window Creation data */  
  57.            );  
  58.   
  59.     /* Make the window visible on the screen */  
  60.     ShowWindow (hwnd, nCmdShow);  
  61.   
  62.     /* Run the message loop. It will run until GetMessage() returns 0 */  
  63.     while (GetMessage (&messages, NULL, 0, 0))  
  64.     {  
  65.         /* Translate virtual-key messages into character messages */  
  66.         TranslateMessage(&messages);  
  67.         /* Send message to WindowProcedure */  
  68.         DispatchMessage(&messages);  
  69.     }  
  70.   
  71.     /* The program return-value is 0 - The value that PostQuitMessage() gave */  
  72.     return messages.wParam;  
  73. }  
  74.   
  75.   
  76. /*  This function is called by the Windows function DispatchMessage()  */  
  77.   
  78. LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
  79. {  
  80.     switch (message)                  /* handle the messages */  
  81.     {  
  82.     case WM_CREATE:                   /*窗口创建时初始化snake结构,计时器和食物坐标*/  
  83.     {  
  84.         int i,j;  
  85.         snake.direct=4;  
  86.         snake.node=4;  
  87.         snake.life=1;  
  88.         for(i=0,j=200; i<snake.node; ++i,j-=25)  
  89.         {  
  90.             snake.x[i]=j;  
  91.             snake.y[i]=100;  
  92.         }  
  93.         SetTimer(hwnd,1,300,NULL); //计时器每300毫秒发出一次WM_TIMER消息,可以自己调  
  94.   
  95.         foodset(&food,&snake);  
  96.     }  
  97.     break;  
  98.     case WM_PAINT:  
  99.     {  
  100.         int i;  
  101.         PAINTSTRUCT ps;  
  102.         HDC hdc;  
  103.         HPEN hpen;  
  104.         HBRUSH hbrush;  
  105.         hdc=BeginPaint(hwnd,&ps);  
  106.         hpen=CreatePen(PS_SOLID, 1, RGB (255, 0, 0)) ; //红色边框  
  107.         hbrush=CreateSolidBrush(RGB(255,0,0));  //红色填充  
  108.         SelectObject(hdc,hpen);  
  109.         SelectObject(hdc,hbrush);  
  110.         Rectangle(hdc,food.x,food.y,food.x+25,food.y+25); //绘制食物  
  111.         hbrush=CreateSolidBrush(RGB(0,0,255));  //蓝色填充  
  112.         SelectObject(hdc,hbrush);  
  113.         for(i=0; i<snake.node; ++i) /*绘制矩形作为蛇身*/  
  114.             Rectangle(hdc,snake.x[i],snake.y[i],snake.x[i]+25,snake.y[i]+25);  
  115.         EndPaint(hwnd,&ps);  
  116.     }  
  117.     break;  
  118.     case WM_KEYDOWN:  
  119.     {  
  120.         switch(wParam)  
  121.         {  
  122.         case VK_LEFT:             /*不能反方向拐弯*/  
  123.             if(snake.direct!=4)  
  124.                 snake.direct=3;  
  125.             break;  
  126.         case VK_RIGHT:  
  127.             if(snake.direct!=3)  
  128.                 snake.direct=4;  
  129.             break;  
  130.         case VK_UP:  
  131.             if(snake.direct!=2)  
  132.                 snake.direct=1;  
  133.             break;  
  134.         case VK_DOWN:  
  135.             if(snake.direct!=1)  
  136.                 snake.direct=2;  
  137.             break;  
  138.         }  
  139.     }  
  140.     break;  
  141.     case WM_TIMER:  //计时器到时的时候  
  142.     {  
  143.         int i;  
  144.         for(i=snake.node-1; i>0; i--)  //关键代码,实现蛇身跟着蛇头走  
  145.         {  
  146.             snake.x[i]=snake.x[i-1];  
  147.             snake.y[i]=snake.y[i-1];  
  148.         }  
  149.         switch(snake.direct)  
  150.         {  
  151.         case 1:  
  152.         {  
  153.             snake.y[0]-=25;  
  154.         }  
  155.         break;  
  156.         case 2:  
  157.         {  
  158.             snake.y[0]+=25;  
  159.         }  
  160.         break;  
  161.         case 3:  
  162.         {  
  163.             snake.x[0]-=25;  
  164.         }  
  165.         break;  
  166.         case 4:  
  167.         {  
  168.             snake.x[0]+=25;  
  169.         }  
  170.         break;  
  171.         }  
  172.   
  173.         if(snake.x[0]==food.x&&snake.y[0]==food.y)   //判断是否吃到食物  
  174.         {  
  175.             snake.node++;  
  176.             snake.x[snake.node-1]=snake.x[snake.node-2];  
  177.             snake.y[snake.node-1]=snake.y[snake.node-2];  
  178.             foodset(&food,&snake);  
  179.         }  
  180.         if(snake.x[0]==500||snake.x[0]==-25||snake.y[0]==400||snake.y[0]==-25)  //判断是否撞墙  
  181.         {  
  182.             snake.life=0; //蛇死了  
  183.             KillTimer(hwnd,1);  
  184.             MessageBox(hwnd,TEXT("撞墙了!"),TEXT("贪吃蛇"),MB_OK);  
  185.         }  
  186.         for(int i=3; i<snake.node; ++i)   /*判断是否吃到自己,从第4节开始判断,因为第三节无论如何也转不过来*/  
  187.         {  
  188.             if(snake.x[0]==snake.x[i]&&snake.y[0]==snake.y[i])  
  189.             {  
  190.                 snake.life=0;  //蛇死了  
  191.                 KillTimer(hwnd,1);  
  192.                 MessageBox(hwnd,TEXT("巨能啊!自己吃自己?"),TEXT("贪吃蛇"),MB_OK);  
  193.             }  
  194.         }  
  195.         if(snake.life==1) //如果没死就重绘屏幕  
  196.         {  
  197.             InvalidateRect(hwnd,NULL,1);  
  198.             UpdateWindow(hwnd);  
  199.         }  
  200.         if(snake.node==16)  //蛇长到16节就赢了,这个可以自己调  
  201.         {  
  202.             KillTimer(hwnd,1);  
  203.             MessageBox(hwnd,TEXT("你赢了!"),TEXT("贪吃蛇"),MB_OK);  
  204.         }  
  205.     }  
  206.     break;  
  207.     case WM_DESTROY:  
  208.         PostQuitMessage (0);       /* send a WM_QUIT to the message queue */  
  209.         break;  
  210.     default:                      /* for messages that we don't deal with */  
  211.         return DefWindowProc (hwnd, message, wParam, lParam);  
  212.     }  
  213.   
  214.     return 0;  
  215. }  
  216.   
  217. void foodset(struct FOOD *a,struct SNAKE *b)  //这是设置食物的函数  
  218. {  
  219.     while(1)  
  220.     {  
  221.         int i,boolfood=1;  
  222.         srand((unsigned)time(NULL));  
  223.         a->x=rand()%451;  
  224.         a->y=rand()%351;  
  225.         while((a->x%25)!=0)  //必须被25整除才可,否则蛇吃不到  
  226.             (a->x)++;  
  227.         while(a->y%25!=0)  
  228.             (a->y)++;  
  229.         for(i=0; i<b->node; ++i)  //食物不能与蛇身重合  
  230.             if((b->x[i]==a->x)&&(b->y[i]==a->y))  
  231.             {  
  232.                 boolfood=0;  
  233.                 break;  
  234.             }  
  235.         if(boolfood)  
  236.         {  
  237.             break;  
  238.         }  
  239.   
  240.     }  
  241. }  

自我感觉不足的地方就是筛选食物坐标的算法,很慢,在游戏的时候会有卡的感觉,请大家帮忙改一下!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值