当前位置:首页 » 《随便一记》 » 正文

C语言实战项目-贪吃蛇小游戏

1 人参与  2024年02月24日 10:56  分类 : 《随便一记》  评论

点击全文阅读


一、贪吃蛇游戏实现思路:


1.定义蛇对象、食物对象
2.初始化蛇、初始化食物
3.控制流程:

(1)蛇头和墙壁的碰撞
(2)蛇头和蛇身体碰撞
(3)蛇头和食物碰撞
(4)移动速度增大

4.游戏效果:
(1)蛇身增长
(2)食物消失 -- 新食物产生
(3)分数累加
(4)移动速度增大
(5)蛇的移动
(6)显示分数

 

二、实现步骤:


1.引入头文件:
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <math.h>#include <time.h>#include <conio.h>#include <windows.h>
2.宏定义:
#define WIDE 60   //宽度#define HIGH 20   //高度
3.定义对象:
蛇身对象:struct BOOY {        int X;        int Y;    };蛇对象:struct SNAKE {        struct BODY body[20*60]; //蛇身 body[0] -- 蛇头        int size;   //蛇的大小    } snake;食物对象:    struct FOOD {            int X;            int Y;    } food;
4.初始化:
初始化分数:    int score = 0;初始化蛇:    封装一个函数 完成蛇的初始化:void initSnake(void){    snake.size = 2;    初始化好了蛇头    snake.body[0].X = WIDE/2;    snake.body[0].Y = HIGH/2;    初始化一节蛇身    snake.body[1].X = WIDE/2 - 1;    snake.body[1].Y = HIGH/2;    return;}初始化食物:void initFood(void){   food.X = rand() % WIDE; //0-59   food.Y = rand() % HIGH; //0-59   return;}

5.控制定位:

修改控制台光标位置:COORD coord;  //CORD --> 结构体, 有两个成员变量:x, y 坐标coord.X = snake.body[0].X;coord.Y = snake.body[0].Y;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);会将光标位置,定位到 初始化好的蛇头位置(WIDE/2, HIGH/2), 屏幕中间
 6.画出形状:
画出蛇和食物:封装函数 initUI(void){//光标移动位置COORD coord = {0};//画蛇for (size_t i = 0; i < snake.size; ++i){coord.X = snake.body[0].X;coord.Y = snake.body[0].Y;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);    if (i == 0)        putchar('@');    else        putchar('*');    }    //画食物    coord.X = food.X;    coord.Y = food.Y;    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);    putchar('#');}
画墙:void initWall(void){    for (size_t i = 0; i <= HIGH; i++)  //多行    {        for (size_t j = 0; j <= WIDE; j++)  //一行中的多列        {            if (j == WIDE)            {                printf("|");            }            else if (i = HIGH)            {                printf("_");            }            else            {                printf(" ");            }        }        printf("\n");    }}
7.按键控制: 
蛇的移动控制:    W: (0, -1)  -->影响蛇头    S: (0, +1)    A: (-1, 0)    D: (+1, 0)    不回显:        getch():接受用户输入。        char key = getch();        编译时出错,尝试使用 _getch();    不堵塞:        kbhit(); 不阻塞判断用户输入。        有用户输入返回“真”,否则返回“假”值        编译时出错,尝试使用 _kbhit();
 8.游戏体验:
开始游戏:    void playGame(void)    {        char key = 'd'; //默认蛇向右移动        蛇头和墙壁的碰撞:        while(判断是否撞墙)         {            //重画蛇身 initUI               //接受用户键盘输入                在全局 添加:kx, ky --> 根据 A S D W 按键得不同坐标, 影响蛇头            //蛇头和身体的碰撞            //蛇头和食物的碰撞            //蛇身体移动:前一节给后一节赋值,舌头收 kx ky 的影响            system("cls"); 清屏 -- 去除蛇尾        }    }    蛇头和墙壁的碰撞:        snake.body[0].X > 0 && snake.body[0].X < WIDE      &&        snake.body[0].Y > 0 && snake.body[0].Y < HIGH    蛇头和身体碰撞:    蛇头的坐标 和 任意一节身体和坐标 完全一致        for(i = 1; i < snake.size; i++)        {            if(snake.body[0].X == snake.body[i].X && snake.body[0].Y == snake.body[i].Y)            {                    //终止游戏                    return;            }        }    蛇头和食物的碰撞:        if(snake.body[0].X == food.X && snake.body[0].Y == food.Y)        {            蛇身增长:snake.size++            食物消失:(产生一个新食物)initFood()            加分:score += 10;            加速:         }    蛇移动:        前一节身体给后一节身体赋值。蛇头按照 A S W D 换算的坐标值 进行交换            for (size_t i = snake.size - 1; i > 0; i--)            {                snake.body[i].X = snake.body[i - 1].X;                snake.body[i].Y = snake.body[i - 1].Y;            }            snake.body[0].X += kx;   //蛇头坐标根据用户按键,修改            snake.body[0].Y += ky;
9.游戏优化 :
去除蛇尾:    蛇移动之前保存蛇尾坐标:    定义全局变量:lastX, lastY;    lastX = snake.body[nake.size - 1].X;    lastX = snake.body[nake.size - 1].X;    在int中,将蛇尾 替换为 ' '    coord.X = lastX;    coord.Y = lastY;    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);    putchar(' ');
去除光标:    typedef struct _CONSOLE_CURSOR_INFO {    DWORD dwSize;   //大小    BOOL bVisible;  //是否可见    } CONSOLE_CURSOR_INFO;    定义结构体变量:    CONSOLE_CURSOR_INFO cci;    cci.dwSize = sizeof(cci);    cci.bVisible = FALSE; //TRUE;设置光标不可见生效:    SetConsoleCursorInfo(SetStdHandle(STD_OUTPUT_HANDLE), &cci);显示分数    playGame调用结束时, 打印 全局 score 值加速:    全局定义变量: sleepSecond = 400;                Sleep(sleepSecond);                sleepSecond -= 20;    
10.实现效果:

 

三、项目源码:


1.主程序文件" main.c "中的代码:
#define _CRT_SECURE_NO_WARNINGS#include "snake.h"  //引入自定义头文件int main(void) {//    强制控制输出//-----------------------------------------------------------------//    setbuf(stdout, NULL);   //直接输出,解除缓存//-----------------------------------------------------------------//    游戏地图范围  测试代码//----------------------------------------------------------------//    for (size_t i = 0; i < 20; i++) {//        for (size_t j = 0; j < 60; j++) {//            printf(" ");//        }//        printf("\n");//    }//----------------------------------------------------------------    //去除光标    CONSOLE_CURSOR_INFO cci;    cci.dwSize = sizeof(cci);    cci.bVisible = FALSE; //TRUE;    SetConsoleCursorInfo(SetStdHandle(STD_OUTPUT_HANDLE), &cci);    srand(time(NULL));  //播种随机数种子    initSnake();  //初始化蛇    initFood();   //初始化食物    initWall();   //画墙    initUI();     //画蛇和食物    playGame();   //启动游戏    showScore();  //打印分数//    测试代码//----------------------------------------------------------------//    printf("头:x=%d, y=%d\n",snake.body[0].X, snake.body[0]);//    printf("身:x=%d, y=%d\n",snake.body[1].X, snake.body[1]);//    printf("food:x=%d, y=%d\n", food.X, food.Y);//----------------------------------------------------------------    system("pause");    return EXIT_SUCCESS;}////void Kithit() {////}void showScore(){    //将光标默认位置移动至  不干扰游戏的任意位置    COORD coord;    coord.X = 0;    coord.Y = HIGH + 2;    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);    printf("Game Over!!!");    printf("成绩为:%d\n\n\n", score);}void initWall(void){    for (size_t i = 0; i <= HIGH; i++)  //多行    {        for (size_t j = 0; j <= WIDE; j++)  //一行中的多列        {            if (j == WIDE)            {                printf("|");            }            else if (i = HIGH)            {                printf("_");            }            else            {                printf(" ");            }        }        printf("\n");    }}void playGame(void){    //定义key案件    char key = 'd';    //判断蛇撞墙    while(snake.body[0].X >= 0 && snake.body[0].X < WIDE          && snake.body[0].Y >= 0 && snake.body[0].X < HIGH)    {        //更新蛇        initUI();        //接受用户键盘输入 A左  D右  W上  S下        if(_kbhit()) {      //为真时,说明用户按下按键            key = _getch();        }        switch (key)        {            case 'w': kx = 0; ky = -1; break;            case 's': kx = 0; ky = +1; break;            case 'd': kx = +1; ky = 0; break;            case 'a': kx = -1; ky = 0; break;            default:                break;        }//        测试上下左右键//------------------------------------------------------------------//        printf("---- key = %c\n", key);//------------------------------------------------------------------        //蛇头撞身体:蛇头 == 任意一节身体        for (size_t i = 0; i < snake.size; i++)        {            if (snake.body[0].X == snake.body[i].X                && snake.body[0].Y == snake.body[i].Y)            {                return; //游戏结束            }        }        //蛇头撞食物        if (snake.body[0].X == food.X && snake.body[0].Y == food.Y)        {            initFood(); //食物消失            snake.size++; //身体增长            score += 10; //加分            sleepSecond; //加速        }        //存储蛇尾坐标        lastX = snake.body[snake.size - 1].X;        lastY = snake.body[snake.size - 1].Y;        //蛇移动,前一节身体给后一节身体赋值        for (size_t i = snake.size - 1; i > 0; i--)        {            snake.body[i].X = snake.body[i - 1].X;            snake.body[i].Y = snake.body[i - 1].Y;        }        snake.body[0].X += kx; //蛇头坐标根据用户按键,修改        snake.body[0].Y += ky;        Sleep(sleepSecond);        //清屏//        system("cls");    }    return;}//定义初始化蛇函数void initSnake(void){    snake.size = 2;    //蛇头初始化    snake.body[0].X = WIDE / 2;    snake.body[0].Y = HIGH / 2;    //蛇一节身体初始化    snake.body[1].X = WIDE / 2 - 1;    snake.body[1].Y = HIGH / 2;    return;}//坐标 COOED结构体定义//------------------------------------------------------------------------------//typedef  struct _COORD{//    SHORT X; //X坐标//    SHORT Y; //Y坐标//} COORD;//------------------------------------------------------------------------------//初始化界面控件void initUI(void){    //光标移动位置    COORD coord = {0};    //画蛇    for (size_t i = 0; i < snake.size; ++i)    {        coord.X = snake.body[0].X;        coord.Y = snake.body[0].Y;        //printf("X=%d,Y=%d\n", coord.X, coord.Y);        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);        if (i == 0)            putchar('@');        else            putchar('*');    }    //去除蛇尾    coord.Y = lastX;    coord.Y = lastY;    SetConsoleCursorPosition( GetStdHandle(STD_OUTPUT_HANDLE), coord);    //画食物    coord.X = food.X;    coord.Y = food.Y;    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);    putchar('#');//    画食物   测试代码//--------------------------------------------------------------------------//    coord.X = 0;//    coord.Y = 0;//    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//--------------------------------------------------------------------------}//初始化食物函数void initFood(void){    food.X = rand() % WIDE; //0-59    food.Y = rand() % HIGH; //0-59    return;}
2.头文件"snake.h"中的代码:
#ifndef __SNAKE_H__#define __SNAKE_H__#define WIDE 60   //宽度#define HIGH 20   //高度#include <stdio.h>#include <string.h>#include <stdlib.h>#include <math.h>#include <time.h>#include <conio.h>#include <windows.h>//一个身体的对象struct BODY {    int X;    int Y;};//定义蛇对象struct  SNAKE {    struct BODY body[WIDE*HIGH];    int size;} snake; //一个蛇对象//定义一个食物对象struct FOOD {    int X;    int Y;} food; //一个食物对象int score = 0;  //分数//用户按下 asdw 任意一个按键所得到的坐标值int kx = 0;int ky = 0;int lastX = 0;   //蛇尾的坐标int lastY = 0;//秒数int sleepSecond = 400;//声明函数void initSnake(void);void initFood(void);void initUI(void);void initWall(void);void playGame(void);void showScore(void);#endif


点击全文阅读


本文链接:http://zhangshiyu.com/post/69712.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1