贪吃蛇

在C++吧发现2个贪吃蛇源码:

#include<iostream>
#include<windows.h>
#include<conio.h>
#include<time.h>
#include<stdlib.h>
using namespace std;
int GameOver=0;

struct Body//蛇身(链表结构)
{
    int x,y;//蛇身结点坐标
    Body *next;//下一个结点
};

void SetPos(int i,int j)//设定光标位置
{
    COORD pos={i-1,j-1};//坐标变量
    HANDLE Out=GetStdHandle(STD_OUTPUT_HANDLE);//获取输出句柄
    SetConsoleCursorPosition(Out,pos);//设定光标位置
}

class Sneak//贪吃蛇类
{
    private:
        Body *head;//蛇头指针
        int Direction;//移动方向。1,2,3,4对应上左下右
        int Count;//蛇长
        int Speed;//速度(等级)
        int FoodExist;//食物存在标记
        int Food_x;//食物X坐标
        int Food_y;//食物Y坐标
    public:
        Sneak(int a=3,int b=4,int c=1,int d=0)//构造函数
        { 
              FoodExist=d;//起始不存在食物
              Body *temp1,*temp2;
              head=new(Body);//申请起始蛇身3节
              head->x=4;
              head->y=2;
              
              temp1=new(Body);
              temp1->x=3;
              temp1->y=2;
              
              temp2=new(Body);
              temp2->x=2;
              temp2->y=2;

              head->next=temp1;
              temp1->next=temp2;
              temp2->next=NULL;

              Direction=b;//方向为右
              Count=a;//长为3
              Speed=c;//等级1
        }
        void Map();//画界面函数
        void Paint();//画蛇身函数
        void Food();//生成食物
        int Over();//判断游戏是否结束
        void Gaming();//游戏进程函数
        void Move();//移动
};

void Sneak::Map()//使用
{
    int i;
    for(i=1;i<=50;i++)
    {
        SetPos(i,1);
        cout<<"-";
    }
    for(i=2;i<=25;i++)
    {
        SetPos(1,i);
        cout<<"|";
        SetPos(50,i);
        cout<<"|";
    }
    for(i=1;i<=50;i++)
    {
        SetPos(i,25);
        cout<<"-";
    }
    SetPos(54,3);
    cout<<"贪吃蛇";
    SetPos(54,5);
    cout<<"长度:"<<Count;
    SetPos(54,7);
    cout<<"LEVEL:"<<Speed;
}

void Sneak::Food()
{
    Body *p;
    int InBody=0;    //判断食物是否产生在蛇体内
    srand((int)time(0));//用系统时间来做随机数种子
    while(1)
    {
        Food_x=rand()%48+2;//随机出食物的坐标
        Food_y=rand()%23+2;
        p=head;
        while(p!=NULL)//判断食物是否产生在蛇体内
        {
            if(p->x==Food_x&&p->y==Food_y)
            {
                InBody=1;
                break;
            }
            p=p->next;
        }
        if(InBody==0)//食物不在蛇身。生成成功
            break;
        InBody=0;
    }
}

int Sneak::Over()
{
    Body *p;
    p=head;
    if((head->x)>=50||(head->x)<=1||(head->y)<=1||(head->y)>=25)//是否撞到边缘
        return 1;
    p=head->next;
    while(p!=NULL)//是否撞到蛇身
    {
        if((head->x==p->x)&&(head->y==p->y))
            return 1;
        p=p->next;
    }
    return 0;
}

void Sneak::Paint()
{
    Body *p;
    p=head;
    while(p!=NULL)
    {
        SetPos(p->x,p->y);
        cout<<"*";
        p=p->next;
    }
    SetPos(Food_x,Food_y);
    cout<<"*";
}

void Sneak::Move()
{
    Body *New;
    New=new(Body);//新的蛇身结点
    if(Direction==1)//确定新蛇头的坐标    
    {
         New->x=head->x;
         New->y=head->y-1;
         New->next=head;
         head=New;
    }
    if(Direction==2)
    {
         New->x=head->x-1;
         New->y=head->y;
         New->next=head;
         head=New;
    }
    if(Direction==3)
    {
         New->x=head->x;
         New->y=head->y+1;
         New->next=head;
         head=New;
    }
    if(Direction==4)
    {
         New->x=head->x+1;
         New->y=head->y;
         New->next=head;
         head=New;
    }
}

void Sneak::Gaming()
{
    system("cls");//刷新屏幕
    char x;
    Body *p;
    Map();//画界面的先
    Paint();//再画蛇身
    while(1)
    {
        if(_kbhit())//_kbhit()判断是否有键盘操作
        {
            x=_getch();//重缓冲区读出一个字符赋给x
            if((x=='W'||x=='w')&&Direction!=3)//改变蛇的方向(不可以是反方向)
                Direction=1;
            if((x=='S'||x=='s')&&Direction!=1)
                Direction=3;
            if((x=='A'||x=='a')&&Direction!=4)
                Direction=2;
            if((x=='D'||x=='d')&&Direction!=2)
                Direction=4;
            while(_kbhit())//读掉这之后所有的键盘输入
                _getch();
        }
        if(FoodExist==0)//如果食物被吃了或刚开始游戏,要生成新的食物
        {
             Food();
             FoodExist=1;
        }
        Move();//移动蛇
        if(head->x==Food_x&&head->y==Food_y)//如果蛇吃到了食物
        {
           FoodExist=0;
           Count++;//蛇身+1
           SetPos(54,5);
           cout<<"长度:"<<Count;//改变界面信息
           if(Count%10==0)//每十个蛇身升一级
           {
              Speed++;
              SetPos(54,7);
              cout<<"LEVEL:"<<Speed;
           }
           if(Speed==10)//最高等级达成。退出游戏
               break;
        }
        Paint();//画新的蛇身
        if(FoodExist==1)//如果没有吃到食物,需要删除蛇尾。
        {
            p=head;
            while((p->next)->next!=NULL)
               p=p->next;
            SetPos(p->next->x,p->next->y);
            cout<<" ";
            delete(p->next);
            p->next=NULL;
        }
        if(Over())//判断是否游戏结束
            break;
        Sleep(500-Speed*50);//等待,具体时间和等级有关
    }
    system("cls");
    if(Speed==10)//通关
    {
        SetPos(25,25);
        cout<<"碉堡-_-||你通关了"<<endl;
        system("pause");
    }
    else//失败
    {
        SetPos(25,10);
        cout<<"-0- ~~你挂了,最终长度为 "<<Count<<endl;
        system("pause");
    }
}
int main()
{
    Sneak game;
    system("cls");
    cout<<"*****************************************************"<<endl;
    cout<<"*                        贪吃蛇                     *"<<endl;
    cout<<"*****************************************************"<<endl;
    cout<<"*                说明                               *"<<endl;
    cout<<"*            W,A,S,D控制移动                        *"<<endl;
    cout<<"*       每10节蛇身升一级,并提高速度,10级通关      *"<<endl;
    cout<<"*****************************************************"<<endl;
    cout<<"*      何某人制作,百度ID:HapHapYear               *"<<endl;
    cout<<"*********         任意键开始   **********************"<<endl;
    _getch();
    game.Gaming();
    return 0;
}



        
#include<windows.h>
#include<tchar.h>
#include<time.h>
#include<list>

#define ID_TIMER 1
#define ID_START 2
#define ID_PAUSE 3
#define ID_HELP 4
#define ID_RESTART 5
#define ID_QUIT 6
#define ID_COMBOBOX 7
#define LEFT 8
#define UP 9
#define RIGHT 10
#define DOWN 11
#define ID_ESC 27

HWND hHelp;                             //帮助信息对话框句柄
HINSTANCE hInst;                         //实例句柄
RECT rtSnakeHead, rtSnakeNeck, rtSnakeTail, rtFood, rtScore; //重绘区域   
RECT rtMap;                             //地图区域
unsigned int score = 0;                         //得分
int nextDirection;                         //蛇头的下一运动方向
bool foodFlag = false;                                       //标记食物是否还存在
bool gameOver = true;                                        //标记游戏是否结束

//蛇身结点定义
typedef struct{
    int left;
    int top;
    int right;
    int bottom;
    int currentDirection;
}SnakeNode;
std::list<SnakeNode>snake;   //整个蛇身

// 此代码模块中包含的函数的前向声明:
ATOM               MyRegisterClass(HINSTANCE hInstance);                 //注册窗口类
BOOL               InitInstance(HINSTANCE, int);                 //初始化窗口各种控件
LRESULT CALLBACK   WndProc(HWND, UINT, WPARAM, LPARAM);                          //主窗口回调函数
VOID               DrawSurroundings(HDC hdc, HWND hWnd, RECT rtFood);            //绘制地图
VOID               DrawTheSnake(HDC hdc, HWND hWnd);                     //绘制蛇身
VOID               GetTimerElapse(int cursel, unsigned int& timerElapse);//获取用户选择的速度
VOID               SnakeMove(RECT rtFood, int timerElapse);                      //蛇身移动
RECT               CreateFood(HDC hdc);                     //生成食物
BOOL               JudgeGameOver(SnakeNode headNode);                            //判断是否达到游戏结束条件
INT_PTR CALLBACK   Help(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);  //帮助信息对话框回调函数

//程序入口
int APIENTRY _tWinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPTSTR    lpCmdLine,
                       int       nCmdShow)
{
    srand((UINT)time(0));   //时间作为随机数种子
    MSG msg;
    MyRegisterClass(hInstance);

    // 执行应用程序初始化:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    // 主消息循环:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        SnakeNode& headNode = snake.back();  //获取蛇头所在结点
        //获取方向键消息
        switch(msg.wParam)
        {
        case VK_LEFT:
            if(headNode.currentDirection != RIGHT)
                nextDirection = LEFT;
            break;
        case VK_UP:
            if(headNode.currentDirection != DOWN)
                nextDirection = UP;
            break;
        case VK_RIGHT:
            if(headNode.currentDirection != LEFT)
                nextDirection = RIGHT;
            break;
        case VK_DOWN:
            if(headNode.currentDirection != UP)
                nextDirection = DOWN;
            break;
        }

        if (!TranslateMessage(&msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

//注册窗口类
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(wcex);

    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = NULL;
    wcex.lpszClassName  = _T("贪吃蛇");
    wcex.hIconSm        = NULL;

    return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    HWND hWnd;
    hInst = hInstance; // 将实例句柄存储在全局变量中

    hWnd = CreateWindowExA(0, "贪吃蛇", "贪吃蛇蛋疼版", WS_OVERLAPPED|WS_SYSMENU|WS_MINIMIZEBOX,
        380, 90, 606, 568, NULL, NULL, hInstance, NULL);
    CreateWindowA("button", "开始游戏", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 
        20, 10, 100, 30, hWnd, (HMENU)ID_START, hInstance, NULL);
    CreateWindowA("button", "暂停/继续", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 
        150, 10, 100, 30, hWnd, (HMENU)ID_PAUSE, hInstance, NULL);
    CreateWindowA("button", "帮助", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 
        280, 12, 40, 25, hWnd, (HMENU)ID_HELP, hInstance, NULL);
    CreateWindowA("button", "重玩一局", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 
        350, 10, 100, 30, hWnd, (HMENU)ID_RESTART, hInstance, NULL);
    CreateWindowA("button", "退出游戏", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 
        480, 10, 100, 30, hWnd, (HMENU)ID_QUIT, hInstance, NULL);
    CreateWindowA("ComboBox", "速度选择", WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST,
        60, 55, 55, 200, hWnd, (HMENU)ID_COMBOBOX, hInstance, NULL);

    //创建帮助信息对话框
    static DLGTEMPLATE Dlg;
    Dlg.cdit = 0;
    Dlg.cx = 200;
    Dlg.cy = 140;
    Dlg.dwExtendedStyle = 0;
    Dlg.style = WS_POPUPWINDOW|WS_CAPTION;
    Dlg.x = 50;
    Dlg.y = 60;
    hHelp = CreateDialogIndirect(hInst, &Dlg, hWnd, Help);
    SetWindowTextA(hHelp, "帮助");
    ShowWindow(hHelp, SW_HIDE);

    //注册快捷键
    RegisterHotKey(hWnd, ID_START, MOD_CONTROL, VK_RIGHT);
    RegisterHotKey(hWnd, ID_PAUSE, NULL, VK_SPACE);
    RegisterHotKey(hWnd, ID_RESTART, MOD_CONTROL|MOD_SHIFT, VK_SPACE);
    RegisterHotKey(hWnd, ID_HELP, NULL, VK_F1);
    RegisterHotKey(hWnd, ID_ESC, NULL, VK_ESCAPE);

    SendMessageA(GetDlgItem(hWnd,ID_COMBOBOX),
        CB_ADDSTRING, NULL, (LPARAM)("特快"));
    SendMessageA(GetDlgItem(hWnd,ID_COMBOBOX),
        CB_ADDSTRING, NULL, (LPARAM)("较快"));
    SendMessageA(GetDlgItem(hWnd,ID_COMBOBOX),
        CB_ADDSTRING, NULL, (LPARAM)("普通"));
    SendMessageA(GetDlgItem(hWnd,ID_COMBOBOX),
        CB_ADDSTRING, NULL, (LPARAM)("缓慢"));
    SendMessageA(GetDlgItem(hWnd,ID_COMBOBOX),
        CB_ADDSTRING, NULL, (LPARAM)("龟速"));
    SendMessageA(GetDlgItem(hWnd,ID_COMBOBOX), CB_SETCURSEL, 2, NULL);  //默认选择第三项

    EnableWindow(GetDlgItem(hWnd, ID_PAUSE), false); //游戏未开始【暂停/继续】按钮无效

    //初始化蛇身长度及位置
    for(int i=rtMap.left+40;i<140;i+=20)
    {
        SnakeNode node;
        node.left = i;
        node.top = rtMap.top+40;
        node.right = i+20;
        node.bottom = rtMap.top+60;
        node.currentDirection = RIGHT;
        snake.push_back(node);
    }
    if (!hWnd)
    {
        return FALSE;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    static bool bPause;              //游戏是否暂停
    static unsigned int timerElapse; //定时器时间间隔
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_CREATE:
        RECT rtClient;
        int xBrickAmount,yBrickAmount;     //X轴、Y轴砖块数量(每块砖的边长为20)
        GetClientRect(hWnd, &rtClient);    //获取客户区域大小
        xBrickAmount = (rtClient.right-rtClient.left)/20;
        yBrickAmount = (rtClient.bottom-rtClient.top)/20;
        rtMap.left = rtClient.left;
        rtMap.top = rtClient.top+80;
        rtMap.right = rtClient.left+xBrickAmount*20;
        rtMap.bottom = rtClient.top+yBrickAmount*20;

        //输出得分的区域
        rtScore.left = 260;
        rtScore.top = rtMap.top-29;
        rtScore.right = 400;
        rtScore.bottom = rtMap.top-1;
        break;
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        switch (wmId)
        {
        case ID_START:
            {
                bPause = false;
                gameOver = false;
                nextDirection = RIGHT;                                                             //初始方向向右
                int cursel = SendMessage(GetDlgItem(hWnd, ID_COMBOBOX), CB_GETCURSEL, NULL, NULL); //获取用户选择的速度索引号
                GetTimerElapse(cursel, timerElapse);   
                SetTimer(hWnd, ID_TIMER, timerElapse, NULL);
                EnableWindow(GetDlgItem(hWnd,ID_COMBOBOX), false);
                EnableWindow(GetDlgItem(hWnd, ID_PAUSE), true);
                EnableWindow(GetDlgItem(hWnd, ID_START), false);
            }
            break;
        case ID_PAUSE:
            {
                if(!gameOver)
                {
                    if(bPause)
                    {
                        SetTimer(hWnd, ID_TIMER, timerElapse, NULL);
                        bPause = false;
                    }
                    else
                    {
                        KillTimer(hWnd, ID_TIMER);
                        bPause = true;
                    }
                }
            }
            break;
        case ID_RESTART:
            {
                KillTimer(hWnd, ID_TIMER);
                snake.clear();               //清空蛇身所有结点
                //重新初始化蛇身长度及位置
                for(int i=rtMap.left+40; i<140; i+=20)
                {
                    SnakeNode node;
                    node.left = i;
                    node.top = rtMap.top+40;
                    node.right = i+20;
                    node.bottom = node.top+20;
                    node.currentDirection = RIGHT;
                    snake.push_back(node);
                }
                gameOver = true;
                score = 0;
                EnableWindow(GetDlgItem(hWnd, ID_START), true);
                EnableWindow(GetDlgItem(hWnd, ID_PAUSE), false);
                EnableWindow(GetDlgItem(hWnd, ID_COMBOBOX), true);
                InvalidateRect(hWnd, &rtMap, true);
                InvalidateRect(hWnd, &rtScore, true);
            }
            break;
        case ID_HELP:
            {
                if(!bPause)
                {
                    SendMessage(hWnd, WM_COMMAND, ID_PAUSE, NULL);
                }
                ShowWindow(hHelp, SW_SHOWNORMAL);
            }
            break;
        case ID_QUIT:
            SendMessage(hWnd, WM_CLOSE, NULL, NULL);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        //食物被吃掉后重绘分数并再次生成食物
        if(!foodFlag)
        {
            InvalidateRect(hWnd, &rtScore, true);
            rtFood = CreateFood(hdc);
            InvalidateRect(hWnd, &rtFood, true);
        }
        DrawSurroundings(hdc, hWnd, rtFood);
        DrawTheSnake(hdc, hWnd);
        EndPaint(hWnd, &ps);
        break;
        //热键消息处理
    case WM_HOTKEY:
        {
            if((wParam == ID_ESC) && (hHelp == GetActiveWindow()))
                ShowWindow(hHelp, SW_HIDE);    
            else if(hWnd == GetActiveWindow())  //判断窗口是否处于激活状态
            {
                switch(wParam)
                {
                case ID_START:
                    if(IsWindowEnabled(GetDlgItem(hWnd, ID_START)))
                        SendMessage(hWnd, WM_COMMAND, ID_START, NULL);
                    break;
                case ID_PAUSE:
                    SendMessage(hWnd, WM_COMMAND, ID_PAUSE, NULL);
                    break;
                case ID_RESTART:
                    SendMessage(hWnd, WM_COMMAND, ID_RESTART, NULL);
                    break;
                case ID_HELP:
                    SendMessage(hWnd, WM_COMMAND, ID_HELP, NULL);
                    break;
                case ID_ESC:
                    SendMessage(hWnd, WM_CLOSE, NULL, NULL);
                    break;
                }
            }
        }
        break;
        //定时器消息处理
    case WM_TIMER:
        SnakeMove(rtFood, timerElapse);
        InvalidateRect(hWnd, &rtSnakeHead, true);
        InvalidateRect(hWnd, &rtSnakeNeck, false);
        InvalidateRect(hWnd, &rtSnakeTail, true);
        break;
        //处理窗口最小化的消息
    case WM_SIZE:
        wmId = LOWORD(wParam);
        if(wmId == SIZE_MINIMIZED)
        {
            if(!gameOver && !bPause)
                SendMessage(hWnd, WM_COMMAND, ID_PAUSE, NULL);
        }
        break;
        //处理关闭窗口的消息
    case WM_CLOSE:
        {
            if(!gameOver)
            {
                KillTimer(hWnd, ID_TIMER);
                if(MessageBoxA(hWnd, "游戏正在进行,确认退出?", "提醒", MB_OKCANCEL|MB_ICONQUESTION) == IDOK)
                {
                    DestroyWindow(hWnd);
                    PostQuitMessage(0);
                }
                else if(!bPause && !gameOver)
                    SetTimer(hWnd, ID_TIMER, timerElapse, NULL);
            }        
            if(gameOver && MessageBoxA(hWnd, "确认退出贪吃蛇蛋疼版?", "提醒", MB_OKCANCEL|MB_ICONQUESTION) == IDOK)
            {
                DestroyWindow(hWnd);
                PostQuitMessage(0);
            }
        }
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

VOID DrawSurroundings(HDC hdc, HWND hWnd, RECT rtFood)
{    
    //绘制分割线
    MoveToEx(hdc, rtMap.left, rtMap.top-30, NULL);
    LineTo(hdc, rtMap.right, rtMap.top-30);

    TextOutA(hdc, 23, rtMap.top-22, "速度:", strlen("速度:")); 
    TextOutA(hdc, 480, rtMap.top-22, "By:非洲小白脸", strlen("By:非洲小白脸"));

    //自定义字体并输出得分
    char szScore[10];
    LOGFONT font;
    memset(&font, 0, sizeof(font));
    font.lfWidth = 11;
    font.lfHeight = 20;
    font.lfWeight = FW_HEAVY;
    lstrcpy(font.lfFaceName, _T("宋体"));
    HFONT hFont = CreateFontIndirect(&font);
    SelectObject(hdc, hFont);
    wsprintfA(szScore, "得分:%d", score);
    SetTextColor(hdc, RGB(0,99,201));
    TextOutA(hdc, 260, rtMap.top-24, szScore, strlen(szScore));
    DeleteObject(hFont);

    //绘制地图(砖块边长为20)
    HBRUSH hBrush = CreateSolidBrush(RGB(139,69,19));
    SelectObject(hdc, hBrush);
    for(int i=rtMap.left; i<rtMap.right; i+=20)
    {
        Rectangle(hdc, i, rtMap.top, i+20, rtMap.top+20);
        Rectangle(hdc, i, rtMap.bottom-20, i+20, rtMap.bottom);
    }
    for(int j=rtMap.top; j<rtMap.bottom; j+=20)
    {
        Rectangle(hdc, rtMap.left, j, rtMap.left+20, j+20);
        Rectangle(hdc, rtMap.right-20, j, rtMap.right, j+20);
    }

    //绘制食物
    hBrush = CreateSolidBrush(RGB(255,0,0));
    SelectObject(hdc, hBrush);
    Ellipse(hdc, rtFood.left, rtFood.top, rtFood.right, rtFood.bottom);
    DeleteObject(hBrush);
}

VOID GetTimerElapse(int cursel, unsigned int& timerElapse)    
{
    switch(cursel)
    {
    case 0:
        timerElapse = 50;
        break;
    case 1:
        timerElapse = 100;
        break;
    case 2:
        timerElapse = 200;
        break;
    case 3:
        timerElapse = 400;
        break;
    case 4:
        timerElapse = 600;
        break;
    }
}

VOID DrawTheSnake(HDC hdc, HWND hWnd)
{
    //画蛇身
    HBRUSH hBrush = CreateSolidBrush(RGB(124,252,0));
    SelectObject(hdc, hBrush);
    std::list<SnakeNode>::iterator sIter = snake.begin();
    for(unsigned int i=0; i<snake.size()-1; i++,sIter++)
        Rectangle(hdc, sIter->left, sIter->top, sIter->right, sIter->bottom);

    //画蛇头
    SnakeNode headNode = snake.back();
    switch(headNode.currentDirection)
    {
    case LEFT:
        {
            POINT ptHead[] = {sIter->left,sIter->top+5,
                sIter->right,sIter->top,
                sIter->right,sIter->bottom,
                sIter->left,sIter->bottom-5};
            Polygon(hdc, ptHead, 4);
        }
        break;
    case UP:
        {
            POINT ptHead[] = {sIter->left+5,sIter->top,
                sIter->right-5,sIter->top,
                sIter->right,sIter->bottom,
                sIter->left,sIter->bottom};
            Polygon(hdc, ptHead, 4);
        }
        break;
    case RIGHT:
        {
            POINT ptHead[] = {sIter->left,sIter->top,
                sIter->right,sIter->top+5,
                sIter->right,sIter->bottom-5,
                sIter->left,sIter->bottom};
            Polygon(hdc, ptHead, 4);
        }
        break;
    case DOWN:
        {
            POINT ptHead[] = {sIter->left,sIter->top,
                sIter->right,sIter->top,
                sIter->right-5,sIter->bottom,
                sIter->left+5,sIter->bottom,
            };
            Polygon(hdc, ptHead, 4);
        }
        break;
    }

    //判断游戏结束
    if(!gameOver)
    {
        if(JudgeGameOver(headNode))
        {
            KillTimer(hWnd, ID_TIMER);
            EnableWindow(GetDlgItem(hWnd, ID_PAUSE), false);
            MessageBoxA(hWnd, "Game Over!", "提醒", MB_OK);
        }
    }
}

VOID SnakeMove(RECT rtFood, int timerElapse)
{
    SnakeNode headNode = snake.back();
    //获取蛇颈区域
    rtSnakeNeck.left = headNode.left;
    rtSnakeNeck.top = headNode.top;
    rtSnakeNeck.right = headNode.right;
    rtSnakeNeck.bottom = headNode.bottom;

    SnakeNode node;
    //根据蛇头的下一方向算出蛇头的新位置
    switch(nextDirection)
    {
    case LEFT:
        node.left = headNode.left-20;
        node.top = headNode.top;
        node.right = headNode.left;
        node.bottom = headNode.bottom;
        node.currentDirection = LEFT;
        snake.push_back(node);
        break;
    case UP:
        node.left = headNode.left;
        node.top = headNode.top-20;
        node.right = headNode.right;
        node.bottom = headNode.top;
        node.currentDirection = UP;
        snake.push_back(node);
        break;
    case RIGHT:
        node.left = headNode.right;
        node.top = headNode.top;
        node.right = headNode.right+20;
        node.bottom = headNode.bottom;
        node.currentDirection = RIGHT;
        snake.push_back(node);
        break;
    case DOWN:
        node.left = headNode.left;
        node.top = headNode.bottom;
        node.right = headNode.right;
        node.bottom = headNode.bottom+20;
        node.currentDirection = DOWN;
        snake.push_back(node);
        break;
    }
    //获取蛇头区域
    headNode = snake.back();
    rtSnakeHead.left = headNode.left;
    rtSnakeHead.top = headNode.top;
    rtSnakeHead.right = headNode.right;
    rtSnakeHead.bottom = headNode.bottom;

    //未吃到食物
    if(!(headNode.left==rtFood.left && headNode.top==rtFood.top))
    {
        std::list<SnakeNode>::iterator iTail = snake.begin();
        rtSnakeTail.left = iTail->left;
        rtSnakeTail.top = iTail->top-1;
        rtSnakeTail.right = iTail->right;
        rtSnakeTail.bottom = iTail->bottom+1;
        snake.pop_front();      
    }
    //吃到食物
    else        {
        switch(timerElapse)
        {
        case 50:
            score+=100;
            break;
        case 100:
            score+=60;
            break;
        case 200:
            score+=40;
            break;
        case 400:
            score+=20;
            break;
        case 600:
            score+=10;
            break;
        }
        foodFlag = false;
    }
}

RECT CreateFood(HDC hdc)
{
    RECT rtFood;                                //食物所在区域
    int xNumber, yNumber;                //食物所在处对应的砖块序号
    int xBrickAmount,yBrickAmount;                //X轴、Y轴砖块总量
    xBrickAmount = (rtMap.right-rtMap.left)/20; 
    yBrickAmount = (rtMap.bottom-rtMap.top)/20;
    //随机生成砖块序号
    xNumber = rand()%(xBrickAmount-2);          
    yNumber = rand()%(yBrickAmount-2);

    //根据砖块序号确定食物位置
    rtFood.left = rtMap.left+(xNumber+1)*20;
    rtFood.right = rtFood.left+20;
    rtFood.top = rtMap.top+(yNumber+1)*20;
    rtFood.bottom = rtFood.top+20;

    foodFlag = true;

    return rtFood;

}

BOOL JudgeGameOver(SnakeNode headNode)
{
    //碰到墙则游戏结束
    if(headNode.left==rtMap.left || headNode.top==rtMap.top 
        || headNode.right==rtMap.right || headNode.bottom==rtMap.bottom)
    {
        gameOver = true;
        return true;
    }
    //咬到自己身体则游戏结束
    else
    {
        SnakeNode head = snake.back();
        std::list<SnakeNode>::iterator sIter = snake.begin();
        for(unsigned int i=0; i<snake.size()-1; i++,sIter++)
            if(head.left==sIter->left && head.top==sIter->top)
            {
                gameOver = true;
                return true;
            }
    }
    return false;
}

INT_PTR CALLBACK Help(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        if(LOWORD(wParam) == IDCANCEL)
        {    
            ShowWindow(hDlg, SW_HIDE);
            return (INT_PTR)TRUE;
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT dPs;
            HDC hdc = BeginPaint(hDlg, &dPs);
            LOGFONT font;
            memset(&font, 0, sizeof(font));
            font.lfWidth = 8;
            font.lfHeight = 16;
            font.lfWeight = FW_HEAVY;
            lstrcpy(font.lfFaceName, _T("宋体"));
            HFONT hFont = CreateFontIndirect(&font);
            SelectObject(hdc, hFont);
            SetTextColor(hdc, RGB(111,55,155));
            SetBkColor(hdc, GetSysColor(COLOR_3DFACE));

            TextOutA(hdc, 5, 5, "游戏规则:", sizeof("游戏规则:"));
            std::string str = "1.通过方向键上、下、左、右控制蛇游动的方向。";
            TextOutA(hdc, 5, 25, str.c_str(), str.size());
            str = "2.该蛇有五种游动速度可供玩家选择。";
            TextOutA(hdc, 5, 45, str.c_str(), str.size());
            str = "3.吃到食物后身体会增长一节并获得相应的分数。";
            TextOutA(hdc, 5, 65, str.c_str(), str.size());
            str = "4.不同游动速度下食物的分值不同,越快则越高。";
            TextOutA(hdc, 5, 85, str.c_str(), str.size());
            str = "5.蛇头碰到自身身体或围墙则游戏结束。";
            TextOutA(hdc, 5, 105, str.c_str(), str.size());

            TextOutA(hdc, 5, 135, "快捷键:", sizeof("快捷键:"));
            str = "开始游戏:Ctrl+右方向键";
            TextOutA(hdc, 5, 155, str.c_str(), str.size());
            str = "暂停/继续游戏:Space(空格键)";
            TextOutA(hdc, 5, 175, str.c_str(), str.size());
            str = "重玩一局:Ctrl+Shift+Space";
            TextOutA(hdc, 5, 195, str.c_str(), str.size());
            str = "退出游戏:Esc";
            TextOutA(hdc, 5, 215, str.c_str(), str.size());
            str = "帮助:F1";
            TextOutA(hdc, 5, 235, str.c_str(), str.size());

            DeleteObject(hFont);
            EndPaint(hDlg, &dPs);
        }
        break;
    }
    return (INT_PTR)FALSE;
}
原文地址:https://www.cnblogs.com/fripside/p/3000000.html