zoukankan      html  css  js  c++  java
  • 贪吃蛇

    在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;
    }
  • 相关阅读:
    北亚一例服务器硬盘故障的数据恢复案例研究
    Syabse数据库无法启动的解决方案
    raid5 阵列硬盘离线数据恢复成功案例
    MSSQL 2000 错误823恢复案例
    服务器数据恢复案例
    虚拟机数据丢失的数据恢复过程和数据恢复方法
    数据库打开时报错该如何解决
    误删除导致文件系统中的邮件丢失的数据恢复过程
    第16月第25天 tableView设置UITableViewStyleGrouped顶部有空余高度
    第16月第24天 find iconv sublime utf-8
  • 原文地址:https://www.cnblogs.com/fripside/p/3000000.html
Copyright © 2011-2022 走看看