贪吃蛇游戏win32 application实现

本文介绍了一个简单的贪吃蛇游戏的实现过程,包括蛇的移动、食物生成、碰撞检测等功能。游戏采用VC++ 6.0开发环境,利用定时器控制蛇的移动速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

贪吃蛇游戏简单实现

1.  实现的情况:

1)  蛇能够在游戏窗口区自由移动,吃到食物后,身体增长。

2)  窗口区,可随机出现一个食物。

3)  当蛇吃掉食物后,食物消失,随后窗口另外随机一个食物。

4)  上,下,左, 右,分别由键盘上的↑,↓,←,→键控制。

5)  食物随机出现,但不会出现在蛇的身体上,且食物出现在蛇可行的轨道上。

6)  加了两个字母键控制。‘s’键表示开始,‘x’键表示退出。

7)  两个定时器,分别是1,2, 当按下s键后,启动定时器1,然后由窗口函数处理WM_TIMER消息,游戏开始,并开启定时器2。

8)  开始游戏,初始化蛇头,并默认蛇头向下运动。关闭定时器1。

9)  由定时器2发出的WM_TIMER消息根据蛇的运行方向,处理相应的情况。

10)  处理完移动之后情况后,获得移动之前的坐标,并处理掉。

11)  改变蛇移动之后的坐标并保存,其后画出来。

12)  判断蛇是否撞到了窗口边界或者是自身,如果是,提示GAME OVER ,游戏结束。如果不是,判断蛇是否吃到了食物,如果吃到了,把吃到的食物清除,然后另外随机食物到游戏区里,并增长蛇的身体。

2.  没解决的问题:

1)  蛇移动后,会留下边框,当然窗口背景为黑色的除外(因为边框是黑色的).

2)  蛇的身体增长到一定程度时,蛇体颜色发生变化或者游戏死机。

3)  暂停键没有实现。

4)  墙没有实现,游戏区的边界是窗口的边界,当蛇撞到边界时,总是超出一部分。

5)  蛇身是由一个个小方块组成(比较丑)。

6)  键盘上只用了6(s, x,↑,↓,←,→)个键, 其它的都没有使用。

7)  缺少菜单栏,蛇缺少速度控制键。只有程序里设置的那个速度值,这个程序里是200ms移动一下。

8)  得分牌没有实现。

3.  程序文字流程图:

          游戏开始--à初始化蛇头和食物,并默认蛇头的运动方向为向下--à控制上,下,左,右键控制蛇的运动-à判断蛇是否撞到边界或者撞到自己--à①如果是,显示GAME OVER,并退出游戏。②如果不是,判断蛇是否吃到食物--à①如果是,去掉吃掉的食物,另外随机食物到游戏区,并且增加蛇的身体。②如果不是,继续控制蛇运动,向前几步一样,循环,直到游戏结束。

 

4.  代码实现:

本程序是基于VC++6.0实现的,工程是Win32 Application。

加源文件:Snake.cpp

 

 

 

 

 

 

 

程序:

/**************************************************************

//File Name : Snake.cpp

//Function  :

//Date      : 25, 12, 2011

//Version   : 0.1

//History   :

//      Version        Author         Memo

//          0.1           HZG           Programming start

***************************************************************/

#include <windows.h>

#include <time.h>

 

 

/**********************************************************/

//Function        : WinMain

 

//Parameter       :

//Returned Values : msg.wParam

//Memo            : main function

/***********************************************************/

// 程序主函数

int WINAPI WinMain(

  HINSTANCE hInstance,  // handle to current instance

  HINSTANCE hPrevInstance,  // handle to previous instance

  LPSTR lpCmdLine,      // pointer to command line

  int nCmdShow          // show state of window

)

{

         MSG msg;

         MyRegisterClass(hInstance);

         if (!Initialize(hInstance))

         {

                 return FALSE;

         }

 

         srand((unsigned)time(NULL));

         while (GetMessage(&msg, NULL, 0, 0))

         {

                 TranslateMessage(&msg);

                 DispatchMessage(&msg);

         }

         return msg.wParam;

}

 

//======================================================

// Function        : MyRegisterClass

//

// Parameter       : hInst -- windows instance

// Returned Values : RegisterClass(&wndcls)---ATOM style

// Memo            : register windows class

//======================================================

// 窗口类注册函数

ATOM MyRegisterClass(HINSTANCE hInst)

{

         WNDCLASS wndcls;

         wndcls.cbClsExtra = 0;

         wndcls.cbWndExtra = 0;

         wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

         wndcls.hCursor = LoadCursor(NULL, IDC_ARROW);

         wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION);

         wndcls.hInstance = hInst;

         wndcls.lpfnWndProc = Wnd_Snake_Proc;

         wndcls.lpszClassName = "Snake";

         wndcls.lpszMenuName = NULL;

         wndcls.style = CS_HREDRAW | CS_VREDRAW;

 

         return RegisterClass(&wndcls);

}

 

 

 

//======================================================

// Function        : Initialize

//

// Parameter       : hInst -- windows instance

// Returned Values : TURE---initialize success

// Memo            : Initialize

//======================================================

// 创建并初始化窗口

BOOL Initialize(HINSTANCE hInst)

{

         HWND hwnd;

 

         hwnd = CreateWindow("Snake", "Snake", WS_OVERLAPPEDWINDOW,

                 0, 0, 400, 500, NULL, NULL, hInst, NULL);

         ShowWindow(hwnd, SW_SHOWNORMAL);

         UpdateWindow(hwnd);

         return TRUE;

}

 

int key = 1;

POINT PreSnake[100];

POINT Snake[100];

int SnakeNum = 0;

POINT Food;

 

void StartGame(HWND hwnd);                  // 游戏开始,初始化蛇头并关闭定时器1

void DrawSnake(HWND hwnd, POINT Snake);      // 画蛇

void GetSnake(HWND hwnd, POINT PreSnake[]);   // 得到移动之前的蛇

void DrawPreSnake(HWND hwnd, POINT PreSnake); // 去掉移动之前的蛇

void ChangeSnake(HWND hwnd, POINT Snake[]);    // 画出移动之后的蛇

void DrawFood(HWND hwnd, POINT Snake[]);      // 游戏区随机出现食物

void AddBody(HWND hwnd, int Num);            // 吃到一个食物, 身体就增一节

BOOL JuageFood(HWND hwnd, POINT Snake[]);    // 判断蛇头是否与蛇身相撞或出游戏边界

void ClearFood(HWND hwnd, POINT Food);        // 食物吃了之后清理食物

 

//=============================================================================

// Function        : Wnd_Snake_Proc

//

// Parameter       :

// Returned Values : 0---return success

// Memo            : CallBack Function ---- process windows messages and come true some methods;

//=============================================================================

// 窗口函数

LRESULT CALLBACK Wnd_Snake_Proc(

                                                                           HWND hwnd,      // handle to window

                                                                           UINT uMsg,      // message identifier

                                                                           WPARAM wParam,  // first message parameter

                                                                           LPARAM lParam   // second message parameter

                                                                 )

{

         switch(uMsg)

         {

         case WM_CHAR:

                   switch(wParam)

                   {

                   case 's':

                            SetTimer(hwnd, 1, 200, NULL);

                            break;

                   case 't':

                            KillTimer(hwnd, 2);

                            break;

                   case 'x':

                            exit(0);

                            break;

                   }

                   break;

         case WM_KEYDOWN:

        switch(wParam)

        {

                   case VK_UP:       // 0为上, 1为下, 2为左, 3为右

                            if (key != 1)

                            {

                               key = 0;

                            }

                            break;

                   case VK_DOWN:

                            if (key != 0)

                            {

                                     key = 1;

                            }

                            break;

                   case VK_LEFT:

                            if (key != 3)

                            {

                                     key = 2;

                            }

                            break;

                   case VK_RIGHT:

                            if (key != 2)

                            {

                                     key = 3;

                            }

                            break;

        }

                   break;

         case WM_TIMER:

                   switch(wParam)

                   {

                   case 1:

                            StartGame(hwnd);

                            SetTimer(hwnd, 2, 200, NULL);

                            break;

                   case 2:

                            if (key == 0)

                            {

                                     Snake[0].y -= 20;

                            }

                            if (key == 1)

                            {

                                     Snake[0].y += 20;

                            }

                            if (key == 2)

                            {

                                     Snake[0].x -= 20;

                            }

                            if (key == 3)

                            {

                                     Snake[0].x += 20;

                            }

                            GetSnake(hwnd, &PreSnake[0]);     //得到蛇移动之前的坐标

                            ChangeSnake(hwnd, &Snake[0]);    //画出移动之后的蛇

 

 

                            if (JuageSnake (hwnd, &Snake[0]) == FALSE)//判断蛇是否撞到边界或者撞到自己

                            {

                                     KillTimer(hwnd, 2);

                                     if (IDYES == MessageBox(hwnd, "GAME OVER", "GAME OVER", MB_YESNO))

                                     {

                                               DestroyWindow(hwnd); 

                                     }

                            }

                            else

                            {

                                     if (Snake[0].x == Food.x && Snake[0].y == Food.y)//判断蛇是否吃到食物

                                     {

                                               ClearFood(hwnd, Food);      //清除吃到的食物

                                               DrawFood(hwnd, &Snake[0]); // 另个随机食物到游戏区内

                                               SnakeNum++;            //蛇的身体增加

                                               AddBody(hwnd, SnakeNum); //画出蛇增加的一部分

                                     }

                            }

                            break;

                   }

                   break;

         case WM_CLOSE:

                   if (IDYES == MessageBox(hwnd, "是否真的结束游戏?", "close", MB_YESNO))

                   {

                            DestroyWindow(hwnd);

                   }

                   break;

         case WM_DESTROY:

                   PostQuitMessage(0);

                   break;

         default:

                   return DefWindowProc(hwnd, uMsg, wParam, lParam);

         }

         return 0;

}

 

//=========================================================

// Function        : StartGame

//

// Parameter       :

// Returned Values : none

// Memo            : start game

//=========================================================

// 游戏开始,并初始蛇头和食物         

void StartGame(HWND hwnd)

{

         PreSnake[0].x = 0;

         PreSnake[0].y = 0;

         Snake[0].x = 0;

         Snake[0].y = 0;

   

         DrawSnake(hwnd, Snake[0]);

         DrawFood(hwnd, &Snake[0]);

         KillTimer(hwnd, 1);

}

//=================================================

// Function        : DrawSnake()

//

// Parameter       :

// Returned Values : none

// Memo            : draw a snake in the client area

//==================================================

//得到蛇节点(蛇是由一节节构成的,这里是蛇的最小单位)

void DrawSnake(HWND hwnd, POINT Snake)

{

         HDC hdc;

         HBRUSH hbrush;

 

         hdc = GetDC(hwnd);

         hbrush = CreateSolidBrush(RGB(255, 0, 0));

         SelectObject(hdc, hbrush);

 

         Rectangle(hdc, Snake.x, Snake.y, Snake.x + 20, Snake.y + 20);

         ReleaseDC(hwnd, hdc);

}

//========================================================

// Function        : DrawFood()

//

// Parameter       :

// Returned Values : none

// Memo            : draw food in the client area

//========================================================

// 随机食物到游戏区

void DrawFood(HWND hwnd, POINT Snake[])

{

         RECT rt;

         HDC hdc;

    HBRUSH hbrush;

         BOOL fit = TRUE;

 

         GetClientRect(hwnd, &rt);

         hdc = GetDC(hwnd);

         hbrush = CreateSolidBrush(RGB(0, 255, 0));

         SelectObject(hdc, hbrush);

 

 

 

         while (fit)

         {

                   Food.x = rand() % (rt.right - rt.left);

             Food.y = rand() % (rt.bottom - rt.top);

 

                   if ((Food.x >= rt.left) && ((Food.y + 20) <= rt.bottom) && ((Food.x + 20) <= rt.right) && (Food.y >= rt.top))

                   {

                            if ((Food.x % 20 == 0) && (Food.y % 20 == 0))

                            {

                                     fit = 0;

                            }// 使食物随机在蛇运动的轨道上

 

                            for (int i = 0; i <= SnakeNum; i++)

                            {

                                     if (Food.x == Snake[i].x && Food.y == Snake[i].y)

                                     {

                                               fit = 1;

                                     }

                            }// 防止出现食物再现在蛇身上

                   }

         }

 

         Rectangle(hdc, Food.x, Food.y, Food.x + 20, Food.y + 20);

         ReleaseDC(hwnd, hdc);

 

}

 

//=================================================

// Function        : GetSnake()

//

// Parameter       :

// Returned Values : none

// Memo            : get all of the snake's coordinate after snake motion

//==================================================

//得到蛇运动之前的身体,并除去(实际是把之前的蛇节点都用和背景一样的颜色填充)

void GetSnake(HWND hwnd, POINT PreSnake[])

{

         for (int i = 0; i <= SnakeNum; i++)

         {

                   DrawPreSnake(hwnd, PreSnake[i]);

         }

}

//=================================================

// Function        : GetSnake()

//

// Parameter       :

// Returned Values : none

// Memo            : draw snake node

//==================================================

// 把蛇移动之前的蛇节点画出来

void DrawPreSnake(HWND hwnd, POINT PreSnake)

{

         HDC hdc;

         HBRUSH hbrush;

 

         hdc = GetDC(hwnd);

         hbrush = (HBRUSH)GetStockObject(BLACK_BRUSH);

//      hbrush = CreateSolidBrush(RGB(0, 0, 0));

         SelectObject(hdc, hbrush);

 

         Rectangle(hdc, PreSnake.x, PreSnake.y, PreSnake.x + 20, PreSnake.y + 20);

         ReleaseDC(hwnd, hdc);

}

 

//============================================================

// Function        : ChangeSnake(HWND hwnd, POINT Snake[])

//

// Parameter       :

// Returned Values : none

// Memo            : come true the snake's move, save and draw

//=============================================================

// 得到蛇动之后的坐标,并保存各画出蛇移动之后的身体

void ChangeSnake(HWND hwnd, POINT Snake[])

{

         // move

         for (int i = SnakeNum; i > 0; i--)

         {

                   Snake[i].x = PreSnake[i-1].x;

                   Snake[i].y = PreSnake[i-1].y;

         }

         // save

         for (i = 0; i <= SnakeNum; i++)

         {

                   PreSnake[i].x = Snake[i].x;

                   PreSnake[i].y = Snake[i].y;

         }

 

         // draw

         for (i = 0; i <= SnakeNum; i++)

         {

                   DrawSnake(hwnd, Snake[i]);

         }

}

//========================================================

// Function        : AddBody

//

// Parameter       :

// Returned Values : none

// Memo            : eat a food ----add a node body

//========================================================

// 蛇吃了食物之后,蛇身增长的实现

void AddBody(HWND hwnd, int Num)

{

         if (key == 0)

         {

                   Snake[Num].x = Snake[Num-1].x;

                   Snake[Num].y = Snake[Num-1].y + 20;

         }

 

         if (key == 1)

         {

                   Snake[Num].x = Snake[Num-1].x;

        Snake[Num].y = Snake[Num-1].y - 20;

         }

 

         if (key == 2)

         {

                   Snake[Num].x = Snake[Num-1].x + 20;

        Snake[Num].y = Snake[Num-1].y;

         }

 

         if (key == 3)

         {

                   Snake[Num].x = Snake[Num-1].x - 20;

        Snake[Num].y = Snake[Num-1].y;

         }

}

 

//========================================================

// Function        : JuageSnake

//

// Parameter       :

// Returned Values : none

// Memo            : juage snake whether hit itself or window border

//========================================================

//判断蛇是不是撞到自己或者是窗口边界

BOOL JuageSnake(HWND hwnd, POINT Snake[])

{

         RECT rt;

         GetClientRect(hwnd, &rt);

 

         if (Snake[0].x < rt.left || Snake[0].y < rt.top || Snake[0].x > rt.right || Snake[0].y >rt.bottom)

         {

                   KillTimer(hwnd, 2);

                   return FALSE;

         }

         else

         {

                   for (int i = 1; i <= SnakeNum; i++)

                   {

                            if (Snake[0].x == Snake[i].x && Snake[0].y == Snake[i].y)

                            {

                                     return FALSE;

                            }

                   }

         }

         return TRUE;

}

 

//========================================================

// Function        : ClearFood

//

// Parameter       :

// Returned Values : none

// Memo            : clear food while the snake eat a food

//========================================================

void ClearFood(HWND hwnd, POINT Food)

{

         HDC hdc;

         HBRUSH hbrush;

 

         hdc = GetDC(hwnd);

         hbrush = (HBRUSH)GetStockObject(BLACK_BRUSH);

         SelectObject(hdc, hbrush);

 

         Rectangle(hdc, Food.x, Food.y, Food.x + 20, Food.y + 20);

         ReleaseDC(hwnd, hdc);

}

 

//  难点1:蛇怎么移动 -----------------------------------------OK             

//  难点2:如何把食物放在蛇移动的轨道上------------------------OK

//  难点3:如何防止食物随机出现在蛇身上------------------------OK

//  难点4:吃到了食物之后,怎么身体变长------------------------OK

//  难点5:随着蛇变长之后, 蛇身上的颜色变白(正常为红色), 然后程序不动(程序死//机了)-----未解决

//  难点6:暂停的实现----没有实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄阿刚仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值