1. 程式人生 > >C語言+easyX介面庫實現貪吃蛇

C語言+easyX介面庫實現貪吃蛇

問題描述:
實現貪吃蛇遊戲,有等級,分數,並且會儲存最高等級和最高分

easysnake.h程式碼:

#pragma once

#include <stdio.h>
#include <graphics.h>
#include <windows.h>
#include <mmsystem.h>
#include <time.h>
#include <conio.h>
#include "resource.h"
#pragma comment(lib, "winmm.lib")

#define SNAKE_DRAW_SIZE     15
#define WND_WIDTH 1000 #define WND_HEIGHT 600 #define REGION_WIDTH 600 #define REGION_HEIGHT 600 #define RIGHT_EDGE_WIDTH 10 #define HEADLINE_POSX 265 #define HEADLINE_POSY 120 #define TEXT_TIME_POSX 670 #define TEXT_TIME_POSY 100 #define TEXT_LEVEL_POSX 670
#define TEXT_LEVEL_POSY 100 #define TEXT_SCORE_POSX 670 #define TEXT_SCORE_POSY 200 #define TEXT_LEN_POSX 670 #define TEXT_LEN_POSY 300 #define TEXT_HIGHSCORE_POSX 670 #define TEXT_HIGHSCORE_POSY 400 #define TEXT_HIGHLEVEL_POSX 670 #define TEXT_HIGHLEVEL_POSY 500 #define SNAKE_INIT_PT_X (REGION_WIDTH / SNAKE_DRAW_SIZE / 5)
#define SNAKE_INIT_PT_Y (REGION_HEIGHT / SNAKE_DRAW_SIZE / 2) #define FIRST_ITEM_POSX 375 #define FIRST_ITEM_POSY 250 #define FIRST_ITEM_WIDTH 220 #define FIRST_ITEM_HEIGHT 30 #define SECOND_ITEM_POSX 375 #define SECOND_ITEM_POSY 350 #define SECOND_ITEM_WIDTH 220 #define SECOND_ITEM_HEIGHT 30 #define THIRD_ITEM_POSX 375 #define THIRD_ITEM_POSY 450 #define THIRD_ITEM_WIDTH 220 #define THIRD_ITEM_HEIGHT 30 #define BIGFOOD_SHOWTIME 6000 #define BIGFOOD_STEPTIME 100 #define FOOD_SCORE 1 #define BIG_FOOD_SCORE 5 #define INIT_SPEED 110 #define MINUS_SPEED 10 #define TOTAL_TIME 100 #define SNAKE_MAX ((REGION_WIDTH / SNAKE_DRAW_SIZE) * (REGION_HEIGHT / SNAKE_DRAW_SIZE)) #define BREAKTHROUGHAPPNAME L"BreakThrough" #define BREAKTHROUGHSCORE L"HighScore" #define BREAKTHROUGHLEVEL L"HighLevel" #define TIMELIMITEDAPPNAME L"TimeLimited" #define TIMELIMITEDSCORE L"HighScore" int arrScore[] = { 0, 8, 16, 24, 32, 40, 48, 60, 72, 85, 95, 118, 130, 155, 170, 190, 210, 230, 250, 270, 300, 350, 400, 460, 500, 550, 600, 650, 700, 750, 810, 880, 950, 1000, 1100, 1250, 1400, 1600, 1850, 2100, 2400, 2700, 3000, 3400, 3800, 4200, 4600, 5000, 5500, 5900, 6300, 6800, 7500, 8000, 8500, 9000, 9500, 10000 }; enum EmPattern { emBreakThroughPattern = 1, emTimeLimitedPattern, emIntelligencePattern, }; enum EmStage { emChooseStage = 1, emPlayStage, }; enum EmDir { emDirUp = 72, emDirDown = 80, emDirLeft = 75, emDirRight = 77, }; struct Point { int x; int y; }; struct Snake { int nCount; Point pt[SNAKE_MAX]; EmDir dir; }; struct Food { Point fpt; char isEat; }; struct BigFood { Point fpt; char isEat; }; EmStage stage = EmStage::emChooseStage; EmPattern pattern = EmPattern::emBreakThroughPattern; Snake snake; Food food; BigFood bigFood; int nBigFoodTimer = 0; int nCurLevel = 1; int nCurScore = 0; int nSnakeLen = 3; int nHighLevel = 0; int nHighScore = 0; int nCurSpeed = INIT_SPEED; int nRemainTime = TOTAL_TIME; int nTimePast = 0; void SetMouseNormal(); void SetMouseHand(); void SetLevelText(); void SetHoverStyle(); void SetNormalStyle(); void TackleMouseMove(int x, int y); void TackleLeftButtonDown(int x, int y); void TackleMouseAction(); void InitFirstScene(); void InitSecondBackGround(); void InitSecondScene(); void GameInit(); void PlayGame(); int IsFoodPosOk(int x, int y); void ProduceFood(); void DrawFood(); int ProduceBigFood(); void DrawBigFood(); int IsEatBigFood(); void EatFood(); void LevelUp(); void DrawSnake(); void SnakeMove(); void ChangeDir(); void BreakSnake(); void WriteRecord(); void BigFoodDisappear(); void TimeEclipse(); void DecideHeadDirection(); void DrawSnakeHead(int nIndex); void DecideCornerDirection(int idx); void DrawCorner(int nIndex, int idx); void DecideBodyDirection(int idx); void DrawBody(int nIndex, int idx); void DecideTailDirection(int idx); void DrawTail(int nIndex, int idx); void BreakThroughPattern(); void TimeLimitedPattern();

easysnake.cpp

#include "easysnake.h"

BOOL KExpandEnvironmentString(IN LPCTSTR lpEnvironmentString, OUT LPTSTR lpExpandString, IN ULONG ulExpandStringLength)
{
    BOOL bResult = FALSE;

    LPTSTR lpBuffer = NULL;
    ULONG ulRetLength = 0;

    if (!lpEnvironmentString || !lpExpandString || 1 > ulExpandStringLength)
    {
        goto _abort;
    }

    ulRetLength = ::ExpandEnvironmentStrings(lpEnvironmentString, NULL, 0);
    if (1 > ulRetLength || ulRetLength > ulExpandStringLength - 1)
    {
        goto _abort;
    }

    __try
    {
        lpBuffer = new TCHAR[ulRetLength];
        if (!lpBuffer)
        {
            goto _abort;
        }

        ::RtlZeroMemory(lpBuffer, sizeof(TCHAR)* ulRetLength);

        ulRetLength = ::ExpandEnvironmentStrings(lpEnvironmentString, lpBuffer, ulRetLength);
        if (ulRetLength && ulRetLength <= ulExpandStringLength - 1)
        {
            _tcsncpy_s(lpExpandString, ulExpandStringLength - 1, lpBuffer, ulRetLength);
            bResult = TRUE;
        }
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        bResult = FALSE;
    }

_abort:

    if (lpBuffer)
    {
        delete[] lpBuffer;
        lpBuffer = NULL;
    }

    return bResult;
}

void SetMouseNormal()
{
    HCURSOR hcur = LoadCursor(NULL, IDC_ARROW);
    HWND hwnd = GetHWnd();
    SetClassLong(hwnd, GCL_HCURSOR, (long)hcur);
}

void SetMouseHand()
{
    HCURSOR hcur = LoadCursor(NULL, MAKEINTRESOURCE(32649));
    HWND hwnd = GetHWnd();
    SetClassLong(hwnd, GCL_HCURSOR, (long)hcur);
}

void SetLevelText()
{
    switch (pattern)
    {
    case EmPattern::emBreakThroughPattern:
        outtextxy(FIRST_ITEM_POSX, FIRST_ITEM_POSY, L"闖關模式");
        break;
    case EmPattern::emTimeLimitedPattern:
        outtextxy(SECOND_ITEM_POSX, SECOND_ITEM_POSY, L"限時模式");
        break;
    case EmPattern::emIntelligencePattern:
        outtextxy(THIRD_ITEM_POSX, THIRD_ITEM_POSY, L"智慧模式");
        break;
    default:
        break;
    }
}

void SetHoverStyle()
{
    settextcolor(RGB(255, 0, 119));
    SetLevelText();
    SetMouseHand();
}

void SetNormalStyle()
{
    settextcolor(BROWN);
    SetLevelText();
    SetMouseNormal();
}

void TackleMouseMove(int x, int y)
{
    if (stage == EmStage::emPlayStage)
        return;

    if (x > FIRST_ITEM_POSX && x < FIRST_ITEM_POSX + FIRST_ITEM_WIDTH && y >FIRST_ITEM_POSY && y < FIRST_ITEM_POSY + FIRST_ITEM_HEIGHT)
    {
        pattern = EmPattern::emBreakThroughPattern;
        SetHoverStyle();
        return;
    }
    else
    {
        pattern = EmPattern::emBreakThroughPattern;
        SetNormalStyle();
    }

    if (x > SECOND_ITEM_POSX && x < SECOND_ITEM_POSX + SECOND_ITEM_WIDTH && y > SECOND_ITEM_POSY && y < SECOND_ITEM_POSY + SECOND_ITEM_HEIGHT)
    {
        pattern = EmPattern::emTimeLimitedPattern;
        SetHoverStyle();
        return;
    }
    else
    {
        pattern = EmPattern::emTimeLimitedPattern;
        SetNormalStyle();
    }

    if (x > THIRD_ITEM_POSX && x < THIRD_ITEM_POSX + THIRD_ITEM_WIDTH && y > THIRD_ITEM_POSY && y < THIRD_ITEM_POSY + THIRD_ITEM_HEIGHT)
    {
        pattern = EmPattern::emIntelligencePattern;
        SetHoverStyle();
    }
    else
    {
        pattern = EmPattern::emIntelligencePattern;
        SetNormalStyle();
    }
}

void TimeLimitedPattern()
{
    settextstyle(20, 20, L"楷體", 0, 0, 900, 0, 0, 0);
    setbkmode(TRANSPARENT);
    settextcolor(RGB(255, 0, 0));

    WCHAR szCurRemainTime[32];
    WCHAR szCurScore[32];
    WCHAR szSnakeLen[32];
    WCHAR szHighScore[32];

    swprintf_s(szCurRemainTime, L"剩餘時間: %d", nRemainTime);
    swprintf_s(szCurScore, L"當前得分: %d", nCurScore);
    swprintf_s(szSnakeLen, L"蛇身長度: %d", snake.nCount);
    swprintf_s(szHighScore, L"最高分數: %d", nHighScore);

    outtextxy(TEXT_TIME_POSX, TEXT_TIME_POSY, szCurRemainTime);
    outtextxy(TEXT_SCORE_POSX, TEXT_SCORE_POSY, szCurScore);
    outtextxy(TEXT_LEN_POSX, TEXT_LEN_POSY, szSnakeLen);
    outtextxy(TEXT_HIGHSCORE_POSX, TEXT_HIGHSCORE_POSY, szHighScore);
}

void BreakThroughPattern()
{
    settextstyle(20, 20, L"楷體", 0, 0, 900, 0, 0, 0);
    setbkmode(TRANSPARENT);
    settextcolor(RGB(255, 0, 0));

    WCHAR szCurLevel[32];
    WCHAR szCurScore[32];
    WCHAR szSnakeLen[32];
    WCHAR szHighLevel[32];
    WCHAR szHighScore[32];

    swprintf_s(szCurLevel, L"當前級別: %d", nCurLevel);
    swprintf_s(szCurScore, L"當前得分: %d", nCurScore);
    swprintf_s(szSnakeLen, L"蛇身長度: %d", snake.nCount);
    swprintf_s(szHighLevel, L"最高級別: %d", nHighLevel);
    swprintf_s(szHighScore, L"最高分數: %d", nHighScore);

    outtextxy(TEXT_LEVEL_POSX, TEXT_LEVEL_POSY, szCurLevel);
    outtextxy(TEXT_SCORE_POSX, TEXT_SCORE_POSY, szCurScore);
    outtextxy(TEXT_LEN_POSX, TEXT_LEN_POSY, szSnakeLen);
    outtextxy(TEXT_HIGHSCORE_POSX, TEXT_HIGHSCORE_POSY, szHighLevel);
    outtextxy(TEXT_HIGHLEVEL_POSX, TEXT_HIGHLEVEL_POSY, szHighScore);
}

void TackleLeftButtonDown(int x, int y)
{
    if (x > FIRST_ITEM_POSX && x < FIRST_ITEM_POSX + FIRST_ITEM_WIDTH && y >FIRST_ITEM_POSY && y < FIRST_ITEM_POSY + FIRST_ITEM_HEIGHT)
    {
        pattern = EmPattern::emBreakThroughPattern;
        InitSecondScene();
    }

    if (x > SECOND_ITEM_POSX && x < SECOND_ITEM_POSX + SECOND_ITEM_WIDTH && y > SECOND_ITEM_POSY && y < SECOND_ITEM_POSY + SECOND_ITEM_HEIGHT)
    {
        pattern = EmPattern::emTimeLimitedPattern;
        InitSecondScene();
    }


    if (x > THIRD_ITEM_POSX && x < THIRD_ITEM_POSX + THIRD_ITEM_WIDTH && y > THIRD_ITEM_POSY && y < THIRD_ITEM_POSY + THIRD_ITEM_HEIGHT)
    {
        pattern = EmPattern::emIntelligencePattern;
        InitSecondScene();
    }
}

void TackleMouseAction()
{
    MOUSEMSG msg;
    while (1)
    {
        msg = GetMouseMsg();//獲取滑鼠資訊
        switch (msg.uMsg)
        {
        case WM_LBUTTONDOWN://處理滑鼠的左鍵點選訊息
            TackleLeftButtonDown(msg.x, msg.y);
            break;
        case WM_MOUSEMOVE://處理滑鼠的左鍵點選訊息
            TackleMouseMove(msg.x, msg.y);
            break;
        default:
            break;
        }
    }
}

void InitFirstScene()
{
    cleardevice();
    stage = EmStage::emChooseStage;

    IMAGE img;
    for (int i = 0; i < 22; i++)
    {
        loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG1), SNAKE_DRAW_SIZE * 3, SNAKE_DRAW_SIZE * 3);
        putimage(4 + SNAKE_DRAW_SIZE * 3 * i, 0, &img);
    }

    settextstyle(38, 38, L"楷體", 0, 0, 1000, 0, 0, 0);
    setbkmode(TRANSPARENT);
    settextcolor(RGB(255, 0, 0));
    outtextxy(HEADLINE_POSX, HEADLINE_POSY, L"貪吃蛇大作戰");

    settextstyle(28, 28, L"楷體", 0, 0, 1000, 0, 0, 0);
    setbkmode(TRANSPARENT);
    pattern = EmPattern::emBreakThroughPattern;
    SetNormalStyle();
    pattern = EmPattern::emTimeLimitedPattern;
    SetNormalStyle();
    pattern = EmPattern::emIntelligencePattern;
    SetNormalStyle();
    pattern = EmPattern::emBreakThroughPattern;
    TackleMouseAction();
}

void InitSecondBackGround()
{
    setlinecolor(RED);
    setlinestyle(PS_SOLID, RIGHT_EDGE_WIDTH);
    line(REGION_WIDTH + 4, 0, REGION_WIDTH + 4, REGION_HEIGHT);
    if (EmPattern::emBreakThroughPattern == pattern)
        BreakThroughPattern();
    else if (EmPattern::emTimeLimitedPattern == pattern)
        TimeLimitedPattern();
    else if (EmPattern::emIntelligencePattern == pattern)
        BreakThroughPattern();
}

void InitSecondScene()
{
    cleardevice();
    stage = EmStage::emPlayStage;

    GameInit();
    InitSecondBackGround();
    PlayGame();
}

void GameInit()
{
    snake.dir = EmDir::emDirRight;
    snake.nCount = 3;
    for (int i = 0; i < snake.nCount; i++)
    {
        snake.pt[i].x = SNAKE_INIT_PT_X - i;
        snake.pt[i].y = SNAKE_INIT_PT_Y;
    }
    food.isEat = 1;
    bigFood.isEat = 1;
    nBigFoodTimer = 0;

    WCHAR szTempPath[MAX_PATH] = { 0 };
    WCHAR szIniPath[MAX_PATH] = { 0 };
    KExpandEnvironmentString(L"%TEMP%", szTempPath, MAX_PATH);
    swprintf_s(szIniPath, L"%s\\record.ini", szTempPath);
    nCurSpeed = INIT_SPEED;
    nCurLevel = 1;
    nCurScore = 0;
    nSnakeLen = 3;
    nRemainTime = TOTAL_TIME;
    nTimePast = 0;
    nHighLevel = ::GetPrivateProfileInt(BREAKTHROUGHAPPNAME, BREAKTHROUGHLEVEL, 1, szIniPath);
    if (pattern == EmPattern::emTimeLimitedPattern)
        nHighScore = ::GetPrivateProfileInt(TIMELIMITEDAPPNAME, TIMELIMITEDSCORE, 0, szIniPath);
    else
        nHighScore = ::GetPrivateProfileInt(BREAKTHROUGHAPPNAME, BREAKTHROUGHSCORE, 0, szIniPath);
}

void PlayGame()
{
    while (1)
    {
        while (!_kbhit())
        {
            ProduceFood();
            BigFoodDisappear();
            TimeEclipse();
            BeginBatchDraw();
            cleardevice();
            InitSecondBackGround();
            DrawFood();
            DrawBigFood();
            EatFood();
            SnakeMove();
            DrawSnake();
            Sleep(nCurSpeed);
            EndBatchDraw();
            BreakSnake();
        }
        ChangeDir();
    }
}

void TimeEclipse()
{
    if (pattern != EmPattern::emTimeLimitedPattern)
        return;

    nTimePast += nCurSpeed;
    nRemainTime = TOTAL_TIME - nTimePast / 1000;
    nCurSpeed = INIT_SPEED - nTimePast / 1000;
    if (nRemainTime < 0)
    {
        WCHAR szScore[32] = { 0 };
        swprintf_s(szScore, L"你的得分是: %d", nCurScore);
        ::MessageBox(0, szScore, L"時間到", 0);
        WriteRecord();
        InitFirstScene();
    }
}

void BigFoodDisappear()
{
    if (1 == bigFood.isEat)
        return;

    nBigFoodTimer += BIGFOOD_STEPTIME;//大食物定時消失
    if (nBigFoodTimer >= BIGFOOD_SHOWTIME)
    {
        bigFood.isEat = 1;
        nBigFoodTimer = 0;
    }
}

void WriteRecord()
{
    WCHAR szTempPath[MAX_PATH] = { 0 };
    WCHAR szIniPath[MAX_PATH] = { 0 };
    WCHAR szHighScore[8] = { 0 };
    WCHAR szHighLevel[8] = { 0 };
    KExpandEnvironmentString(L"%TEMP%", szTempPath, MAX_PATH);
    swprintf_s(szIniPath, L"%s\\record.ini", szTempPath);

    if (pattern == EmPattern::emBreakThroughPattern)
    {
        nHighLevel = ::GetPrivateProfileInt(BREAKTHROUGHAPPNAME, BREAKTHROUGHLEVEL, 1, szIniPath);
        nHighScore = ::GetPrivateProfileInt(BREAKTHROUGHAPPNAME, BREAKTHROUGHSCORE, 0, szIniPath);
        if (nCurScore > nHighScore)
        {
            swprintf_s(szHighScore, L"%d", nCurScore);
            WritePrivateProfileString(BREAKTHROUGHAPPNAME, BREAKTHROUGHSCORE, szHighScore, szIniPath);
        }
        if (nCurLevel > nHighLevel)
        {
            swprintf_s(szHighLevel, L"%d", nCurLevel);
            WritePrivateProfileString(BREAKTHROUGHAPPNAME, BREAKTHROUGHLEVEL, szHighLevel, szIniPath);
        }
    }
    else if (pattern == EmPattern::emTimeLimitedPattern)
    {
        nHighScore = ::GetPrivateProfileInt(TIMELIMITEDAPPNAME, TIMELIMITEDSCORE, 0, szIniPath);
        if (nCurScore > nHighScore)
        {
            swprintf_s(szHighScore, L"%d", nCurScore);
            WritePrivateProfileString(TIMELIMITEDAPPNAME, TIMELIMITEDSCORE, szHighScore, szIniPath);
        }
    }
}

void BreakSnake()
{
    if (snake.pt[0].x < 0 || snake.pt[0].x > REGION_WIDTH / SNAKE_DRAW_SIZE - 1 || snake.pt[0].y < 0 || snake.pt[0].y > REGION_HEIGHT / SNAKE_DRAW_SIZE - 1)
    {
        ::MessageBox(0, L"你撞牆了", L"遊戲失敗", 0);
        WriteRecord();
        InitFirstScene();
    }

    for (int i = snake.nCount - 2; i > 0; i--)
    {
        if (snake.pt[i].x == snake.pt[0].x && snake.pt[i].y == snake.pt[0].y)
        {
            ::MessageBox(0, L"你咬到尾巴了", L"遊戲失敗", 0);
            WriteRecord();
            InitFirstScene();
        }
    }
}

void ChangeDir()
{
    int dir = _getch();
    switch (dir)
    {
    case EmDir::emDirUp:
        if (snake.dir != EmDir::emDirDown)
            snake.dir = EmDir::emDirUp;
        break;
    case EmDir::emDirDown:
        if (snake.dir != EmDir::emDirUp)
            snake.dir = EmDir::emDirDown;
        break;
    case EmDir::emDirLeft:
        if (snake.dir != EmDir::emDirRight)
            snake.dir = EmDir::emDirLeft;
        break;
    case EmDir::emDirRight:
        if (snake.dir != EmDir::emDirLeft)
            snake.dir = EmDir::emDirRight;
        break;
    default:
        break;
    }
}

void SnakeMove()
{
    for (int i = snake.nCount; i > 0; i--)
    {
        snake.pt[i].x = snake.pt[i - 1].x;
        snake.pt[i].y = snake.pt[i - 1].y;
    }
    switch (snake.dir)
    {
    case EmDir::emDirUp:
        snake.pt[0].y--;
        break;
    case EmDir::emDirDown:
        snake.pt[0].y++;
        break;
    case EmDir::emDirLeft:
        snake.pt[0].x--;
        break;
    case EmDir::emDirRight:
        snake.pt[0].x++;
        break;
    default:
        break;
    }
}

void DecideHeadDirection()
{
    if (snake.pt[0].y == snake.pt[1].y && snake.pt[0].x > snake.pt[1].x)//頭往右走
        DrawSnakeHead(0);
    else if (snake.pt[0].y == snake.pt[1].y && snake.pt[0].x < snake.pt[1].x)//頭往左走
        DrawSnakeHead(1);
    else if (snake.pt[0].x == snake.pt[1].x && snake.pt[0].y < snake.pt[1].y)//頭往上走
        DrawSnakeHead(2);
    else if (snake.pt[0].x == snake.pt[1].x && snake.pt[0].y > snake.pt[1].y)//頭往下走
        DrawSnakeHead(3);
}

void DrawSnakeHead(int nIndex)
{
    IMAGE img;
    loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG2 + nIndex), SNAKE_DRAW_SIZE, SNAKE_DRAW_SIZE);
    putimage(snake.pt[0].x * SNAKE_DRAW_SIZE, snake.pt[0].y * SNAKE_DRAW_SIZE, &img);
}

void DecideCornerDirection(int idx)
{
    if (snake.pt[idx].y > snake.pt[idx - 1].y && snake.pt[idx].x == snake.pt[idx - 1].x && snake.pt[idx].y == snake.pt[idx + 1].y && snake.pt[idx].x > snake.pt[idx + 1].x)
        DrawCorner(0, idx);//右->上
    else if (snake.pt[idx].y == snake.pt[idx - 1].y && snake.pt[idx].x > snake.pt[idx - 1].x && snake.pt[idx].y > snake.pt[idx + 1].y && snake.pt[idx].x == snake.pt[idx + 1].x)
        DrawCorner(0, idx);//下->左

    else if (snake.pt[idx].y > snake.pt[idx - 1].y && snake.pt[idx].x == snake.pt[idx - 1].x && snake.pt[idx].y == snake.pt[idx + 1].y && snake.pt[idx].x < snake.pt[idx + 1].x)
        DrawCorner(1, idx);//左->上
    else if (snake.pt[idx].y == snake.pt[idx - 1].y && snake.pt[idx].x < snake.pt[idx - 1].x && snake.pt[idx].y > snake.pt[idx + 1].y && snake.pt[idx].x == snake.pt[idx + 1].x)
        DrawCorner(1, idx);//下->右

    else if (snake.pt[idx].y < snake.pt[idx - 1].y && snake.pt[idx].x == snake.pt[idx - 1].x && snake.pt[idx].y == snake.pt[idx + 1].y && snake.pt[idx].x > snake.pt[idx + 1].x)
        DrawCorner(2, idx);//右->下
    else if (snake.pt[idx].y == snake.pt[idx - 1].y && snake.pt[idx].x > snake.pt[idx - 1].x && snake.pt[idx].y < snake.pt[idx + 1].y && snake.pt[idx].x == snake.pt[idx + 1].x)
        DrawCorner(2, idx);//上->左

    else if (snake.pt[idx].y < snake.pt[idx - 1].y && snake.pt[idx].x == snake.pt[idx - 1].x && snake.pt[idx].y == snake.pt[idx + 1].y && snake.pt[idx].x < snake.pt[idx + 1].x)
        DrawCorner(3, idx);//左->下
    else if (snake.pt[idx].y == snake.pt[idx - 1].y && snake.pt[idx].x < snake.pt[idx - 1].x && snake.pt[idx].y < snake.pt[idx + 1].y && snake.pt[idx].x == snake.pt[idx + 1].x)
        DrawCorner(3, idx);//上->右
    else
        DecideBodyDirection(idx);//不是corner的情況在考慮body
}

void DrawCorner(int nIndex, int idx)
{
    IMAGE img;
    loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG6 + nIndex), SNAKE_DRAW_SIZE, SNAKE_DRAW_SIZE);
    putimage(snake.pt[idx].x * SNAKE_DRAW_SIZE, snake.pt[idx].y * SNAKE_DRAW_SIZE, &img);
}

void DecideBodyDirection(int idx)
{
    if (snake.pt[idx].x == snake.pt[idx - 1].x || snake.pt[idx].x == snake.pt[idx + 1].x)//上下
        DrawBody(0, idx);
    else if (snake.pt[idx].y == snake.pt[idx - 1].y || snake.pt[idx].y == snake.pt[idx + 1].y)//左右
        DrawBody(1, idx);
}

void DrawBody(int nIndex, int idx)
{
    IMAGE img;
    loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG10 + nIndex), SNAKE_DRAW_SIZE, SNAKE_DRAW_SIZE);
    putimage(snake.pt[idx].x * SNAKE_DRAW_SIZE, snake.pt[idx].y * SNAKE_DRAW_SIZE, &img);
}

void DecideTailDirection()
{
    int idx = snake.nCount - 1;
    if (snake.pt[idx].y == snake.pt[idx - 1].y && snake.pt[idx].x < snake.pt[idx - 1].x)//往右
        DrawTail(0, idx);
    else if (snake.pt[idx].y == snake.pt[idx - 1].y && snake.pt[idx].x > snake.pt[idx - 1].x)//往左
        DrawTail(1, idx);
    else if (snake.pt[idx].y > snake.pt[idx - 1].y && snake.pt[idx].x == snake.pt[idx - 1].x)//往上
        DrawTail(2, idx);
    else if (snake.pt[idx].y < snake.pt[idx - 1].y && snake.pt[idx].x == snake.pt[idx - 1].x)//往下
        DrawTail(3, idx);
}

void DrawTail(int nIndex, int idx)
{
    IMAGE img;
    loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG12 + nIndex), SNAKE_DRAW_SIZE, SNAKE_DRAW_SIZE);
    putimage(snake.pt[idx].x * SNAKE_DRAW_SIZE, snake.pt[idx].y * SNAKE_DRAW_SIZE, &img);
}

void DrawSnake()
{
    for (int i = 0; i < snake.nCount; i++)
    {
        if (0 == i)
            DecideHeadDirection();
        else if (i == snake.nCount - 1)
            DecideTailDirection();
        else
            DecideCornerDirection(i);
    }
}

int IsEatBigFood()
{
    if (1 == bigFood.isEat)
        return 0;

    for (int i = bigFood.fpt.x; i < bigFood.fpt.x + 3; i++)
    {
        for (int j = bigFood.fpt.y; j < bigFood.fpt.y + 3; j++)
        {
            if (snake.pt[0].x == i && snake.pt[0].y == j)
                return 1;
        }
    }
    return 0;
}

void LevelUp()
{
    if (pattern == EmPattern::emTimeLimitedPattern)
        return;

    WCHAR szLevelUp[32];
    if (nCurScore > arrScore[nCurLevel])
    {
        swprintf_s(szLevelUp, L"恭喜你,升到第%d級", nCurLevel + 1);
        ::MessageBox(0, szLevelUp, L"升級啦", 0);
        nCurLevel++;
        if (nCurSpeed > 0)
            nCurSpeed -= MINUS_SPEED;
    }
}

void EatFood()
{
    if (snake.pt[0].x == food.fpt.x && snake.pt[0].y == food.fpt.y)
    {
        nCurScore += FOOD_SCORE;
        snake.nCount++;
        food.isEat = 1;
        ProduceBigFood();
    }

    if (IsEatBigFood())
    {
        nCurScore += BIG_FOOD_SCORE;
        snake.nCount++;
        bigFood.isEat = 1;
    }

    LevelUp();
}

int IsFoodPosOk(int x, int y)
{
    for (int i = 0; i < snake.nCount; i++)
    {
        if (snake.pt[i].x == x && snake.pt[i].y == y)
            return 0;
    }

    if (0 == bigFood.isEat)
    {
        for (int i = bigFood.fpt.x; i < bigFood.fpt.x + 3; i++)
        {
            for (int j = bigFood.fpt.y; j < bigFood.fpt.y + 3; j++)
            {
                if (x == i && y == j)
                    return 0;
            }
        }
    }
    return 1;
}

int IsBigFoodPosOk(int x, int y)
{
    for (int i = x; i < x + 3; i++)
    {
        for (int j = y; j < y + 3; j++)
        {
            if (i < 0 || i > REGION_WIDTH / SNAKE_DRAW_SIZE - 1 || j < 0 || j > REGION_HEIGHT / SNAKE_DRAW_SIZE - 1)
                return 0;

            for (int k = 0; k < snake.nCount; k++)
            {
                if (snake.pt[k].x == i && snake.pt[k].y == j)
                    return 0;
            }
        }
    }
    return 1;
}

void ProduceFood()
{
    if (0 == food.isEat)
        return;

    while (1)
    {
        food.fpt.x = rand() % (REGION_WIDTH / SNAKE_DRAW_SIZE);
        food.fpt.y = rand() % (REGION_HEIGHT / SNAKE_DRAW_SIZE);
        if (IsFoodPos