贪吃蛇游戏代码(C语言项目)

2024-06-19 05:52

本文主要是介绍贪吃蛇游戏代码(C语言项目),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本篇仅提供C语言代码,详细讲解在这篇博客:C语言:贪吃蛇游戏(从0开始完整版)-CSDN博客

1、运行演示

QQ2024618-155655

2、代码构成(vs编译器)

3、C语言代码

3.1 头文件Snake.h

#pragma once
#include <locale.h>
#include <windows.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>#define POS_X 24
#define POS_Y 5#define WALL L'□'
#define BODY L'●'
#define FOOD L'★'//类型的声明//蛇的方向
enum DIRECTION
{UP = 1,DOWN,LEFT,RIGHT
};//蛇的状态
//正常、撞墙、撞到自己、正常退出
enum GAME_STATUS
{OK, //正常KILL_BY_WALL, //撞墙KILL_BY_SELF, //撞到自己END_NORMAL //正常退出
};//蛇身的节点类型
typedef struct SnakeNode
{//坐标int x;int y;//指向下一个节点的指针struct SnakeNode* next;
}SnakeNode, * pSnakeNode;//贪吃蛇
typedef struct Snake
{pSnakeNode _pSnake;//指向蛇头的指针pSnakeNode _pFood;//指向食物节点的指针enum DIRECTION _dir;//蛇的方向enum GAME_STATUS _status;//游戏的状态int _food_weight;//一个食物的分数int _score;      //总成绩int _sleep_time; //休息时间,时间越短,速度越快,时间越长,速度越慢
}Snake, * pSnake;//函数的声明
// 
// 
//定位光标位置
void SetPos(int x, int y);//欢迎界面的打印
void WelcomeToGame();//游戏的初始化
void GameStart(pSnake ps);//创建地图
void CreateMap();//初始化蛇身
void InitSnake(pSnake ps);//创建食物
void CreateFood(pSnake ps);//游戏运行的逻辑
void GameRun(pSnake ps);//蛇的移动-走一步
void SnakeMove(pSnake ps);//判断下一个坐标是否是食物
int NextIsFood(pSnakeNode next, pSnake ps);//下一个位置是食物,就吃掉食物
void EatFood(pSnakeNode next, pSnake ps);//下一个位置不是食物
void NoFood(pSnakeNode next, pSnake ps);//检测蛇是否撞墙
void KillByWall(pSnake ps);//检测蛇是否撞到自己
void KillBySelf(pSnake ps);//游戏善后的工作
void GameEnd(pSnake ps);

3.2 Snake.c(游戏相关代码)

#define _CRT_SECURE_NO_WARNINGS 1
#include "snake.h"
void SetPos(int x, int y)
{HANDLE hOutput = NULL;//获取标准输出的句柄(⽤来标识不同设备的数值)hOutput = GetStdHandle(STD_OUTPUT_HANDLE);COORD pos = { x,y };SetConsoleCursorPosition(hOutput, pos);
}
void WelcomeToGame()
{SetPos(40, 12);wprintf(L"欢迎来到贪吃蛇小游戏!");SetPos(43, 17);system("pause");system("cls");SetPos(25, 14);wprintf(L"用 ↑. ↓ . ← . → 来控制蛇的移动,按F3加速,F4减速\n");SetPos(40, 16);wprintf(L"加速能够得到更高的分数\n");SetPos(43, 20);system("pause");system("cls");
}
//●
void CreateMap()
{//上围墙for (int i = 0; i < 29; i++){wprintf(L"%c", WALL);}//下围墙SetPos(0, 26);for (int i = 0; i < 29; i++){wprintf(L"%c", WALL);}//左围墙for (int i = 1; i < 26; i++){SetPos(0, i);wprintf(L"%c", WALL);}//右围墙{for (int i = 1; i < 26; i++){SetPos(56, i);wprintf(L"%c", WALL);}}
}
#include <errno.h>
//初始化蛇身
void InitSnake(pSnake ps)
{pSnakeNode cur = NULL;for (int i = 0; i < 5; i++){cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL){perror("InitSnake::malloc() fail\n");return;}cur->x = POS_X + i * 2;cur->y = POS_Y;cur->next = NULL;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"%lc", BODY);cur = cur->next;}//设置贪吃蛇的属性ps->_dir = RIGHT;//默认向右ps->_score = 0;ps->_food_weight = 10;ps->_sleep_time = 200;//单位是毫秒ps->_status = OK;
}//创建食物
void CreateFood(pSnake ps)
{
#if 1int x = 0;int y = 0;
again:do{x = rand() % 53 + 2;//2~54y = rand() % 25 + 1;//1~25} while (x % 2 != 0);//只能为2的倍数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()");return;}pFood->x = x;pFood->y = y;pFood->next = NULL;SetPos(x, y);wprintf(L"%lc", FOOD);ps->_pFood = pFood;
#endif}
void GameStart(pSnake ps)
{system("mode con cols=100 lines=30");system("title 贪吃蛇");HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);//隐藏光标操作CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标信息CursorInfo.bVisible = false; //隐藏控制台光标SetConsoleCursorInfo(houtput, &CursorInfo);//设置控制台光标状态WelcomeToGame();CreateMap();InitSnake(ps);CreateFood(ps);
}void HelpInfor(pSnake ps)
{SetPos(60, 12);printf("不能穿墙,不能咬伤自己");SetPos(60, 13);printf("用 ↑. ↓ . ← . → 来控制蛇的移动");SetPos(60, 14);printf("按F3加速,F4减速");SetPos(60, 15);printf("ESC:退出游戏    space:暂停游戏");SetPos(60, 18);printf("由用户 小丁爱养花 制作");
}//最⾼位是1,说明按键的状态是按下,
// 如果最⾼是0,说明按键的状态是抬起
#define KeyPress(VK) (GetAsyncKeyState(VK)&1)void Pause()
{while (1){Sleep(200);if (KeyPress(VK_SPACE)){break;}}
}//判断下一个坐标是否是食物
int NextIsFood(pSnakeNode next, pSnake ps)
{if (next->x == ps->_pFood->x && next->y == ps->_pFood->y){return 1;}else{return 0;}
}//下一个位置是食物,就吃掉食物
void EatFood(pSnakeNode next, pSnake ps)
{ps->_pFood->next = ps->_pSnake;ps->_pSnake = ps->_pFood;free(next);next = NULL;pSnakeNode cur = ps->_pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}ps->_score += ps->_food_weight;CreateFood(ps);
}//下一个位置不是食物
void NoFood(pSnakeNode next, pSnake ps)
{next->next = ps->_pSnake;ps->_pSnake = next;pSnakeNode cur = ps->_pSnake;pSnakeNode prev = NULL;while (cur->next != NULL){prev = cur;SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}SetPos(cur->x, cur->y);wprintf(L"  ");if (prev){prev->next = NULL;}free(cur);cur = NULL;
}//检测蛇是否撞墙
void KillByWall(pSnake ps)
{if (ps->_pSnake->x <= 1|| ps->_pSnake->x >= 56|| ps->_pSnake->y <= 0|| ps->_pSnake->y >= 26){ps->_status = KILL_BY_WALL;}
}//检测蛇是否撞到自己
void KillBySelf(pSnake ps)
{pSnakeNode body = ps->_pSnake->next;while (body){if (ps->_pSnake->x == body->x && ps->_pSnake->y == body->y){ps->_status = KILL_BY_SELF;break;}body = body->next;}
}//蛇的移动-走一步
void SnakeMove(pSnake ps)
{pSnakeNode next = (pSnakeNode)malloc(sizeof(SnakeNode));if (next == NULL){perror("CreateFood()::malloc()");return;}next->next = NULL;if (ps->_dir == UP){next->x = ps->_pSnake->x;next->y = ps->_pSnake->y - 1;}else if (ps->_dir == DOWN){next->x = ps->_pSnake->x;next->y = ps->_pSnake->y + 1;}else if (ps->_dir == LEFT){next->x = ps->_pSnake->x - 2;next->y = ps->_pSnake->y;}else if (ps->_dir == RIGHT){next->x = ps->_pSnake->x + 2;next->y = ps->_pSnake->y;}if (NextIsFood(next, ps)){EatFood(next, ps);}else{NoFood(next, ps);}//检测蛇是否撞墙KillByWall(ps);//检测蛇是否撞到自己KillBySelf(ps);}//游戏运行的逻辑
void GameRun(pSnake ps)
{HelpInfor(ps);do{SetPos(60, 7);printf("得分:%d 每个食物得分:%d", ps->_score, ps->_food_weight);if (KeyPress(VK_UP) && ps->_dir != DOWN){ps->_dir = UP;}else if (KeyPress(VK_DOWN) && ps->_dir != UP){ps->_dir = DOWN;}else if (KeyPress(VK_LEFT) && ps->_dir != RIGHT){ps->_dir = LEFT;}else if (KeyPress(VK_RIGHT) && ps->_dir != LEFT){ps->_dir = RIGHT;}else if (KeyPress(VK_SPACE)){Pause();}else if (KeyPress(VK_ESCAPE)){ps->_status = END_NORMAL;}else if (KeyPress(VK_F3)){if (ps->_sleep_time > 80){ps->_sleep_time -= 30;ps->_food_weight += 2;}}else if (KeyPress(VK_F4)){if (ps->_food_weight > 2){ps->_sleep_time += 30;ps->_food_weight -= 2;}}SnakeMove(ps);Sleep(ps->_sleep_time);} while (ps->_status == OK);
}//游戏善后的工作
void GameEnd(pSnake ps)
{SetPos(24, 12);switch(ps->_status){case KILL_BY_WALL:wprintf(L"!!!您撞上墙壁了,游戏结束!!!");break;case KILL_BY_SELF:wprintf(L"!!!您撞上自己了,游戏结束!!!");break;case END_NORMAL:wprintf(L"!!!您主动退出游戏,游戏结束!!!");break;}pSnakeNode cur = ps->_pSnake;pSnakeNode prev = NULL;while (cur){prev = cur;cur = cur->next;free(prev);}prev = cur = NULL;
}

3.3 test.c(运行相关代码)

#define _CRT_SECURE_NO_WARNINGS 1
#include "snake.h"
//
void TestSnack()
{//char ch = '\0';int ch = 0;do {system("cls");Snake snake = { 0 };GameStart(&snake);GameRun(&snake);GameEnd(&snake);SetPos(20, 15);printf("是否开始新的一局游戏?Y/N:");ch = getchar();//while (getchar() != '\n');while (getchar() != '\n');system("cls");} while (ch == 'y' || ch == 'Y');SetPos(5, 26);
}
int main()
{setlocale(LC_ALL, "");srand((unsigned int)time(NULL));TestSnack();return 0;
}

这篇关于贪吃蛇游戏代码(C语言项目)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1074182

相关文章

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础

vite搭建vue3项目的搭建步骤

《vite搭建vue3项目的搭建步骤》本文主要介绍了vite搭建vue3项目的搭建步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1.确保Nodejs环境2.使用vite-cli工具3.进入项目安装依赖1.确保Nodejs环境

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D

idea+spring boot创建项目的搭建全过程

《idea+springboot创建项目的搭建全过程》SpringBoot是Spring社区发布的一个开源项目,旨在帮助开发者快速并且更简单的构建项目,:本文主要介绍idea+springb... 目录一.idea四种搭建方式1.Javaidea命名规范2JavaWebTomcat的安装一.明确tomcat

pycharm跑python项目易出错的问题总结

《pycharm跑python项目易出错的问题总结》:本文主要介绍pycharm跑python项目易出错问题的相关资料,当你在PyCharm中运行Python程序时遇到报错,可以按照以下步骤进行排... 1. 一定不要在pycharm终端里面创建环境安装别人的项目子模块等,有可能出现的问题就是你不报错都安装

Java集合之Iterator迭代器实现代码解析

《Java集合之Iterator迭代器实现代码解析》迭代器Iterator是Java集合框架中的一个核心接口,位于java.util包下,它定义了一种标准的元素访问机制,为各种集合类型提供了一种统一的... 目录一、什么是Iterator二、Iterator的核心方法三、基本使用示例四、Iterator的工

Java 线程池+分布式实现代码

《Java线程池+分布式实现代码》在Java开发中,池通过预先创建并管理一定数量的资源,避免频繁创建和销毁资源带来的性能开销,从而提高系统效率,:本文主要介绍Java线程池+分布式实现代码,需要... 目录1. 线程池1.1 自定义线程池实现1.1.1 线程池核心1.1.2 代码示例1.2 总结流程2. J

Go语言中json操作的实现

《Go语言中json操作的实现》本文主要介绍了Go语言中的json操作的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录 一、jsOChina编程N 与 Go 类型对应关系️ 二、基本操作:编码与解码 三、结构体标签(Struc

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

Vue实现路由守卫的示例代码

《Vue实现路由守卫的示例代码》Vue路由守卫是控制页面导航的钩子函数,主要用于鉴权、数据预加载等场景,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、概念二、类型三、实战一、概念路由守卫(Navigation Guards)本质上就是 在路