C语言,234行代码控制台贪吃蛇

article/2025/10/23 10:48:49

  结果图:

先上全代码:

#include <stdio.h>
#include <Windows.h>//移动光标
#include <stdlib.h>
#include <time.h>//使用时间戳创建随机数种子
#include <conio.h>//监听键盘#define WIDE 50//定义地图宽度
#define HIGH 28//定义地图高度
#define MAP_MODE "■"//地图与食物模型
#define SNAKE_HEAD "□"//蛇头模型
#define SNAKE_BODY "●"//蛇身模型
#define X 70//光标归位横坐标
#define Y 28//光标归位纵坐标
#define INITLEN 3//初始化蛇长
#define MAXN 100//最大值int game = 1;//控制游戏是否退出
int initDirection = 'a';//原方向
int direction = 'a';//改变方向struct Snake {int size;//蛇长int x[MAXN];//蛇头横坐标int y[MAXN];//蛇头纵坐标
}snake;struct Food {int x;//食物横坐标int y;//食物纵坐标int flag;//此变量用于检测地图上是否需要食物
}food;//声明部分
//打印地图的函数
void mapPrint();
//初始化蛇
void initSnake();
//打印蛇
void moveSnake();
//光标移动函数
void gotoxy(int x, int y);
//随机出现食物
void creatFood();
//判断游戏状态
int judge();
//结算界面
void gameOver();
//游戏生成
void gameStart();
//
int levelControl();void main() {system("title 贪吃蛇");//更改窗口名system("mode con cols=100 lines=29");//更改窗口大小printf("输入1开始游戏,输入0退出:");scanf_s("%d", &game);while (game) gameStart(); 
}void gameStart() {int k = 150;//此变量用于控制延迟(游戏速度)k = levelControl();system("cls");//清屏mapPrint();food.flag = 1;initDirection = 'a';direction = 'a';while (game) {Sleep(k);//延迟150msif (food.flag) creatFood();//生成食物moveSnake();//控制移动if (judege()) game = 0;//判断游戏状态}gameOver();//结算画面
}
int levelControl() {//延迟控制int level = 0;printf("请输入游戏速度(1-5)(默认为3):");scanf_s("%d", &level);switch (level) {case 1:return 250;case 2:return 200;case 3:return 150;case 4:return 100;case 5:return 50;}
}void gotoxy(int x,int y) {//此函数用于移动光标HANDLE handle;handle = GetStdHandle(STD_OUTPUT_HANDLE);COORD pos = { x,y };SetConsoleCursorPosition(handle, pos);
}void mapPrint() {for (int i = 0;i < HIGH;i++) {//用i控制行for (int j = 0;j < WIDE;j++) {//用j控制列if (j == 0 || j == WIDE - 1) {//如果是第一列或最后一列printf(MAP_MODE);}else if (i == 0 || i == HIGH - 1) {//如果是第一行或最后一行printf(MAP_MODE);}else {printf("  ");}}printf("\n");}printf("使用wasd控制方向");//操作提示行initSnake();
}void creatFood() {srand(time(NULL));//利用时间戳赋予一个种子int isCreat = 1;//此变量用于确认食物位置与蛇是否重合food.x = rand() % (WIDE * 2 - 4) + 2;//产生横坐标随机数,减4防止与地图重合food.y = rand() % (HIGH - 2) + 1;//产生纵坐标随机数if (food.x % 2 == 0) {//因蛇头的坐标为偶数,为使吃到食物,食物横坐标须为偶数for (int i = 0;i < snake.size;i++) {if (snake.x[i] == food.x && snake.y[i] == food.y) isCreat = 0;}if (isCreat) {gotoxy(food.x, food.y);//光标跳跃printf(MAP_MODE);//打印食物gotoxy(X, Y);//光标归位food.flag = 0;}}
}//初始化一条蛇
void initSnake() {snake.size = INITLEN;//初始化蛇长snake.x[0] = WIDE;//定义蛇头在屏幕正中间snake.y[0] = HIGH / 2;//蛇头纵坐标gotoxy(snake.x[0], snake.y[0]);printf(SNAKE_HEAD);//打印蛇头for (int i = 1;i < snake.size;i++) {//打印蛇身snake.x[i] = snake.x[i - 1] + 2;snake.y[i] = snake.y[i - 1];gotoxy(snake.x[i], snake.y[i]);printf(SNAKE_BODY);}gotoxy(X, Y);//光标归位
}//移动
void moveSnake() {if (_kbhit()) {//监听键盘fflush(stdin);//清空缓存区int judgement = _getch();if (judgement == 'w' || judgement == 'W' || judgement == 's' || judgement == 'S' || judgement == 'a' || judgement == 'A' || judgement == 'd' || judgement == 'D')direction = judgement;//获得键盘输入的值,并赋给direction}gotoxy(snake.x[snake.size - 1], snake.y[snake.size - 1]);//移除蛇尾printf("  ");//打印空格以移除蛇尾for (int i = snake.size - 1;i > 0;i--) {//重新打印蛇身,蛇头使用direction控制snake.x[i] = snake.x[i - 1];snake.y[i] = snake.y[i - 1];gotoxy(snake.x[i], snake.y[i]);printf(SNAKE_BODY);}switch (direction) {//改变蛇头位置case 'w':case 'W':if(initDirection != 's' && initDirection != 'S')snake.y[0]--;else{direction = initDirection;snake.y[0]++;}break;case 's':case 'S':if (initDirection != 'w' && initDirection != 'W')snake.y[0]++;else {direction = initDirection;snake.y[0]--;}break;case 'a':case 'A':if (initDirection != 'd' && initDirection != 'D')snake.x[0] -= 2;else {direction = initDirection;snake.x[0] += 2;}break;case 'd':case 'D':if (initDirection != 'a' && initDirection != 'A')snake.x[0] += 2;else {direction = initDirection;snake.x[0] -= 2;}break;}initDirection = direction;gotoxy(snake.x[0], snake.y[0]);//重新打印蛇头printf(SNAKE_HEAD);gotoxy(X, Y);//光标归位if (snake.x[0] == food.x && snake.y[0] == food.y) {//若蛇头吃到食物snake.size++;food.flag = 1;}
}int judege() {//此函数用于判断游戏状态if (snake.x[0] == 0 || snake.x[0] == WIDE * 2 - 2) return 1;//如果撞到左右墙if (snake.y[0] == 0 || snake.y[0] == HIGH - 1) return 1;//如果撞到上下墙for (int i = 1;i < snake.size;i++) {//如果吃到自己if (snake.x[0] == snake.x[i] && snake.y[0] == snake.y[i]) return 1;}return 0;
}void gameOver() {system("cls");//清屏gotoxy(WIDE, HIGH / 2);//跳跃光标printf("Game Over!\n");//打印结束语printf("请输入0退出游戏,1重新游戏:\n");scanf_s("%d", &game);
}

写在最前面,对于gotoxy函数的解释:

gotoxy函数用于移动光标,来控制在何处打印食物,蛇头或蛇身。

void gotoxy(int x,int y) {//此函数用于移动光标HANDLE handle;handle = GetStdHandle(STD_OUTPUT_HANDLE);COORD pos = { x,y };SetConsoleCursorPosition(handle, pos);
}

HANDLE与COORD为系统定制好的一个结构体。

第三行代码获得标准输出句柄,并赋给handle。

COORD pos中的x,y代表光标移动的横坐标和纵坐标。

SetConsoleCursorPosition 函数是用来移动光标的。

贪吃蛇程序实现思路:

1.创建一个地图

2.创建一条蛇

3.随机生成食物

4.控制蛇移动,当蛇吃到食物,蛇变长

5.蛇头撞到墙或者自身,游戏结束

main函数前面就不解释了,从while开始:

gameStart游戏开始,使用levelControl函数控制返回延迟时间,来控制游戏速度

int levelControl() {//延迟控制int level = 0;printf("请输入游戏速度(1-5)(默认为3):");scanf_s("%d", &level);switch (level) {case 1:return 250;case 2:return 200;case 3:return 150;case 4:return 100;case 5:return 50;}
}

然后开始创建地图,调用mapPrint函数:

我写代码习惯还不错,注释基本都写了,我感觉这个看注释就能懂了

void mapPrint() {for (int i = 0;i < HIGH;i++) {//用i控制行for (int j = 0;j < WIDE;j++) {//用j控制列if (j == 0 || j == WIDE - 1) {//如果是第一列或最后一列printf(MAP_MODE);}else if (i == 0 || i == HIGH - 1) {//如果是第一行或最后一行printf(MAP_MODE);}else {printf("  ");}}printf("\n");}printf("使用wasd控制方向");//操作提示行initSnake();
}

第一步完成,接下来玩蛇,首先用结构体定义一条蛇:

注释标的很清楚了,MAXN是蛇身最大长,在最开始写了define MAXN 100;

struct Snake {int size;//蛇长int x[MAXN];//蛇头横坐标int y[MAXN];//蛇头纵坐标
}snake;

 mapPrint函数的结尾调用的initSnake函数,初始化一条蛇

其中INITLEN,WIDE,HIGH分别为初始蛇长,宽度,高度,均已define。

须注意snake.x[0] = WIDE;是因为地图模型的■,每个占用两字节。

main函数中定义的宽度为WIDE * 2,所以地图的x轴正中间为WIDE

void initSnake() {snake.size = INITLEN;//初始化蛇长snake.x[0] = WIDE;//定义蛇头在屏幕正中间snake.y[0] = HIGH / 2;//蛇头纵坐标gotoxy(snake.x[0], snake.y[0]);printf(SNAKE_HEAD);//打印蛇头for (int i = 1;i < snake.size;i++) {//打印蛇身snake.x[i] = snake.x[i - 1] + 2;snake.y[i] = snake.y[i - 1];gotoxy(snake.x[i], snake.y[i]);printf(SNAKE_BODY);}gotoxy(X, Y);//光标归位
}

然后生成食物,首先创建一个食物结构体:

struct Food {int x;//食物横坐标int y;//食物纵坐标int flag;//此变量用于检测地图上是否需要食物
}food;

for循环遍历蛇的各点坐标与食物坐标比较防止刷在蛇上面。

void creatFood() {srand(time(NULL));//利用时间戳赋予一个种子int isCreat = 1;//此变量用于确认食物位置与蛇是否重合food.x = rand() % (WIDE * 2 - 4) + 2;//产生横坐标随机数,减4防止与地图重合food.y = rand() % (HIGH - 2) + 1;//产生纵坐标随机数if (food.x % 2 == 0) {//因蛇头的坐标为偶数,为使吃到食物,食物横坐标须为偶数for (int i = 0;i < snake.size;i++) {if (snake.x[i] == food.x && snake.y[i] == food.y) isCreat = 0;}if (isCreat) {gotoxy(food.x, food.y);//光标跳跃printf(MAP_MODE);//打印食物gotoxy(X, Y);//光标归位food.flag = 0;}}
}

接下来是moveSnake函数,首先定义两个全局变量用来控制方向:

int initDirection = 'a';//原方向
int direction = 'a';//改变方向

初始化方向为向左。

第二行if监听键盘是否输入,如果输入,获取输入值赋给judgement,判断是否为wasd,如果是,将其赋给direction。

移除蛇尾并重新打印蛇身,使用switch判断键盘输入的direction,其中if用于判断输入要移动的方向与原来移动的方向是否冲突,若冲突,仍按原来的方向进行移动。

结尾判断蛇头坐标与食物坐标是否重合,若重合蛇变长,食物消失,须重新打印

void moveSnake() {if (_kbhit()) {//监听键盘fflush(stdin);//清空缓存区int judgement = _getch();if (judgement == 'w' || judgement == 'W' || judgement == 's' || judgement == 'S' || judgement == 'a' || judgement == 'A' || judgement == 'd' || judgement == 'D')direction = judgement;//获得键盘输入的值,并赋给direction}gotoxy(snake.x[snake.size - 1], snake.y[snake.size - 1]);//移除蛇尾printf("  ");//打印空格以移除蛇尾for (int i = snake.size - 1;i > 0;i--) {//重新打印蛇身,蛇头使用direction控制snake.x[i] = snake.x[i - 1];snake.y[i] = snake.y[i - 1];gotoxy(snake.x[i], snake.y[i]);printf(SNAKE_BODY);}switch (direction) {//改变蛇头位置case 'w':case 'W':if(initDirection != 's' && initDirection != 'S')snake.y[0]--;else{direction = initDirection;snake.y[0]++;}break;case 's':case 'S':if (initDirection != 'w' && initDirection != 'W')snake.y[0]++;else {direction = initDirection;snake.y[0]--;}break;case 'a':case 'A':if (initDirection != 'd' && initDirection != 'D')snake.x[0] -= 2;else {direction = initDirection;snake.x[0] += 2;}break;case 'd':case 'D':if (initDirection != 'a' && initDirection != 'A')snake.x[0] += 2;else {direction = initDirection;snake.x[0] -= 2;}break;}initDirection = direction;gotoxy(snake.x[0], snake.y[0]);//重新打印蛇头printf(SNAKE_HEAD);gotoxy(X, Y);//光标归位if (snake.x[0] == food.x && snake.y[0] == food.y) {//若蛇头吃到食物snake.size++;food.flag = 1;}
}

最后判断蛇此刻的状态:

int judege() {//此函数用于判断游戏状态if (snake.x[0] == 0 || snake.x[0] == WIDE * 2 - 2) return 1;//如果撞到左右墙if (snake.y[0] == 0 || snake.y[0] == HIGH - 1) return 1;//如果撞到上下墙for (int i = 1;i < snake.size;i++) {//如果吃到自己if (snake.x[0] == snake.x[i] && snake.y[0] == snake.y[i]) return 1;}return 0;
}

结尾添加结束界面:

void gameOver() {system("cls");//清屏gotoxy(WIDE, HIGH / 2);//跳跃光标printf("Game Over!\n");//打印结束语printf("请输入0退出游戏,1重新游戏:\n");scanf_s("%d", &game);
}

结束


http://chatgpt.dhexx.cn/article/aIyjjBG5.shtml

相关文章

贪吃蛇c语言源代码彩色版,贪吃蛇C语言源代码

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #include #include #include #include typedef struct snake { int a; int b; struct snake *u; struct snake *n; }snake,*snake1; typedef struct food { int a; int b; }food; void main() { char c,c0 d; int i,j,k,n1,t,at;…

C语言贪吃蛇游戏代码,贪吃蛇C语言代码实现大全

一、C语言贪吃蛇代码实现前言 设计贪吃蛇游戏的主要目的是让大家夯实C语言基础&#xff0c;训练编程思维&#xff0c;培养解决问题的思路&#xff0c;领略多姿多彩的C语言。 贪吃蛇是非常经典的一款游戏&#xff0c;本次我们模拟在控制台实现贪吃蛇游戏&#xff0c;也就是实现…

C语言入门项目篇:贪吃蛇(完整代码+详细注释)

C语言入门项目篇:贪吃蛇 可直接运行。 #include <stdio.h> #include <stdlib.h> #include <windows.h> #include <time.h> #include <conio.h> /*大一上的时候C语言入门学的一个小游戏。还是挺有意思的&#xff0c;有兴趣的同学可以继续优化下&…

完整!贪吃蛇游戏c语言代码分享(包括界面,计数,提示)

最近看到身边有些朋友抱怨&#xff0c;网上的贪吃蛇项目完整源码太少&#xff0c;或者说运行不了&#xff0c;甚至还有花钱购买的情况&#xff0c;作为你们的过来人&#xff0c;学长了解你们期末考试的苦&#xff0c;今天的博客我就不啰嗦&#xff0c;我直接放代码给你们。 所有…

C7-如何学好C语言

1&#xff1a;必须实践--敲代码 2&#xff1a;画图理解--内存布局 3&#xff1a;调试&#xff01;调试&#xff01; 课本推荐&#xff1a;

学好C语言从关键字开始

目录 1、C语言数据类型 2、变量的命名规则 3、最冤枉的关键字——sizeof 4、signed和unsigned 原、反、补 深入理解变量内容的存入和取出 大小端 1、C语言数据类型 在学习C语言数据类型之前&#xff0c;我们得先了解&#xff1a;为什么要有类型&#xff1f; 类型为什…

【c语言】如何学好c语言?c语言应该怎么去学?

大家好&#xff0c;我是想要慢慢变得优秀的向阳同学&#xff0c;谢谢大家的支持&#xff01;让我这个菜鸟博主可以有非常开心的收获1000的浏览量和200的粉丝&#xff01;我也会不断努力去持续分享一下高质量的博客内容的&#xff01;再次感谢大家的支持&#xff01;如果觉得我的…

python open函数编码_python中的open函数如何编码?

python中的open函数可以通过在打开文件时添加encoding参数来指定使用的编码方式&#xff0c;encoding表示的是返回的数据采用何种编码。 open()的函数原型&#xff1a;open(file, mode‘r, buffering-1, encodingNone, errorsNone, newlineNone, closefdTrue) 从官方文档中我…

open函数和 write函数

问题 Python内置多种函数与第三方库&#xff0c;本文对python中的open()函数和 write函数进行简单的讲解。 方法 open()函数 open()函数用于创建或打开指定文件&#xff0c;该函数的常用语法格式: open(name[,mode[,buffering]]) name : 要创建或打开文件的文件名称&#xff0c…

python open函数用法_Python使用open函数打开文件的常用模式

python 中open()的用法? open("/path/to/my/image.png", "rb") 中的‘rb’代表了什么意思?所有试图感动你而做的事,最终都只感动了小编自己。 r表示只读,b表示二进制 与此对应的是w表示可写,t表示文本方式打开。 再增加一些官方的解释: >>>…

linux中open函数详解

1、open函数 包含头文件 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> open函数有两个参数和三个参数 int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); Pathname:要打开的文件名…

python open函数默认路径_Python open函数打开文件路径

要以读文件的模式打开一个文件对象,使用Python内置的open()函数,传入文件名和标示符,标示符r表示读。 >>> f = open(D:/test.txt,r) 注意了,对初学python的同学而言,open()函数着实存在一个不大不小的坑,而且十分不容易发现。 错误演示: >>> f = open…

linux open详解,Linux系统open函数详解

Linux系统中open函数主要作用就是打开和创建文件,可以根据参数来定制我们需要的文件的属性和用户权限等各种参数,下面良许教程网为大家分享一下Linux系统open函数具体使用方法。 一、open函数用来干什么 open函数在Linux下一般用来打开或者创建一个文件,我们可以根据参数来定…

第9.2节 Python的文件打开函数open详解

一、 引言 在操作一个文件前&#xff0c;大部分情况需要先打开文件&#xff0c;才能进行&#xff0c;在Python中使用内置函数open来打开一个文件。open函数是Python的一个内置函数&#xff0c;io模块 定义的函数open是该内置函数的同义词&#xff08;这是Python官网中关于io.op…

Python open 函数

open 函数语法 open() 函数的作用是打开一个文件,并返回一个 file对象(即文件对象)。 open 是一个动作,可以理解为我们打开文档的点击动作。 file 对象是一个实物,可以理解为我们打开的具体文档,例如记事本、表格、Word 或其他具体的文档。 open() 函数的语法为: f =…

Linux 文件IO学习之open函数深入了解

open()函数是在学习文件IO中的第一个函数。作用是打开一个文件&#xff0c;或者创建出一个文件。 需要注意的是&#xff0c;能实现这样功能的函数其实有两套&#xff0c;一个是系统IO所提供的open()函数&#xff0c;一个是标准IO提供的fopen()函数。(二者对比放在最后) 先看看…

Python open函数详解

演示环境&#xff0c;操作系统&#xff1a;Win10 21H2&#xff08;64bit&#xff09;&#xff1b;Python解释器&#xff1a;3.8.10。 open是Python的一个内置函数&#xff0c;一般用于本地文件的读写操作。用法如下。 my_file open(file, mode, buffering, encoding, errors…

sql去重查询

背景&#xff1a; 项目有消息推送&#xff0c;根据消息推送记录&#xff0c;筛选出一共有哪几种消息类型&#xff0c;并且标题和文本是什么 表部分结构如图&#xff1a; 主要是根据subject来去重所有数据&#xff0c;难点是&#xff0c;使用distinct的话&#xff0c;无法显示…

sql 去重查询 distinct

sql 去重查询 select Distinct UserId,Name from UserInfo where UserType1 介绍 distinct一般是用来去除查询结果中的重复记录的&#xff0c;而且这个语句在select、insert、delete和update中只可以在select中使用&#xff0c; 具体的语法如下&#xff1a; select distinc…

SQL去重的三种方法

目录 1.distinct去重 2.group by去重 3.row_number() over (parttion by 分组列 order by 排序列) 有这么一张test的表, 我们将对这张表进行操作来自验证去重 这里的去重&#xff1a;查询的时候, 不显示重复&#xff0c;并不是删除表中的重复项 1.distinct去重 只能一列去…