c语言实现贪吃蛇

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <stdbool.h>
#include <string.h>

#define U 1
#define D 2
#define L 3
#define R 4       //蛇的状态,U:上 ;D:下;L:左 R:右

#define width 100
#define height 30

typedef struct BLOCK
{
    int x;
    int y;
    struct BLOCK *next;
}Block;

Block *snakeHead; //蛇头指针
Block *p;//遍历蛇身的指针
Block *food; //食物指针 
int speed = 200;

void drawBlock(int x,int y);
void eraseBlock(int x,int y);
void createWindow();
void createMap();
void createSnake();
void createFood();
void moveSnake();
void endGame();

int main()
{
    createWindow();
    createMap();
    createSnake();
    createFood();
    moveSnake();
    return 0;
}

void drawBlock(int x,int y)  //画方块 
{
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD coord;
    coord.X = x;
    coord.Y = y;
    SetConsoleCursorPosition(handle, coord); //设置控制台光标的位置

    //CONSOLE_CURSOR_INFO curInfo; //定义光标信息的结构体变量
    //curInfo.dwSize = 1;  //如果没赋值的话,隐藏光标无效
    //curInfo.bVisible = FALSE; //将光标设置为不可见
    //SetConsoleCursorInfo(handle, &curInfo); //设置光标信息

    printf("□");//一个方块占两个位置  //● ■ ▲ ★ ▁  ▁ 
}

void eraseBlock(int x,int y)  //擦除方块 
{
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD coord;
    coord.X = x;
    coord.Y = y;
    SetConsoleCursorPosition(handle, coord); //设置控制台光标的位置
    printf(" ");//一个方块占两个位置
}

void createWindow()
{
    char s[30];
    sprintf(s,"mode con cols=%d lines=%d",width,height);
    //system("mode con cols=100 lines=30"); //创建窗口
    system(s);
    system("title 贪食蛇游戏"); //设置窗口标题

    system("color b");
}


void createMap()
{
    int i;
    for(i=0;i<width-2;i+=2) 
    {
        drawBlock(i,0);  //画上墙 
        drawBlock(i,height-1); //画下墙 
    }

    for(i=0;i<height-1;i++)
    {
        drawBlock(0,i);//画左墙 
        drawBlock(width-2,i);//画右墙 
    }
}

void createSnake()
{
    snakeHead = (Block *)malloc(sizeof(Block));
    snakeHead->x = 44;
    snakeHead->y = 15;
    snakeHead->next = NULL;

    drawBlock(snakeHead->x,snakeHead->y);

    p = snakeHead;
    int i;
    for(i=1;i<5;i++)
    {
        Block *body = (Block *)malloc(sizeof(Block));
        body->x = p->x + 2;
        body->y = p->y;
        body->next = NULL;

        drawBlock(body->x,body->y);

        p->next = body;
        p = body;
    }
}

void createFood()
{
    int x;
    int y;
    while(1){
        //srand((unsigned)time(NULL));//为了防止每次产生的随机数相同,种子设置为time
        srand(time(0));
        x = (rand() % (width/2-2)) * 2 + 2;//设置x为偶数
        y = rand() % (height-2) + 1;

        //食物不能与蛇身重合
        bool inSnake = false;
        p=snakeHead;
        while(p->next != NULL) //遍历循环
        {
           if(p->x == x && p->y == y)
           {
               inSnake = true;
               break;
           }
           p = p->next;
        }

        if(inSnake == false){
            break;
        }
    }

    food = (Block *)malloc(sizeof(Block));
    food->x = x;
    food->y = y;
    food->next = NULL;
    drawBlock(x,y);
}


void moveSnake()
{
    int state = L;
    int x = snakeHead->x;
    int y = snakeHead->y;

    while(1){
        Sleep(speed);

        if(state == U){
            y =y-1;
        }else if(state == D){
            y =y+1;
        }else if(state == R){
            x = x+2;
        }else if(state == L){
            x = x-2;
        }

        if(x==food->x && y==food->y){ //遇到食物
            food->next = snakeHead;
            snakeHead = food; //吃掉食物

            createFood();//再建一个食物

        }else{   //没有遇到食物  创建新的蛇头  接入蛇身 抹除蛇尾 实现移动
            Block *newHead = (Block *)malloc(sizeof(Block));
            newHead->x = x;
            newHead->y = y;
            newHead->next = snakeHead;
            drawBlock(newHead->x,newHead->y);

            p = snakeHead;
            while(p->next->next != NULL){  //指针指向倒数第二节
                p=p->next;
            }
            eraseBlock(p->next->x,p->next->y); //抹除蛇尾
            free(p->next);
            p->next = NULL;

            snakeHead=newHead;
        }

        // >>>>>>>>>>判定游戏结束
        bool gameOver = false;

        //撞墙
        if(snakeHead->x == 0 || snakeHead->x == width-2 ||snakeHead->y == 0||snakeHead->y ==height-1){
            gameOver = true;
        }

        //碰到自己
        p=snakeHead->next;
        while(p->next != NULL){
            if(p->x == snakeHead->x && p->y == snakeHead->y){
                gameOver = true;
                break;
            }
            p=p->next;
        }

        if(gameOver){
            endGame();
            break;
        }
        //<<<<<<<<<<<判定游戏结束


        //>>>>>>>>>>>响应键盘控制
        if(GetAsyncKeyState(VK_UP) && state != D){
            state = U;
        }else if(GetAsyncKeyState(VK_DOWN) && state != U){
            state = D;
        }else if(GetAsyncKeyState(VK_RIGHT) && state != L){
            state = R;
        }else if(GetAsyncKeyState(VK_LEFT) && state != R){
            state = L;
        }
        //<<<<<<<<<<<响应键盘控制
    }
}


void endGame()
{
    system("cls"); //清屏
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD coord;
    coord.X = 30;
    coord.Y = 10;
    SetConsoleCursorPosition(handle, coord); //设置控制台光标的位置
    printf("Game Over!\n");
    //system("pause");
}
 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
用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 } ...
好的,以下是一个简单的贪吃蛇C语言源代码,满足您的要求: ```c #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> #define MAXSIZE 100 int score; // 分数 int speed; // 速度 // 蛇的结构体 struct Snake { int x; int y; }; // 食物的结构体 struct Food { int x; int y; }; int main() { // 初始化蛇和食物 struct Snake snake[MAXSIZE]; struct Food food; snake[0].x = 10; snake[0].y = 10; food.x = 20; food.y = 20; // 初始化分数和速度 score = 0; speed = 100; // 游戏循环 while (1) { // 显示分数和速度 system("cls"); printf("Score: %d\n", score); printf("Speed: %d\n", speed); // 显示地图 for (int i = 0; i < 25; i++) { for (int j = 0; j < 25; j++) { if (i == 0 || i == 24 || j == 0 || j == 24) { printf("#"); } else if (i == snake[0].y && j == snake[0].x) { printf("O"); } else if (i == food.y && j == food.x) { printf("X"); } else { printf(" "); } } printf("\n"); } // 移动蛇 int direction = getch(); if (direction == 72) { snake[0].y--; } else if (direction == 80) { snake[0].y++; } else if (direction == 75) { snake[0].x--; } else if (direction == 77) { snake[0].x++; } // 判断是否吃到食物 if (snake[0].x == food.x && snake[0].y == food.y) { score++; // 重新生成食物 food.x = rand() % 22 + 1; food.y = rand() % 22 + 1; } // 判断游戏是否结束 if (snake[0].x == 0 || snake[0].x == 24 || snake[0].y == 0 || snake[0].y == 24) { printf("Game Over\n"); break; } // 延迟 Sleep(speed); } return 0; } ``` 在这个代码中,我们使用了 `struct` 来定义了蛇和食物的结构体,并且使用了 `score` 和 `speed` 分别记录分数和速度。游戏循环中,我们先显示了分数和速度,然后显示了地图,接着根据用户输入移动蛇,判断是否吃到食物,判断游戏是否结束,最后通过 `Sleep` 函数来延迟一定时间,控制蛇的速度。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值