鱼C论坛

 找回密码
 立即注册
查看: 2310|回复: 3

[技术交流] C-贪吃蛇

[复制链接]
发表于 2015-12-17 10:50:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
学了一个多月,花了几天时间,查了一些资料,撸了几百行代码。
用了线程和回调函数,有点四不像。
有个程序猿看了代码说像shi一样。请大家指点一下,什么问题。
另外,有时候不产生食物,不知道问题出在哪。
工具:VS2013
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <stdlib.h>
#include <conio.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>

///////////////////////////////////////////////////////////////////////
#define printBeginUIPos 40
#define printPoolUIPos 75
//////////////////////////////////////////////////////////////////////

typedef struct        SNAKE                        //定义蛇的结构
{
        POINT        snakeHeadPos;                //蛇头坐标
        int                Len;                                //蛇身长度
        char        direction;                        //当前行动方向
        int                score;                                //游戏得分
        struct SNAKE *next;                        //指向下一个节点的指针
}Snake;

typedef struct FOOD                                //定义食物的坐标
{
        int x;
        int y;
}food;                        

food *Food;

int gameStatus = 1;                                        //定义当前游戏状态
                                                                //1、正常游戏;2、退出游戏;3、暂停游戏;4、撞到墙壁;5、吃到自己

HWND g_hConsoleOutPut;                        //控制台句柄

Snake *head,*p;

HANDLE hThread;
DWORD ThreadID;

//HHOOK glhHook = NULL;
//HINSTANCE glhInstance;
/////////////////////////////------函数声明-------//////////////////////////////////
void initBeginUI();                                //初始化开始界面
void printGamePool();                        //打印游戏池
void gotoxy(short x, short y);        //鼠标移动到 x,y
void initGame();                                //初始化游戏
void createFood();                                //产生食物
int playGame();
void decideDirection(key);                //由按键字母得到方向
void moveSnake();
void endGame();
void CALLBACK TimeProc(HWND,UINT,UINT,DWORD);                //时间类的回调函数
//void CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
void threadMoveSnake();                        //线程--蛇移动

/////////////////////////////----Main----////////////////////////
int main()
{
        initBeginUI();
        initGame();
        playGame();

        system("pause > nul");
        system("cls");

        return 0;
}

///////////////////////////////////////////////////////////////////////
void initBeginUI()                                //初始化开始界面
{
        g_hConsoleOutPut = GetStdHandle(STD_OUTPUT_HANDLE);

        CONSOLE_CURSOR_INFO cursorInfo = { 1, false };
        SetConsoleCursorInfo(g_hConsoleOutPut,&cursorInfo);
        SetConsoleTitleA("Snake---By fpx");
        system("mode con cols=100 lines=30");

        SetConsoleTextAttribute(g_hConsoleOutPut, 0x0F);  //API设置控制台窗口字体颜色和背景色的函数
        gotoxy(printBeginUIPos, 5);
        printf("┏━━━━━━━┓");
        gotoxy(printBeginUIPos, 6);
        printf("┃ %2s%s%2s ┃", "", "-贪吃蛇-", "");
        gotoxy(printBeginUIPos, 7);
        printf("┗━━━━━━━┛");
        gotoxy(printBeginUIPos, 10);
        printf("    Made By fpx");
        gotoxy(printBeginUIPos-2, 12);
        printf("Press any key to continue...");

        while (1)
        {
                if (_kbhit())
                {
                        break;
                }
        }
        //fflush(stdin);        //清除标准输入设备(即键盘)的缓冲区。
        _getch();
        system("cls");

        printGamePool();
}

void printGamePool()                        //打印游戏池
{
        int i;
        for (i = 0; i < 70; i += 2)
        {
                gotoxy(i, 0);
                printf("■");
                gotoxy(i, 29);
                printf("■");
        }
        for (i = 0; i < 30; i++)
        {
                gotoxy(0, i);
                printf("■");
                gotoxy(70, i);
                printf("■");
        }

        SetConsoleTextAttribute(g_hConsoleOutPut, 0xB);
        gotoxy(printPoolUIPos, 8);
        printf("□向左移动:← A");
        gotoxy(printPoolUIPos, 10);
        printf("□向右移动:→ D");
        gotoxy(printPoolUIPos, 12);
        printf("□向下移动:↓ S");
        gotoxy(printPoolUIPos, 14);
        printf("□向下移动:↑ W");
        gotoxy(printPoolUIPos, 16);
        printf("□Score   : 0");
        gotoxy(printPoolUIPos, 18);
        printf("■By: fpx 15.11.18");

}

void gotoxy(short x, short y)
{
        COORD pos = { x, y };
        SetConsoleCursorPosition(g_hConsoleOutPut, pos);
}
///////////////////////////////////////////////////////////////////////
void initGame()                                        //初始化游戏
{
        int i;

        Snake *tail;
        tail = (Snake *)malloc(sizeof(Snake));        //定义蛇尾
        tail->next = NULL;
        tail->snakeHeadPos.x = 20; 
        tail->snakeHeadPos.y = 5;

        for (i = 0; i < 2; i++)
        {
                head = (Snake *)malloc(sizeof(Snake));
                head->next = tail;
                head->snakeHeadPos.x = 20 + 2 * (i+1); head->snakeHeadPos.y = 5;
                tail = head;
        }

        head = tail;
        head->direction = 'D';
        head->Len = 3;
        head->score = 0;

        while (tail != NULL)
        {
                gotoxy(tail->snakeHeadPos.x, tail->snakeHeadPos.y);
                printf("■");
                tail = tail->next;
        }
        createFood();
}

void createFood()                                        //产生食物
{
        food *food_1;
        srand((unsigned)time(NULL));
        food_1 = (food *)malloc(sizeof(food));

        while ((food_1->x % 2) != 0 || food_1->x < 2)                //保证食物的横坐标为2的偶数
        {
                food_1->x = rand() % 67 + 2;
        }
        food_1->y = rand() % 28 + 1;

        p = head;
        while (p->next != NULL)
        {
                if (food_1->x == p->snakeHeadPos.x && food_1->y == p->snakeHeadPos.y)
                {
                        createFood();
                        return 0;
                }
                p = p->next;
        }
        Food = food_1;
        gotoxy(food_1->x, food_1->y);
        printf("☆");
}
//////////////////////////////////////////////////////////////////////
int playGame()
{
        char direction,key;
        //clock_t clockNow, clockLast;

        //clockLast = clock();

        hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMoveSnake, NULL, 0, &ThreadID);
        
        while (1)
        {
                key = _getch();
                if (key == 27)
                {
                        gameStatus = 2;
                }

                if (gameStatus > 2)
                {
                        return 0;
                }

                decideDirection(key);
                Sleep(150);
        }

}

void decideDirection(key)                //由按键字母得到方向
{
        char returnValue;
        switch (key)
        {
        case 'W':
        case 'w':
        case 72:
                if (head->direction != 'S')
                {
                        head->direction = 'W';
                }
                break;
        case 'S':
        case 's':
        case 80:
                if (head->direction != 'W')
                {
                        head->direction = 'S';
                }
                break;
        case 'A':
        case 'a':
        case 75:
                if (head->direction != 'D')
                {
                        head->direction = 'A';
                }
                break;
        case 'D':
        case 'd':
        case 77:
                if (head->direction != 'A')
                {
                        head->direction = 'D';
                }
                break;
        default:
                head->direction = head->direction;
                break;
        }
}

void moveSnake()
{
        //1、判断是否撞墙
        //2、由方向确定坐标的变化
        //3、判断下一个是否为食物,若是,则加长;否则移动蛇身
        //4、判断是否吃到自己
        int x, y;

        if (head->snakeHeadPos.x < 2 || head->snakeHeadPos.x > 68 || head->snakeHeadPos.y < 1 || head->snakeHeadPos.y > 29)
        {
                gameStatus = 4;
                endGame();
        }

        x = head->snakeHeadPos.x;
        y = head->snakeHeadPos.y;

        Snake *nextsnake,*q;
        nextsnake = (Snake *)malloc(sizeof(Snake));
        q = (Snake *)malloc(sizeof(Snake));
        //ZeroMemory(&p,sizeof(p));                //清空结构体

        switch (head->direction)
        {
        case 'W':y--; break;
        case 'S':y++; break;
        case 'A':x -= 2; break;
        case 'D':x += 2; break;
        }

        nextsnake->snakeHeadPos.x = x;                        //对新节点赋值
        nextsnake->snakeHeadPos.y = y;
        nextsnake->Len = head->Len;
        nextsnake->direction = head->direction;
        nextsnake->score = head->score;
        nextsnake->next = head;

        if (nextsnake->snakeHeadPos.x == Food->x && nextsnake->snakeHeadPos.y == Food->y)
        {
                head = nextsnake;
                p = head;

                while (p != NULL)
                {
                        gotoxy(p->snakeHeadPos.x, p->snakeHeadPos.y);
                        printf("■");
                        p = p->next;
                }
                head->Len += 1;
                head->score += 10;
                gotoxy(printPoolUIPos, 16);
                printf("□Score   : %d",head->score);
                createFood();
        }
        else
        {
                head = nextsnake;
                p = head;

                while (p->next->next != NULL)
                {
                        gotoxy(p->snakeHeadPos.x, p->snakeHeadPos.y);
                        printf("■");
                        p = p->next;
                }
                gotoxy(p->next->snakeHeadPos.x, p->next->snakeHeadPos.y);
                printf("  ");
                p->next = NULL;
        }

        q = head->next;
        while (q)
        {
                if (head->snakeHeadPos.x == q->snakeHeadPos.x && head->snakeHeadPos.y == q->snakeHeadPos.y)
                {
                        gameStatus = 5;
                        endGame();
                }
                q = q->next;
        }
}

void CALLBACK TimeProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
{
        moveSnake();
}

//void CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
//{
//        switch (wParam)
//        {
//        case VK_UP:
//        case 'W':
//        case 'w':
//        case 72:
//                if (head->direction != 'S')
//                {
//                        head->direction = 'W';
//                }
//                break;
//        case VK_DOWN:
//        case 'S':
//        case 's':
//        case 80:
//                if (head->direction != 'W')
//                {
//                        head->direction = 'S';
//                }
//                break;
//        case VK_LEFT:
//        case 'A':
//        case 'a':
//        case 75:
//                if (head->direction != 'D')
//                {
//                        head->direction = 'A';
//                }
//                break;
//        case VK_RIGHT:
//        case 'D':
//        case 'd':
//        case 77:
//                if (head->direction != 'A')
//                {
//                        head->direction = 'D';
//                }
//                break;
//        //default:
//        //        head->direction = head->direction;
//                //break;
//        }
//}

void threadMoveSnake()                        //线程中移动蛇身
{
        SetTimer(NULL, 1, 300, TimeProc);
        MSG msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
                if (msg.message == WM_TIMER)
                {
                        DispatchMessage(&msg);
                }
                //if (msg.message == WM_KEYDOWN)
                //{
                //        TranslateMessage(&msg);
                //        DispatchMessage(&msg);
                //}
        }
}
////////////////////////////////////////////////////////////////////////////
void endGame()
{
        /*TerminateThread(hThread, 0);*/
        
        KillTimer(g_hConsoleOutPut,1);

        system("cls");
        gotoxy(40, 12);

        switch (gameStatus)
        {
        case 2:
                printf("您的已经结束了游戏。"); break;
        case 4:
                printf("您撞到墙了。游戏结束."); break;
        case 5:
                printf("您咬到自己了。游戏结束."); break;
        }
        gotoxy(40, 15);
        printf("您的得分是 %d\n", head->score);

        //ExitThread(0);

        system("pause > nul");
        /*system("cls");*/
        exit(0);
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-12-17 12:08:43 | 显示全部楼层
:call:看一看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-4-15 21:02:46 | 显示全部楼层
厉害
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-4-16 14:57:31 | 显示全部楼层
支持楼主
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-27 00:18

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表