贪吃蛇游戏的C语言实现

贪吃蛇游戏的C语言实现

刚学习完C语言基础知识,希望通过制作简单的游戏来提高自己的能力

//2020年12月2日23:19:54  begin

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#include<iostream>
#include<conio.h>

using namespace std;

#define SNAKESIZE 100               //蛇的最大长度
#define MAPHIGHT 24
#define MAPWIDTH 78
#define GAMEINFX 82
#define GAMEINFY 10


void movetoxy(int x,int y)          //光标移动函数
{
    COORD p;
    p.X = x;
    p.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),p);
}

struct          //食物的坐标
{
    int x;
    int y;
}food;

struct
{
    int speed;              //蛇的速度
    int len;
                   //蛇 长度
    int x[SNAKESIZE];       //蛇身体的x坐标
    int y[SNAKESIZE];       //        y坐标
}snake;

int key = 77;               //向"→"移动

int changeFlag = 0;         //判断蛇是否吃到食物
int endFlag = 0;            //结束标识变量
int score = 0;              //分数变量
int speed = 10;

void huanying(void);
void mapDraw(void);
void foodCreat(void);
void keyCtr(void);           //返回移动方向的int值
void snakeMove(int dir);     //蛇移动的方向
void conCtr(void);           //控制得分及失败条件
void gameInf(void);          //游戏信息,包括得分等

int main()
{
    huanying();
    if(endFlag)
        return 0;
    cout << endl << "\t按'↑'↓'←'→'以控制蛇移动的方向" << endl << endl << "\t按任意键以继续!";
    getchar();
    getchar();
    system("cls");
    mapDraw();
    foodCreat();
    while(1)
    {
        if(endFlag)
            break;
        keyCtr();
        snakeMove(key);
        conCtr();
        gameInf();
        Sleep(snake.speed);
        movetoxy(0,MAPHIGHT+1);
    }
    Sleep(5000);
    system("exit");

    return 0;
}

void huanying(void)
{
    int a;
    cout << endl << "\t\t贪吃蛇 V1.0" << endl;
    cout << "\t1.开始游戏" << endl;
    cout << "\t2.退出游戏" << endl << endl << "\t";
    cin >> a;
    if(a==1)
        endFlag = 0;
    else if(a==2)
        endFlag = 1;
    else
    {
        cout << endl << "\t请输入正确信息";
        endFlag = 1;
    }

}

void mapDraw(void)              //2020年12月3日00:09:25 完成
{
    //蛇属性初始化
    snake.len = 3;
    snake.speed = 300;
    snake.x[0] = MAPWIDTH/2+1;          //蛇头初始位置
    snake.y[0] = MAPHIGHT/2;

    int i = 0,j;
    for(i = 2;i<MAPWIDTH;i+=2)      //打印内部
    {
        for(j = 1;j<MAPHIGHT;j++)
        {
            movetoxy(i,j);
            cout << " ";
        }
    }
    for(i = 0;i<MAPWIDTH;i+=2)       //打印上下边界
    {
        movetoxy(i,0);
        std::cout << "□";
        movetoxy(i,MAPHIGHT);
        std::cout << "□";
    }
    for(i = 0;i<=MAPHIGHT;i++)          //打印左右边界
    {
        movetoxy(0,i);
        cout << "□";
        movetoxy(MAPWIDTH,i);
        cout << "□";
    }
                                        //打印游戏信息边框
    for(i = 0;i<28;i++)
    {
        movetoxy(GAMEINFX+i,0);
        cout << "+";
        movetoxy(GAMEINFX+i,GAMEINFY);
        cout << "+";
    }
    for(i = 0;i<GAMEINFY;i++)
    {
        movetoxy(GAMEINFX,i);
        cout << "+";
        movetoxy(GAMEINFX+27,i);
        cout << "+";
    }
    //打印蛇的身体
    i = 0;
    movetoxy(snake.x[0],snake.y[0]);
    cout << "●";       //■
    for(i = 1;i<snake.len;i++)
    {
        snake.x[i] = snake.x[i-1] - 2;
        snake.y[i] = snake.y[i-1];
        movetoxy(snake.x[i],snake.y[i]);
        cout << "○";
    }

}

void foodCreat(void)        //蛇的食物创造  2020年12月3日00:17:12
{
    int i = 0;
    srand(time(NULL));
    while(1)
    {
        food.x = rand()%(MAPWIDTH-1);
        food.y = rand()%(MAPHIGHT-1);
        for(i = 0;i<snake.len;i++)
        {
            if(food.x!=snake.x[i]&&food.y!=snake.y[i])
            {
                break;
            }
        }
        if(food.x%2==0&&food.x!=0&&food.x!=MAPWIDTH&&food.y!=0&&food.y!=MAPHIGHT)
            break;
    }
    movetoxy(food.x,food.y);
    cout << "■";
}

void keyCtr(void)
{
    //*“↑”:72
	//*“↓”:80
	//*“←”:75
	//*“→”:77
    int pre_key = key;       //创建个pre_key来存储之前的方向
    if(_kbhit()!=0)
    {
        fflush(stdin);

        key = _getch();
        key = _getch();
    }
    //若方向与移动方向相反,则按键无效
    if(pre_key==77&&key==75)
        key = 77;
    if(pre_key==75&&key==77)
        key = 75;
    if(pre_key==80&&key==72)
        key = 80;
    if(pre_key==72&&key==80)
        key = 72;


}

void snakeMove(int dir)
{
    int i = 0;
    if(changeFlag==0)
    {
        movetoxy(snake.x[snake.len-1],snake.y[snake.len-1]);
        cout << "  ";
    }
    if(changeFlag==1)
    {
        snake.len++;
    }
    for(i = snake.len - 1;i>0;i--)
    {
        snake.x[i] = snake.x[i-1];
        snake.y[i] = snake.y[i-1];
        movetoxy(snake.x[i],snake.y[i]);
        cout << "○";
    }
    switch(dir)
    {
        case 77: snake.x[0] += 2;break;
        case 75: snake.x[0] -= 2;break;
        case 72: snake.y[0]--;break;
        case 80: snake.y[0]++;break;
        default: break;
    }

    if(snake.x[0]==food.x&&snake.y[0]==food.y)
        {
            changeFlag = 1;
            score += 10;
            if(score%100==0)
                {
                    speed += 5;
                    snake.speed -= 50;
                }
            foodCreat();
        }
    else
        changeFlag = 0;

    movetoxy(snake.x[0],snake.y[0]);
    cout << "●";

    movetoxy(0,MAPHIGHT);
}

void conCtr(void)
{
    int i = 0;
    //条件1:蛇不能撞到墙上,否则结束游戏
    if(snake.y[0]==0||snake.y[0]==MAPHIGHT||snake.x[0]==0||snake.x[0]==MAPWIDTH)
        {
            movetoxy(snake.x[0],snake.y[0]);
            cout << "□";
            endFlag = 1;
            return;
        }
    //条件2:蛇不能撞到自己
    for(i = 1;i<snake.len-1;i++)
    {
        if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0])
        {
            endFlag = 1;
            break;
        }
    }



}

void gameInf(void)
{
    movetoxy(GAMEINFX+5,3);
    cout << "长度:" << snake.len;
    movetoxy(GAMEINFX+15,3);
    cout << "速度:" << speed;
    movetoxy(GAMEINFX+10,5);
    cout << "得分:" << score;
    if(endFlag)
    {
        movetoxy(GAMEINFX+8,7);
        cout << "  游戏结束     ";
    }
    else
    {
        movetoxy(GAMEINFX+8,7);
        cout << "游戏进行中...";
        movetoxy(0,MAPHIGHT+1);
    }
}

简单的游戏,实现原理较简单,不过本人能力不足,按键输入及x、y坐标处理方面参考另外一篇文章“C语言贪吃蛇完整代码

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
用windows api 做的贪吃蛇 #include #include"resource.h" #include"Node.h" #include #include TCHAR szAppname[] = TEXT("Snack_eat"); #define SIDE (x_Client/80) #define x_Client 800 #define y_Client 800 #define X_MAX 800-20-SIDE //点x的范围 #define Y_MAX 800-60-SIDE //点y的范围 #define TIME_ID 1 #define SECOND 100 #define NUM_POINT 10 //点的总个数 #define ADD_SCORE 10 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd; //窗口句柄 MSG msg; //消息 WNDCLASS wndclass; //窗口类 HACCEL hAccel;//加速键句柄 wndclass.style = CS_HREDRAW | CS_VREDRAW; //窗口的水平和垂直尺寸被改变时,窗口被重绘 wndclass.lpfnWndProc = WndProc; //窗口过程为WndProc函数 wndclass.cbClsExtra = 0; //预留额外空间 wndclass.cbWndExtra = 0; //预留额外空间 wndclass.hInstance = hInstance; //应用程序的实例句柄,WinMain的第一个参数 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //设置图标 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); //载入预定义的鼠标指针 wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //设置画刷 wndclass.lpszMenuName = szAppname; //设置菜单 wndclass.lpszClassName = szAppname; //设置窗口类的名字 if (!RegisterClass(&wndclass))//注册窗口类 { MessageBox(NULL, TEXT("这个程序需要windows NT!"), szAppname, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppname, TEXT("Snack_eat"),//CreateWindow函数调用时,WndProc将受到WM_CREATE WS_OVERLAPPEDWINDOW&~WS_THICKFRAME& ~WS_MAXIMIZEBOX,//普通的层叠窗口&禁止改变大小&禁止最大化 CW_USEDEFAULT, //初始x坐标(默认) CW_USEDEFAULT, //初始y坐标 x_Client, //初始x方向尺寸 770 y_Client, //初始y方向尺寸 750 NULL, //父窗口句柄 NULL, //窗口菜单句柄 hInstance, //程序实例句柄 WinMain函数中第二个参数 NULL); //创建参数 ShowWindow(hwnd, iCmdShow);//显示窗口,iCmdShow是WinMain的第四个参数,决定窗口在屏幕中的初始化显示形式,例:SW_SHOWNORMAL表示正常显示 UpdateWindow(hwnd);//使窗口客户区重绘,通过向WndProc发送一条WM_PAINT消息而完成的 hAccel = LoadAccelerators(hInstance, szAppname);//加载加速键 while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(hwnd, hAccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }/* while (GetMessage(&msg, NULL, 0, 0))//GetMessage函数从消息队列中得到消息,填充msg。如果msg.message等于WM_QUIT,返回0,否则返回非0 { TranslateMessage(&msg);//将msg返回给windows已进行某些键盘消息的转换 DispatchMessage(&msg);//将msg再次返回给windows }*/ return msg.wParam;//msg.wParam是PostQuitMessage函数的参数值,通常是0 } ...

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值