C语言小游戏:贪吃蛇(游戏代码实现)

❀❀❀ 文章由@不准备秃的大伟原创 ❀❀❀

♪♪♪ 若有转载,请联系博主哦~ ♪♪♪

❤❤❤ 致力学好编程的宝藏博主,代码兴国!❤❤❤

        生命不停,学习不止。大家好,我是大伟,今天的话继续给大家实现我们的C语言小游戏:贪吃蛇的主要的代码的编写,喜欢的铁汁们请关注并支持大伟哦~

        上篇博客我们谈论了贪吃蛇的游戏开发的环境和功能介绍,什么?你还没看过?那还不赶紧戳戳传送:——————> 贪吃蛇(游戏开发的环境和功能介绍) 

        效果展示:

贪吃蛇游戏

         首先呢,在实现代码之前,我们先理清一下我们游戏要实现的功能:

  1. 众所周知,我们玩贪吃蛇的时候都有个建议的地图来限制蛇的行动,而蛇撞到墙的时候会直接结束游戏。所以,我们需要写个正方形的墙体,并实现蛇的头撞到墙(蛇头的坐标与墙的坐标相同)就结束游戏。
  2. 此外,我们还需要一条蛇,我们需要用键盘操作蛇的运动方向,还可以改变蛇的运动速度,而当蛇吃到食物的时候蛇身会变长,当蛇头撞到墙或自己的身体时会结束游戏。所以我们需要用一种方法维护这条蛇,至于是什么方法呢,那当然是我们的单链表啦(各位铁汁们可以思考一下为什么是使用单链表) (^▽^ ) 。
  3. 然后就是食物了,食物每次只会出现一个(当然可以一次出现多个,看你自己的需求),而且食物出现的坐标是在墙限制的范围内随机的,当食物被蛇吃掉时就会消失,然后重新生成一个食物
  4. 接着就是需要一个计分表,用来显示当前的分数和每个食物的分数(速度越快,食物的占比分越高,反之越少)
  5. 最后就是游戏状态,可以控制游戏的进行与停止

        好的,以上就是要实现的功能,我们一个一个来吧!开码!

        Snake.h:

不管怎么说,现在头文件中把我们需要的功能及前置条件先写出来,博主这里直接给大家了:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<windows.h>
#include<locale.h>
#include<time.h>
//头文件的包含#define KEY_PRESS(VK)  ((GetAsyncKeyState(VK)&1) ? 1 : 0)
//检测按键是否按下#define WALL  L'□'
#define BODY L'●'
#define FOOD L'☆'
//定义宽字符#define POS_X 24
#define POS_Y 15
//定义坐标enum GAME_STATUS
{OK = 1,ESC,KILL_BY_WALL,KILL_BY_SELF,END_NORMAL
};
//定义游戏状态enum DIRECTION
{up = 1,down,left,right
};
//定义蛇的运动方向typedef struct SnakeNode
{int x;int y;struct SnakeNode* next;
}SnakeNode, * pSnakeNode;
//定义蛇的节点及身体坐标typedef struct Snake
{pSnakeNode _pSnake;//维护整条蛇的指针pSnakeNode pFood;//指向食物的指针int Score;//当前累积的分数int FoodWeight;//一个食物的分数int SleepTime;//蛇休眠的时间,休眠的时间越短,蛇的速度越快,休眠的时间越长,蛇的速度越慢enum GAME_STATUS Status;//游戏当前的状态enum DIRECTION Dir;//蛇当前走的方向
}Snake,*pSnake;
//定义游戏的各个功能//游戏开始前的初始化 
void GameStart(pSnake ps);//游戏运⾏过程 
void GameRun(pSnake ps);//游戏结束 
void GameEnd(pSnake ps);//设置光标的坐标 
void SetPos(short x, short y);//欢迎界面
void WelcomeToGame();//打印帮助信息 
void PrintHelpInfo();//创建地图 
void CreateMap();//初始化蛇 
void InitSnake(pSnake ps);//创建⻝物 
void CreateFood(pSnake ps);//暂停响应 
void pause();//下⼀个节点是食物 
int NextIsFood(pSnakeNode psn, pSnake ps);//吃食物 
void EatFood(pSnakeNode psn, pSnake ps);//不吃食物 
void NoFood(pSnakeNode psn, pSnake ps);//撞墙检测 
int KillByWall(pSnake ps);//撞自身检测 
int KillBySelf(pSnake ps);//蛇的移动 
void SnakeMove(pSnake ps);//游戏初始化 
void GameStart(pSnake ps);//游戏运⾏ 
void GameRun(pSnake ps);//游戏结束 
void GameEnd(pSnake ps);

       Snake.c:

             开始游戏:

void GameStart(pSnake ps)
{//设置控制台的信息,窗口大小,窗口名system("mode con cols=100 lines=30");system("title 贪吃蛇");//隐藏光标HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息CursorInfo.bVisible = false;SetConsoleCursorInfo(handle, &CursorInfo);//打印欢迎信息WelcomeToGame();//绘制地图CreateMap();//初始化蛇InitSnake(ps);//创建食物CreateFood(ps);
}

                 光标坐标定义:

void SetPos(short x, short y)
{HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获得设备句柄COORD pos = { x , y };//根据句柄设置光标位置SetConsoleCursorPosition(handle, pos);
}

                 打印欢迎信息:

void WelcomeToGame()
{//欢迎信息SetPos(36, 10);printf("欢迎来到贪吃蛇小游戏\n");SetPos(38, 20);system("pause");//暂停界面system("cls");//清除界面//功能介绍信息SetPos(15, 10);printf("用 ↑ . ↓ . ← . → 来控制蛇的移动,F3是加速,F4是减速");SetPos(15, 11);printf("加速能得到更高的分数");SetPos(38, 20);system("pause");system("cls");
}

                 绘制地图(坐标可以自己定义):

void CreateMap()
{int i = 0;//上SetPos(0, 0);for (i = 0; i <= 57; i+=2){wprintf(L"%c", WALL);}//下SetPos(0, 25);for (i = 0; i <= 57; i+=2){wprintf(L"%c", WALL);}//左for (i = 1; i <= 25; i++){SetPos(0, i);wprintf(L"%c", WALL);}//右for (i = 1; i <= 25; i++){SetPos(56, i);wprintf(L"%c", WALL);}}

                 初始化蛇:

void InitSnake(pSnake ps)
{pSnakeNode cur = NULL;int i = 0;for (int i = 0; i < 5; i++){cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL){perror("InitSnake()::malloc fail");return;}cur->next = NULL;cur->x = POS_X + i * 2;cur->y = POS_Y;//头插if (ps->_pSnake == NULL){ps->_pSnake = cur;}else{cur->next = ps->_pSnake;ps->_pSnake = cur;}}cur = ps->_pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%c", BODY);cur = cur->next;}ps->SleepTime = 200;ps->Score = 0;ps->Status = OK;ps->Dir = right;ps->FoodWeight = 10;}

                创建食物:

void CreateFood(pSnake ps)
{int x = 0;int y = 0;
again:do{x = rand() % 53 + 2;y = rand() % 24 + 1;} while (x % 2 != 0);pSnakeNode cur = ps->_pSnake;while (cur){if (cur->x == x && cur->y == y){goto again;}cur = cur->next;}pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));if (pFood == NULL){perror("CreateFood()::malloc fail");return;}else{pFood->x = x;pFood->y = y;SetPos(pFood->x, pFood->y);wprintf(L"%c", FOOD);ps->pFood = pFood;}
}

        游戏运行: 

void GameRun(pSnake ps)
{//打印帮助信息PrintHelpInfo();do{SetPos(64, 10);printf("得分:%d ", ps->Score);printf("每个食物得分:%-2d分", ps->FoodWeight);if (KEY_PRESS(VK_UP) && ps->Dir != down){ps->Dir = up;}if (KEY_PRESS(VK_DOWN) && ps->Dir != up){ps->Dir = down;}if (KEY_PRESS(VK_LEFT) && ps->Dir != right){ps->Dir = left;}if (KEY_PRESS(VK_RIGHT) && ps->Dir != left){ps->Dir = right;}if (KEY_PRESS(VK_SPACE)){pause(ps);}else if (KEY_PRESS(VK_ESCAPE)){ps->Status = END_NORMAL;break;}else if (KEY_PRESS(VK_F1)){if (ps->SleepTime >= 50){ps->SleepTime -= 30;ps->FoodWeight += 2;}}else if (KEY_PRESS(VK_F2)){if (ps->SleepTime <= 350){ps->SleepTime += 30;ps->FoodWeight -= 2;if(ps->SleepTime == 350)ps->FoodWeight = 1;}}Sleep(ps->SleepTime);SnakeMove(ps);} while (ps->Status == OK);}

                帮助信息:

void PrintHelpInfo()
{SetPos(64, 15);printf("不能穿墙,不能咬到自己\n");SetPos(64, 16);printf("用↑.↓.←.→分别控制蛇的移动.");SetPos(64, 17);printf("F1 为加速,F2 为减速\n");SetPos(64, 18);printf("ESC :退出游戏.space:暂停游戏.");SetPos(64, 20);printf("@不准备秃的大伟");
}

                游戏暂停: 

void pause()
{while (1){Sleep(300);if (KEY_PRESS(VK_SPACE)){break;}}
}

                蛇的运动: 

void SnakeMove(pSnake ps)
{pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));if (pNextNode == NULL){perror("SnakeMove():: malloc fail");return;}switch (ps->Dir){case up:{pNextNode->y = ps->_pSnake->y-1;pNextNode->x = ps->_pSnake->x;}break;case down:{pNextNode->y = ps->_pSnake->y + 1;pNextNode->x = ps->_pSnake->x;}break;case left:{pNextNode->y = ps->_pSnake->y;pNextNode->x = ps->_pSnake->x - 2;}break;case right:{pNextNode->y = ps->_pSnake->y;pNextNode->x = ps->_pSnake->x + 2;}break;}if (NextIsFood(pNextNode, ps)){EatFood(pNextNode,ps);}elseNoFood(pNextNode,ps);KillByWall(ps);KillBySelf(ps);
}

                        下一个位置是食物: 

int NextIsFood(pSnakeNode pfood, pSnake ps)
{return (pfood->x == ps->pFood->x) && (pfood->y == ps->pFood->y);
}

                        吃食物: 

void  EatFood(pSnakeNode pfood, pSnake ps)
{//头插pfood->next = ps->_pSnake;ps->_pSnake = pfood;pSnakeNode cur = ps->_pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%c", BODY);cur = cur->next;}ps->Score += ps->FoodWeight;free(ps->pFood);CreateFood(ps);
}

                        下一个位置不是食物: 

void NoFood(pSnakeNode pfood, pSnake ps)
{//头插pfood->next = ps->_pSnake;ps->_pSnake = pfood;pSnakeNode cur = ps->_pSnake;while (cur->next->next){SetPos(cur->x, cur->y);wprintf(L"%c", BODY);cur = cur->next;}SetPos(cur->next->x, cur->next->y);printf("  ");free(cur->next);cur->next = NULL;}

                        撞墙了: 

int KillByWall(pSnake ps)
{if  (  (ps->_pSnake->x == 0)|| (ps->_pSnake->x == 56)|| (ps->_pSnake->y == 0)|| (ps->_pSnake->y == 25)){ps->Status = KILL_BY_WALL;return 1;}return 0;
}

                        撞到自己了: 

int KillBySelf(pSnake ps)
{pSnakeNode cur = ps->_pSnake->next;while (cur){if((ps->_pSnake ->x == cur->x)&& (ps->_pSnake->y == cur->y)){ps->Status = KILL_BY_SELF;return 1;}cur = cur->next;}return 0;
}

        游戏结束:

void GameEnd(pSnake ps)
{pSnakeNode cur = ps->_pSnake;SetPos(10, 12);switch (ps->Status){case KILL_BY_SELF:printf("呆毛,撞上自己了,笑死啦哈哈!");break;case KILL_BY_WALL:printf("这么简单的游戏都能撞上墙,啧啧啧,啥实力?");break;case END_NORMAL:printf("玩不起就退游戏,我只能说菜,就多练 ");break;}while (cur){pSnakeNode del = cur;cur = cur->next;free(del);}
}

         test.c:

#include"Snake.h"
void test1()
{int ch = 0;srand((unsigned int)time(NULL));do{//创建贪食蛇Snake snake = { 0 };GameStart(&snake);//游戏开始前的初始化GameRun(&snake);//玩游戏的过程GameEnd(&snake);//善后的工作SetPos(20, 15);printf("再来一局吗?(Y/N):");ch = getchar();getchar();} while (ch == 'Y');SetPos(0, 26);
}
int main()
{setlocale(LC_ALL, "");test1();return 0;
}

        到此为止我们的贪吃蛇游戏已经写完啦!给自己鼓个掌把,啪叽啪叽~  游戏运行视频已经放在文章开头,大家敬请观看哦~

        A bird in the hand is worth two in the bush.   双鸟在林不如一鸟在手

        本篇博客也就到此为止了,送大家一碗鸡汤,勉励自己以及这世界上所有追逐梦想的赤子趁年华尚好努力提升自己,莫欺少年穷!   5ba9c2e48a6b4d0b87e7ce8c1dd150c1.jpeg

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/455988.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【CSS】css如何实现字体大小小于12px?

【CSS】css如何实现字体大小小于12px? 问题解决方案transform: scale(0.5)&#xff08;常用&#xff09;SVG 矢量图设置text 问题 文字需要显示为12px&#xff0c;但是小于12px的&#xff0c;浏览器是显示不来的 解决方案 transform: scale(0.5)&#xff08;常用&#xff0…

Spring核心基础:全面总结Spring中提供的那些基础工具类!

内容概要 Spring Framework 提供了众多实用的工具类&#xff0c;这些工具类在简化开发流程、提升代码质量和维护性方面发挥了重要作用&#xff0c;以下是部分关键工具类的总结及其使用场景&#xff1a; StringUtils&#xff1a;不仅提供了基础的字符串操作&#xff0c;如拼接…

完蛋,我被offer包围了|秋招自救指南

前言 &#x1f31f; 白泽时隔8年终于记起了b站的密码&#xff0c;这篇文章的视频讲解版已经上传&#xff0c;出镜怪不好意思的&#xff0c;后面写技术文章也会同步用视频的方式讲解&#xff0c;期待您的关注。 公众号&#xff1a;白泽talk&#xff0c;交流群&#xff1a;622383…

「牵手」联合国,看这家企业如何推动厕所可持续发展

作者 | 叶蓁 来源 | 洞见新研社 “没有人是一座孤岛&#xff0c;每个人都是广袤大陆的一部分。”英国诗人的这句话&#xff0c;用来形容当下的消费市场再准确不过。 当前&#xff0c;正是国家增强经济活力、发展内生动力的关键时期。2023年&#xff0c;我国全年GDP增速5.2%&…

电力负荷预测 | 基于TCN的电力负荷预测(Python)———数据预处理

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 基于TCN的电力负荷预测(Python) python3.8 keras2.6.0 matplotlib3.5.2 numpy1.19.4 pandas1.4.3 tensorflow==2.6.0

2024年美赛数学建模F题思路分析 - 减少非法野生动物贸易 (1)

# 1 赛题 问题F&#xff1a;减少非法野生动物贸易 非法的野生动物贸易会对我们的环境产生负面影响&#xff0c;并威胁到全球的生物多样性。据估计&#xff0c;它每年涉及高达265亿美元&#xff0c;被认为是全球第四大非法交易。[1]你将开发一个由数据驱动的5年项目&#xff0c…

【Python基础】案例分析:电商分析

电商分析 1 案例:某年淘宝双12部分购物数据 1.1 数据&#xff1a;某年淘宝双12部分购物数据&#xff1b; 来源&#xff1a;天池数据平台 1.2 分析目的&#xff1a; 熟悉电商常用分析指标用户行为分析用户价值模型 2 熟悉数据 2.1 导入数据 import pandas as pd fpath …

可拖拽表单可以用在哪些领域?

如果想要实现高效率的办公&#xff0c;可以通过低代码技术平台及可拖拽表单实现。什么服务商专业研发低代码技术平台产品&#xff1f;流辰信息拥有丰厚的研发技术功底和市场经验&#xff0c;可以助力企业做好数据管理工作&#xff0c;实现流程化办公&#xff0c;一起进入数字化…

【C语言】C的数据类型

数据类型决定&#xff1a; 1.数据所占内存字节数 2.数据取值范围 3.可以进行的操作 1. 数据类型决定&#xff1a;数据所占内存字节数 数据类型16位编译器32位编译器64位编译器int2字节4字节4字节char1字节1字节1字节float4字节4字节4字节double8字节8字节8字节 2. 数据类型决…

正点原子-STM32通用定时器学习笔记(1)

1. 通用定时器简介&#xff08;F1为例&#xff09; F1系列通用定时器有4个&#xff0c;TIM2/TIM3/TIM4/TIM5 主要特性&#xff1a; 16位递增、递减、中心对齐计数器&#xff08;计数值&#xff1a;0~65535&#xff09;&#xff1b; 16位预分频器&#xff08;分频系数&#xff…

VXLAN:虚拟化网络的强大引擎

1.什么是VXLAN VXLAN&#xff08;Virtual eXtensible Local Area Network&#xff0c;虚拟扩展局域网&#xff09;&#xff0c;是由IETF定义的NVO3&#xff08;Network Virtualization over Layer 3&#xff09;标准技术之一&#xff0c;是对传统VLAN协议的一种扩展。VXLAN的特…

【Python 实战】---- 实现向指定PDF指定页面指定位置插入图片

1. 需求 想要能否实现批量自动为多个pdf加盖不同六格虚拟章(不改变pdf原有分辨率和文字可识别性);改在pdf首页上方空白位置,一般居中即可;如可由使用者自主选择靠页边距更好,以便部分首页上方有字的文件时人工可微调位置。2. 需求分析 直接将 pdf 文件转换为图片,在将图…