C語言——簡單貪喫蛇設計思路

(轉載請註明出處,菜鳥之處還望拍磚)

 

思路

-----------------------------------------------------------------------

      兩個指針(概念上的指針,不是int *p那個),一個指頭一個指向尾巴。

      用類似隊列的方法,身體上每一塊都標名其更前(靠進頭部爲前)一塊的相對位置。比如, 身體上有一塊被標識爲“2”表示比他更靠前的一塊的位置在其上方,以此類推。

                                                                                                ——二維隊列(O(∩_∩)O 自創名詞。。)

 

     頭指針移動:

                 POINT head;

                 movehead(int 方向 )

                 {

                       //生成身體塊

                        map[head.x][head.y]=方向;

                       //頭指針遷移

                       head.x 更新(根據方向)

                       head.y 更新(根據方向)

                 }

     尾指針移動:

                 POINT rear;

                 moverear(int 方向 )

                {

                       //清楚身體塊

                        map[head.x][head.y]=0;

                       //尾指針遷移

                       rear.x 更新(根據方向)

                       rear.y 更新(根據方向)

                 }

      然後實現起來就很簡單了。

          移動:

              執行movehead(int 方向 )和moverear(int 方向 )。

          喫食物:

              只執行movehead(int 方向 )。

          GAME OVER:

              經過判斷頭指針更新不能(撞牆、撞身體)。

     代碼基本實現後,數組MAP實時實值打印效果圖:

 

MAP實時實值打印效果,功能基本實現

 

 

 

 

收穫

-----------------------------------------------------------------------

1.解決思考多年問題。。多線程纔是王道。。

 

2.從DOS向窗口進步。。圖形太2。。不過大體明白。。可備開始圖形學。。FOR PLAY

 

3.足夠多文件多函數,函數儘量簡單。。。思路更適合我這種低智商人羣。。。

 

4.蓄謀已久,構思(偶爾)1月,資料2天,程序3天,每天2-3小時。。

 

5.特此記錄。。。。

 

6.的確老了。。。。

 

7.很少算法。。。。

 

8.多線程貌似沒有KILL。。。太基礎。。。太低級。

 

9.句柄調用。。int tmp_hwnd=(int)hwnd;。。function((HWND)tmp_hwnd);。。這樣也可以。。

 

 

代碼(Buliding by C-free)

---------------------------------DOS------------------------------

#include <windows.h>
#include <time.h>
int map[32][22],direction;
POINT head,rear;
//map[i][j]= 0  1  2  3  4  5  6  7
//          空 牆 上 下 左 右 食 頭
int init()
{
    int i,j;
    for (i=0;i<32;i++)
        for (j=0;j<22;j++)
        {
            if ((0==i) || (31==i) || (0==j) || (21==j))
            {
                map[i][j]=1;
            }  else {
                map[i][j]=0;
            }
        }
    map[23][14]=6;
    map[15][23]=6;
    //初始化蛇
    map[1][1]=5;
    rear.x=1;
    rear.y=1;
    map[2][1]=5;
    map[3][1]=7;
    head.x=3;
    head.y=1;   
}

int feed()
{
    int i,j;
    srand( (unsigned)time( NULL) );
    do {
        i=rand()%30+1;
        j=rand()%20+1;
    }while (0!=map[i][j]);
    map[i][j]=6;
}

int over()
{
    system("cls");
    printf("/n/n/n/n/n/n/t/t/tGAME OVER/n");
    getch();
    exit(0);
}

int cango(int direction)
//0:dead.    1:can go.   2:can eat.  3:can't go.
{
    switch(direction)
    {
        case 1: //上
            if (3==map[head.x][head.y-1])
            {
                return 3;//判斷"往下走的過程按上"的情況
            }
            if ((0==map[head.x][head.y-1])||(6==map[head.x][head.y-1]))
            {
                if (6==map[head.x][head.y-1])
                {
                    return 2;
                }
                return 1;
            }else{
                return 0;
            }
        break;
        case 2: //下
            if (2==map[head.x][head.y+1])
            {
                return 3;
            }
            if ((0==map[head.x][head.y+1])||(6==map[head.x][head.y+1]))
            {
                if (6==map[head.x][head.y+1])
                {
                    return 2;
                }
                return 1;
            }else{
                return 0;
            }
        break;
        case 3: //左
            if (5==map[head.x-1][head.y])
            {
                return 3;
            }
             if ((0==map[head.x-1][head.y])||(6==map[head.x-1][head.y]))
            {
                if (6==map[head.x-1][head.y])
                {
                    return 2;
                }
                return 1;
            }else {
                return 0;
            }
        break;
        case 4: //右
            if (4==map[head.x+1][head.y])
            {
                return 3;
            }
            if ((0==map[head.x+1][head.y])||(6==map[head.x+1][head.y]))
            {
                if (6==map[head.x+1][head.y])
                {
                    return 2;
                }
                return 1;
            }else {
                return 0;
            }
        break;
    }
}

int movehead(int direction)
{
    switch(direction)
    {
        case 1: //上
            map[head.x][head.y]=2;
            head.y--;
            map[head.x][head.y]=7;
        break;
        case 2: //下
            map[head.x][head.y]=3;
            head.y++;
            map[head.x][head.y]=7;
        break;
        case 3: //左
            map[head.x][head.y]=4;
            head.x--;
            map[head.x][head.y]=7;
        break;
        case 4: //右
            map[head.x][head.y]=5;
            head.x++;
            map[head.x][head.y]=7;
        break;
    }
}

int moverear()
{
    switch(map[rear.x][rear.y])
    {
        case 2: //上
            map[rear.x][rear.y]=0;
            rear.y--;
        break;
        case 3: //下
            map[rear.x][rear.y]=0;
            rear.y++;
        break;
        case 4: //左
            map[rear.x][rear.y]=0;
            rear.x--;
        break;
        case 5: //右
            map[rear.x][rear.y]=0;
            rear.x++;
        break;
    }
}

int move(int direction)
//direction= 1 2 3 4
//          上下左右
{
    switch(cango(direction))
    {
        case 1:
            movehead(direction);
            moverear();
        break;
        case 2:
            movehead(direction);
            feed();
        break;
        case 0:
            over();
        break;
        default:       
        break;
    }
}

long WINAPI  Thread( LPVOID pParam )
{
       
        int i,j;
        while(1)
        {
            Sleep(100);
            move(direction);
            system("cls");
            printf("--------------/n");
            for (j=0;j<22;j++)
            {
                for (i=0;i<32;i++)
                {
                    if (map[i][j]==0)
                       printf("  ");
                       else
                        printf("%2d",map[i][j]);
                }
                printf("|/n");
            }
            printf("--------------");
        }
        return 1;     
}

int main()
{
    init();
    direction=0;
    char ch;
   
    unsigned long * p=NULL;
    CreateThread(0,0,(LPTHREAD_START_ROUTINE)Thread,NULL,0,p);
    while (1)
    {
        ch=getch();
        switch(ch)
        {
            case 'w':
                 direction=1;
            break;
            case 's':
                direction=2;
            break;
            case 'a':
                direction=3;
            break;
            case 'd':
                direction=4;
            break;
        }
       
    }
}

 

 

 

 

--------------------------------------windows-----------------------------

-----main.c----

#include <windows.h>
extern score,speed;

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "WindowsApp";
int direction=100;//控制方向的量
int    tmp_hwnd=0;//臨時存儲窗口句柄

int WINAPI
WinMain (HINSTANCE hThisInstance,
         HINSTANCE hPrevInstance,
         LPSTR lpszArgument,
         int nFunsterStil)

{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "pictcs",         /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           710,                 /* The programs width */
           580,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nFunsterStil);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }
   
    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


long WINAPI  Thread( LPVOID pParam )
{
        SYSTEMTIME nowtime;
        int tmp_time;
        int timedelay;
       
        while(0!=tmp_hwnd)//取句柄。。若臨時句柄被複制工作
        {
            switch(speed)
            {
                case 10:timedelay= 50;break;
                case 9:timedelay= 100;break;
                case 8:timedelay= 150;break;
                case 7:timedelay= 200;break;
                case 6:timedelay= 300;break;
                case 5:timedelay= 400;break;
                case 4:timedelay= 500;break;
                case 3:timedelay= 600;break;
                case 2:timedelay= 800;break;
                case 1:timedelay= 1000;break;
                default:timedelay=50 ;break;
            }
            Sleep(timedelay);
            tmp_time=nowtime.wSecond ;
            draw_text((HWND)tmp_hwnd,score,speed);
            move((HWND)tmp_hwnd,direction);
           
        }
        return 1;     
}



/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK
WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    RECT rt;
   
    switch (message)                  /* handle the messages */
    {
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            /* TODO: Add any drawing code here... */
                Rectangle (hdc,10,10,690,540);
                Rectangle (hdc,40,40,660,510);
                Rectangle (hdc,50,50,650,95);
                Rectangle (hdc,50,100,650,500);
            EndPaint(hwnd, &ps);
            drawmap(hwnd);
            if (0==tmp_hwnd)//若已有線程 則不再重新開
            {
                init(hwnd);
                tmp_hwnd=(int)hwnd;//存臨時句柄  以便線程尋找
                unsigned long * p=NULL;
                 CreateThread(0,0,(LPTHREAD_START_ROUTINE)Thread,NULL,0,p);
            }
        //    test(hwnd);           
            break;
        case WM_KEYDOWN:
            switch(wParam)
            {
                case VK_UP:   
                    direction=1;
                    //move(hwnd,1);
                break;
                case VK_DOWN:
                    direction=2;
                    //move(hwnd,2);
                break;
                case VK_LEFT:
                    direction=3;
                    //move(hwnd,3);
                break;
                case VK_RIGHT:
                    direction=4;
                    //move(hwnd,4);
                break;
                case VK_SPACE:
                    init(hwnd);
                break;
            }
        break;
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

------draw.c-------

#include<windows.h>


int draw_bodyUP(HWND hwnd,POINT place)
{
    HDC hdc;
    hdc=GetDC(hwnd);
    Rectangle (hdc,place.x+1,place.y+1,place.x+19,place.y+19);
    ReleaseDC(hwnd,hdc);
}
int draw_bodyDOWN(HWND hwnd,POINT place)
{
    HDC hdc;
    hdc=GetDC(hwnd);
    Rectangle (hdc,place.x+1,place.y+1,place.x+19,place.y+19);
    ReleaseDC(hwnd,hdc);
}
int draw_bodyLEFT(HWND hwnd,POINT place)
{
    HDC hdc;
    hdc=GetDC(hwnd);
    Rectangle (hdc,place.x+1,place.y+1,place.x+19,place.y+19);
    ReleaseDC(hwnd,hdc);
}
int draw_bodyRIGHT(HWND hwnd,POINT place)
{
    HDC hdc;
    hdc=GetDC(hwnd);
    Rectangle (hdc,place.x+1,place.y+1,place.x+19,place.y+19);
    ReleaseDC(hwnd,hdc);
}
int draw_head(HWND hwnd,POINT place)
{
    HDC hdc;
    hdc=GetDC(hwnd);
    Rectangle (hdc,place.x+1,place.y+1,place.x+19,place.y+19);
    ReleaseDC(hwnd,hdc);
}
int draw_food(HWND hwnd,POINT place)
{
    HDC hdc;
    hdc=GetDC(hwnd);
    Ellipse (hdc,place.x+1,place.y+1,place.x+19,place.y+19);
    ReleaseDC(hwnd,hdc);
}
int draw_space(HWND hwnd,POINT place)
{
    HDC hdc;
    RECT rtc;
    hdc=GetDC(hwnd);
            rtc.left=place.x+1;
            rtc.top=place.y+1;
            rtc.right=place.x+19;
            rtc.bottom=place.y+19;
            FillRect(hdc,&rtc,(HBRUSH)(0));
    ReleaseDC(hwnd,hdc);
}

int draw(HWND hwnd,POINT where,int func)
{
    POINT place;
    place.x=50+(where.x-1)*20;
    place.y=100+(where.y-1)*20;
    switch(func)
    {
        case 0://空
            draw_space(hwnd,place);
        break;
        case 7://頭 此處爲了和MAP數組對應
            draw_head(hwnd,place);
        break;
        case 2://上
            draw_bodyUP(hwnd,place);
        break;
        case 3://下
            draw_bodyDOWN(hwnd,place);
        break;
        case 4://左
            draw_bodyLEFT(hwnd,place);
        break;
        case 5://右
            draw_bodyRIGHT(hwnd,place);
        break;
        case 6://食
            draw_food(hwnd,place);
        break;
        default:
        break;
    }   
}

int draw_text(HWND hwnd,int score,int speed)
{
    HDC hdc;
    TCHAR out_text[100],*outer;
    RECT rt;
    rt.left=50;
    rt.top=70;
    rt.right=650;
    rt.bottom=95;
   
    hdc=GetDC(hwnd);
    wsprintf(out_text,TEXT("分數:%d    級別:%d   RESET:[空格] /0"),
        score,speed);
    outer=out_text;
    DrawText(hdc, outer, strlen(outer)-1, &rt, DT_CENTER);
    ReleaseDC(hwnd,hdc);
}

 

--------brain.c----

#include <windows.h>
int map[32][22],direction,speed=1,score=0,speed_tmp=0;
POINT head,rear;
//map[i][j]= 0  1  2  3  4  5  6  7
//          空 牆 上 下 左 右 食 頭

int drawmap(HWND hwnd)
{
    POINT here;
    for (here.x=1;here.x<=30;here.x++)
    {
        for (here.y=1;here.y<=20;here.y++)
        {
            draw(hwnd,here,map[here.x][here.y]);
        }
    }
}

int init(HWND hwnd)
{
    int i,j;
    for (i=0;i<32;i++)
        for (j=0;j<22;j++)
        {
            if ((0==i) || (31==i) || (0==j) || (21==j))
            {
                map[i][j]=1;
            }  else {
                map[i][j]=0;
            }
        }
    map[23][14]=6;
    map[15][23]=6;
    //初始化蛇
    map[1][1]=5;
    rear.x=1;
    rear.y=1;
    map[2][1]=5;
    map[3][1]=7;
    head.x=3;
    head.y=1;   
    drawmap(hwnd);
}

int feed(HWND hwnd)
{
    POINT foods;
    srand( (unsigned)time( NULL) );
    do {
        foods.x=rand()%30+1;
        foods.y=rand()%20+1;
    }while (0!=map[foods.x][foods.y]);
    map[foods.x][foods.y]=6;
    draw(hwnd,foods,6);
    score++;//計分
    speed_tmp++;
    if (speed_tmp>=20) {speed_tmp=0;speed++;}
}

int over(HWND hwnd)
{
    HDC hdc;
    hdc=GetDC(hwnd);
    RECT rt;
    GetClientRect(hwnd, &rt);
    rt.top=300;
   
    DrawText(hdc, TEXT("Game Over!...Over!...ver!...er!...r!...!..."), 43, &rt, DT_CENTER);
    ReleaseDC(hwnd,hdc);
}

int cango(int direction)
//0:dead.    1:can go.   2:can eat.  3:can't go.
{
    switch(direction)
    {
        case 1: //上
            if (3==map[head.x][head.y-1])
            {
                return 3;//判斷"往下走的過程按上"的情況
            }
            if ((0==map[head.x][head.y-1])||(6==map[head.x][head.y-1]))
            {
                if (6==map[head.x][head.y-1])
                {
                    return 2;
                }
                return 1;
            }else{
                return 0;
            }
        break;
        case 2: //下
            if (2==map[head.x][head.y+1])
            {
                return 3;
            }
            if ((0==map[head.x][head.y+1])||(6==map[head.x][head.y+1]))
            {
                if (6==map[head.x][head.y+1])
                {
                    return 2;
                }
                return 1;
            }else{
                return 0;
            }
        break;
        case 3: //左
            if (5==map[head.x-1][head.y])
            {
                return 3;
            }
             if ((0==map[head.x-1][head.y])||(6==map[head.x-1][head.y]))
            {
                if (6==map[head.x-1][head.y])
                {
                    return 2;
                }
                return 1;
            }else {
                return 0;
            }
        break;
        case 4: //右
            if (4==map[head.x+1][head.y])
            {
                return 3;
            }
            if ((0==map[head.x+1][head.y])||(6==map[head.x+1][head.y]))
            {
                if (6==map[head.x+1][head.y])
                {
                    return 2;
                }
                return 1;
            }else {
                return 0;
            }
        break;
    }
}

int movehead(HWND hwnd,int direction)
{
    switch(direction)
    {
        case 1: //上
            map[head.x][head.y]=2;
            draw(hwnd,head,2);
            head.y--;
            map[head.x][head.y]=7;
            draw(hwnd,head,7);
        break;
        case 2: //下
            map[head.x][head.y]=3;
            draw(hwnd,head,3);
            head.y++;
            map[head.x][head.y]=7;
            draw(hwnd,head,7);
        break;
        case 3: //左
            map[head.x][head.y]=4;
            draw(hwnd,head,4);
            head.x--;
            map[head.x][head.y]=7;
            draw(hwnd,head,7);
        break;
        case 4: //右
            map[head.x][head.y]=5;
            draw(hwnd,head,5);
            head.x++;
            map[head.x][head.y]=7;
            draw(hwnd,head,7);
        break;
    }
}

int moverear(HWND hwnd)
{
    switch(map[rear.x][rear.y])
    {
        case 2: //上
            map[rear.x][rear.y]=0;
            draw(hwnd,rear,0);
            rear.y--;
        break;
        case 3: //下
            map[rear.x][rear.y]=0;
            draw(hwnd,rear,0);
            rear.y++;
        break;
        case 4: //左
            map[rear.x][rear.y]=0;
            draw(hwnd,rear,0);
            rear.x--;
        break;
        case 5: //右
            map[rear.x][rear.y]=0;
            draw(hwnd,rear,0);
            rear.x++;
        break;
    }
}

int move(HWND hwnd,int direction)
//direction= 1 2 3 4
//          上下左右
{
   
    if (100==direction) return 0;//若還未開始 移動無效
    switch(cango(direction))
    {
        case 1:
            movehead(hwnd,direction);
            moverear(hwnd);
        break;
        case 2:
            movehead(hwnd,direction);
            feed(hwnd);
        break;
        case 0:
            over(hwnd);
        break;
        default:       
        break;
    }
}


/*int test(hwnd)
{
    init(hwnd);
    POINT here;
            for (here.x=1;here.x<=30;here.x++)
                for (here.y=1;here.y<=20;here.y++)
                {
                    draw(hwnd,here,map[here.x][here.y]);
                }
    Sleep(1000);
    feed(hwnd);
        Sleep(1000);
    feed(hwnd);
        Sleep(1000);
    feed(hwnd);
        Sleep(1000);
    feed(hwnd);
    Sleep(1000);
    move(hwnd,2);
    Sleep(1000);
    move(hwnd,4);
    Sleep(1000);
    move(hwnd,1);
    Sleep(1000);
    move(hwnd,4);
    Sleep(1000);
    move(hwnd,4);
    Sleep(1000);
    move(hwnd,4);
    Sleep(1000);
    move(hwnd,4);Sleep(1000);
    move(hwnd,4);
    Sleep(1000);
    move(hwnd,4);Sleep(1000);
    move(hwnd,4);Sleep(1000);
    move(hwnd,4);Sleep(1000);
    move(hwnd,4);
    Sleep(1000);
    move(hwnd,4);
    Sleep(1000);
    move(hwnd,4);
    Sleep(1000);
    move(hwnd,4);
    Sleep(1000);
    move(hwnd,4);
    Sleep(1000);
    move(hwnd,4);Sleep(1000);
    move(hwnd,4);
    Sleep(1000);
    move(hwnd,4);Sleep(1000);
    move(hwnd,4);Sleep(1000);
    move(hwnd,4);Sleep(1000);
    move(hwnd,4);Sleep(1000);
    move(hwnd,4);Sleep(1000);
    move(hwnd,4);Sleep(1000);
    move(hwnd,4);
    Sleep(1000);
    move(hwnd,1);
   
}*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章