对csdn作者的贪吃蛇程序进行了拓展增加了蛇头碰到蛇身为输以及给蛇身加点颜色。
原代码:
include <stdio.h>
include <stdlib.h>
include <windows.h>
include <time.h>
include <conio.h>``
/*大一上的时候C语言入门学的一个小游戏。还是挺有意思的,有兴趣的同学可以继续优化下:比如蛇头碰到蛇身就判定为输 /给蛇身加点颜色等。
*/
//1.2食物结构体
define MAPHEIGHT 25
define MAPWIDTH 60
define SNAKESIZE 50 //蛇的最大节数
struct FOOD
{
int x;
int y;
}food;
define SNAKESIZE 50 //蛇的最大节数
struct
{ //每一节蛇的坐标
int x[SNAKESIZE];
int y[SNAKESIZE];
int len; //蛇长
int speed; //
}snake;
///全局变量
int key='w';//初始化移动方向
int changFlag = 0;//蛇变化标记
//模块化设计
//
//1.画地图
void gotoxy(int x,int y); //实现的函数声明
void drawMap();
void createFood();
int snakeStatus();
void drawMap()
{
srand((unsigned)time(NULL)); //随机函数种子
//1.圈地
//1.1 左右边框
for(int i=0;i<=MAPHEIGHT;i++)
{
gotoxy(0,i);
printf("■");
gotoxy(MAPWIDTH,i);
printf("■");
}
for(int i=0;i<=MAPWIDTH;i+=2) //上下 ■占用两个字符
{
gotoxy(i,0);
printf("■");
gotoxy(i,MAPHEIGHT);
printf("■");
}
//2.画蛇 ■
//2.1确定蛇的属性
snake.len=3;
snake.speed =100;
snake.x[0]=MAPWIDTH/2; //开始蛇头放屏幕中间
snake.y[0]=MAPHEIGHT/2;
//2.2画蛇头
gotoxy(snake.x[0],snake.y[0]);
printf("■"); //一节 x=2
//画身体
for(int k =1;k<snake.len;k++)
{
snake.x[k]=snake.x[k-1]+2;
snake.y[k]=snake.y[k-1];
gotoxy(snake.x[k],snake.y[k]);
printf("■");
}
//3.画食物 ● //3.1确定坐标
food.x=rand()%(MAPWIDTH-4)+2; //边框的宽度是2 占用两个字符 两边边框就是4
food.y=rand()%(MAPHEIGHT-2)+1; //上下各占一个
if(food.x%2!=0)
{
food.x=food.x+1;
}
//3.2 画出来就可以
gotoxy(food.x,food.y);
printf("●");
}
//2.food
void createFood()
{
//蛇头坐标等于食物坐标,就是吃了
if(snake.x[0]food.x && snake.y[0]food.y)
{
srand((unsigned int)time(NULL));
//产生的食物不能在蛇的身上,并且坐标要是偶数 因为蛇头的宽度是偶数
while(1)
{
int flag=1;
food.x=rand()%(MAPWIDTH-4)+2;
food.y=rand()%(MAPHEIGHT-2)+1;
//产生的食物不能在蛇身上
for(int k=0;k<snake.len;k++)
{
if(snake.x[k]food.x&&snake.y[k]food.y)
{
flag = 0; //不合适的标志
break;
}
}
if(flag&&food.x%2==0)
{
break;}}gotoxy(food.x,food.y);//产生新的食物
printf("●");
snake.len++;
changFlag =1;//蛇的标记是1
}
//gotoxy(food.x,food.y);//产生新的食物
// printf("●");
}
void keyDown() //3.按键操作
{
//无按键的处理 原方向
if(_kbhit())
{//有按键
fflush(stdin);
key=_getch();
}
//擦除
if(!changFlag)
{
gotoxy(snake.x[snake.len-1],snake.y[snake.len-1]);
printf(" ");//两个空格擦掉尾巴。
}
//后面的蛇身
for(int i =snake.len-1;i>0;i--)
{
snake.x[i]=snake.x[i-1];
snake.y[i]=snake.y[i-1];
}
//移动方向的处理
switch(key)
{
case 'W': //往上走 y--
case 'w':
snake.y[0]--;
break;
case 'S':
case 's':
snake.y[0]++;
break;
case 'A':
case 'a':
snake.x[0]-=2;
break;
case 'd':
case 'D':
snake.x[0]+=2;
break;
}
//画蛇头
gotoxy(snake.x[0],snake.y[0]);
printf("■");
changFlag=0;
gotoxy(MAPHEIGHT+2,0); //移动不能一直看着光标
}
int snakeStatus() //4.蛇的状态:判断是否结束游戏
{
if (snake.x[0]0||snake.x[0]MAPWIDTH||snake.y[0]0||snake.y[0]MAPHEIGHT)
{
return 0;
//蛇头不能撞自己
for(int k=1;k<snake.len;k++)
{
if(snake.x[0]== snake.x[k]&& snake.y[k]==snake.y[0])
return 0;
}
}
return 1;
}
void gotoxy(int x,int y) //5.光标移动
{
//调用win32 API去设置控制台的光标位置
//1.找到控制台的这个窗口
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
//2.光标的结构体
COORD coord;
//3.设置光标
coord.X =x;
coord.Y =y;
//4.同步到控制台 Set Console Cursor Position
SetConsoleCursorPosition(handle,coord);
}
int main(){
drawMap();
while(1)
{
createFood();
Sleep(snake.speed);//延时
keyDown();
if(!snakeStatus())
{
break;
}
}
gotoxy(MAPWIDTH/2,MAPHEIGHT/2);
printf("You lose!");
system("pause"); //
return 0;
}
原代码地址:https://blog.csdn.net/TTKunn/article/details/140923996
修改后的代码:
include <stdio.h>
include <stdlib.h>
include <windows.h>
include <time.h>
include <conio.h>
define MAPHEIGHT 25
define MAPWIDTH 60
define SNAKESIZE 50 //蛇的最大节数
// 食物结构体
struct FOOD {
int x;
int y;
} food;
// 蛇结构体
struct {
int x[SNAKESIZE];
int y[SNAKESIZE];
int len; //蛇长
int speed; //速度
} snake;
// 全局变量
int key = 'w'; //初始化移动方向
int changFlag = 0; //蛇变化标记
// 函数声明
void gotoxy(int x, int y);
void drawMap();
void createFood();
int snakeStatus();
void keyDown();
void setColor(int color);
int selectDifficulty();
// 设置控制台文本颜色
void setColor(int color) {
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, color);
}
// 选择游戏难度
int selectDifficulty() {
int choice;
printf("请选择游戏难度:\n");
printf("1. 简单(慢)\n");
printf("2. 普通(中)\n");
printf("3. 困难(快)\n");
printf("请输入你的选择(1-3):");
scanf("%d", &choice);
switch (choice) {
case 1:
return 200; // 慢速
case 2:
return 100; // 中速
case 3:
return 50; // 快速
default:
printf("输入无效,默认选择普通难度。\n");
return 100;
}
}
// 画地图
void drawMap() {
srand((unsigned)time(NULL)); //随机函数种子
//1.圈地
//1.1 左右边框
for (int i = 0; i <= MAPHEIGHT; i++) {
gotoxy(0, i);
printf("■");
gotoxy(MAPWIDTH, i);
printf("■");
}
for (int i = 0; i <= MAPWIDTH; i += 2) { //上下 ■占用两个字符
gotoxy(i, 0);
printf("■");
gotoxy(i, MAPHEIGHT);
printf("■");
}
//2.画蛇 ■
//2.1确定蛇的属性
snake.len = 3;
snake.speed = selectDifficulty(); // 根据难度设置速度
snake.x[0] = MAPWIDTH / 2; //开始蛇头放屏幕中间
snake.y[0] = MAPHEIGHT / 2;
//2.2画蛇头
gotoxy(snake.x[0], snake.y[0]);
setColor(10); // 设置蛇头颜色为绿色
printf("■"); //一节 x=2
//画身体
for (int k = 1; k < snake.len; k++) {
snake.x[k] = snake.x[k - 1] + 2;
snake.y[k] = snake.y[k - 1];
gotoxy(snake.x[k], snake.y[k]);
setColor(12); // 设置蛇身颜色为红色
printf("■");
}
//3.画食物 ● //3.1确定坐标
food.x = rand() % (MAPWIDTH - 4) + 2; //边框的宽度是2 占用两个字符 两边边框就是4
food.y = rand() % (MAPHEIGHT - 2) + 1; //上下各占一个
if (food.x % 2 != 0) {
food.x = food.x + 1;
}
//3.2 画出来就可以
gotoxy(food.x, food.y);
setColor(14); // 设置食物颜色为黄色
printf("●");
}
// 创建食物
void createFood() {
//蛇头坐标等于食物坐标,就是吃了
if (snake.x[0] == food.x && snake.y[0] == food.y) {
srand((unsigned int)time(NULL));
//产生的食物不能在蛇的身上,并且坐标要是偶数 因为蛇头的宽度是偶数
while (1) {
int flag = 1;
food.x = rand() % (MAPWIDTH - 4) + 2;
food.y = rand() % (MAPHEIGHT - 2) + 1;
//产生的食物不能在蛇身上
for (int k = 0; k < snake.len; k++) {
if (snake.x[k] == food.x && snake.y[k] == food.y) {
flag = 0; //不合适的标志
break;
}
}
if (flag && food.x % 2 == 0) {
break;
}
}
gotoxy(food.x, food.y); //产生新的食物
setColor(14); // 设置食物颜色为黄色
printf("●");
snake.len++;
changFlag = 1; //蛇的标记是1
}
}
// 按键操作
void keyDown() {
//无按键的处理 原方向
if (_kbhit()) { //有按键
fflush(stdin);
key = _getch();
}
//擦除
if (!changFlag) {
gotoxy(snake.x[snake.len - 1], snake.y[snake.len - 1]);
printf(" "); //两个空格擦掉尾巴。
}
//后面的蛇身
for (int i = snake.len - 1; i > 0; i--) {
snake.x[i] = snake.x[i - 1];
snake.y[i] = snake.y[i - 1];
}
//移动方向的处理
switch (key) {
case 'W': //往上走 y--
case 'w':
snake.y[0]--;
break;
case 'S':
case 's':
snake.y[0]++;
break;
case 'A':
case 'a':
snake.x[0] -= 2;
break;
case 'd':
case 'D':
snake.x[0] += 2;
break;
}
//画蛇头
gotoxy(snake.x[0], snake.y[0]);
setColor(10); // 设置蛇头颜色为绿色
printf("■");
//画蛇身
for (int k = 1; k < snake.len; k++) {
gotoxy(snake.x[k], snake.y[k]);
setColor(12); // 设置蛇身颜色为红色
printf("■");
}
changFlag = 0;
gotoxy(MAPHEIGHT + 2, 0); //移动不能一直看着光标
}
// 蛇的状态:判断是否结束游戏
int snakeStatus() {
// 判断蛇头是否撞到墙壁
if (snake.x[0] == 0 || snake.x[0] == MAPWIDTH || snake.y[0] == 0 || snake.y[0] == MAPHEIGHT) {
return 0;
}
// 判断蛇头是否撞到蛇身
for (int k = 1; k < snake.len; k++) {
if (snake.x[0] == snake.x[k] && snake.y[0] == snake.y[k]) {
return 0;
}
}
return 1;
}
// 光标移动
void gotoxy(int x, int y) {
//调用win32 API去设置控制台的光标位置
//1.找到控制台的这个窗口
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
//2.光标的结构体
COORD coord;
//3.设置光标
coord.X = x;
coord.Y = y;
//4.同步到控制台 Set Console Cursor Position
SetConsoleCursorPosition(handle, coord);
}
int main() {
drawMap();
while (1) {
createFood();
Sleep(snake.speed); //延时
keyDown();
if (!snakeStatus()) {
break;
}
}
gotoxy(MAPWIDTH / 2, MAPHEIGHT / 2);
setColor(12); // 设置游戏结束文字颜色为红色
printf("You lose!");
setColor(7); // 恢复默认颜色
system("pause"); //
return 0;
}
代码说明:
- 蛇头撞到蛇身为输:在 snakeStatus 函数中,添加了一个循环来检查蛇头是否与蛇身的任何一部分相撞。如果相撞,返回
0
,表示游戏结束。
2.添加蛇身颜色:使用setColor
函数来设置蛇头和蛇身的颜色。蛇头设置为绿色(颜色代码10
),蛇身设置为红色(颜色代码12
),食物设置为黄色(颜色代码14
)。 - 恢复默认颜色:在游戏结束时,将控制台文本颜色恢复为默认颜色(颜色代码
7
)。
4.选择游戏难度:
在游戏开始时,玩家可以选择难度级别(简单、普通、困难)。
难度级别决定了蛇的移动速度:
简单:蛇速较慢(200ms)。
普通:蛇速中等(100ms)。
困难:蛇速较快(50ms)。
实现方式:
新增 selectDifficulty 函数,用于提示玩家选择难度并返回对应的速度值。
在 drawMap 函数中调用 selectDifficulty,将返回的速度值赋给 snake.speed。
游戏体验:
玩家可以根据自己的水平选择适合的难度,增加游戏的趣味性和挑战性。