文档开发者中心
我的

C语言彩色贪吃蛇代码实现

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/Fdog_/article/details/102625969

C语言彩色贪吃蛇代码实现

大家好,这是我在博客写的第一篇文章,如果哪里有问题还请多多指教!!以前我写的贪吃蛇是全图刷新的,导致在窗口运行时,眼睛都快闪瞎了!今天我为大家带来了不闪的贪吃蛇!!!废话不多说,上图,上代码!!





相关变量,

int JudgeSum = 0; //判断是否加快

int Pause = 200000000; //暂停速度(移动速度)

int * PJ = &JudgeDirection; //用指针传值判断移动方向

nakebody *end = NULL; //尾节点


创建链表 ,贪吃蛇的身体如何保存是游戏的核心,所以我们需要用到链表来保存蛇的身体,这样就可以随时知道蛇身数据。

typedef struct Snakebody

{

int x, y; //蛇身的坐标

struct Snakebody *next;//保存下一个蛇身的地址

}Snakebody; //通过typedef将 Snakebody 替代 struct Snakebody


食物坐标,记录食物出现的坐标。

typedef struct Snakexy

{

int x;

int y;

}Snakexy; //记录食物坐标


绘制初始界面和游戏地图,如图所示。

#include<Windows.h>

#define HEIGHT 20 //设置地图高度

#define WIDTH 40 //设置地图宽度

#define PRINTF printf('■');

#define LINE printf('\n');

#define EMPTY printf(' '); //因为这三个语句经常用,所以我就定义成了宏

void Front(); //绘制初始界面

void DeawMap(); //绘制地图


void Front()

{

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);//设置红色

MoveCursor(18, 11);

printf(' 贪 吃 蛇 ');

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);//设置绿色

MoveCursor(18, 12);

printf('作者:花狗');

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);//设置蓝色

MoveCursor(18, 13);

printf('QQ:2506897252');

MoveCursor(18, 14);

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);//设置红色和蓝色相加

MoveCursor(18, 15);

printf('请等待......');

for (int i = 0; i <= 3000000000; i++){}

system('cls');//清屏处理

}

void DeawMap()

{

for (int i = 0; i < WIDTH; i++)PRINTF LINE //打印上边框

for (int i = 1; i < HEIGHT - 1; i++) //打印左右边框

{

for (int j = 0; j < WIDTH; j++)

{

if (j == 0 || j == WIDTH - 1 || j == WIDTH - 10)

{

PRINTF

if (j == WIDTH - 1)LINE

}

else EMPTY

}

}

for (int i = 0; i < WIDTH; i++)PRINTF LINE //打印下边框

}


SetConsoleTextAttribute()函数是一个API设置字体颜色和背景色的函数。参数表中使用两个属性(属性之间用,隔开),不同于system(),SetConsoleTextAttribute()可以改变界面多种颜色,而system()只能修改为一种!。

4. 初始化蛇身,刚开始蛇不应该只要一个头,所以我们必须创建几个身体。


Snakebody *Phead = NULL; //存储着整个蛇身 不可更改

Snakebody *Phead_1 = NULL; //指向蛇身

Snakebody *Pbady = NULL; //创建节点

void ISnake(); //初始化蛇身

void ISnake()

{

for (int i = 0; i < 5; i++)//初始化蛇身拥有五个长度

{

Pbady = (Snakebody*)malloc(sizeof(Snakebody));//创建节点

Pbady->x = 5 - i;

Pbady->y = 5;

if (Phead == NULL)

{

Phead = Pbady;

}

else

{

end->next = Pbady;

}

Pbady->next = NULL;

end = Pbady;

}

Phead_1 = Phead;

while (Phead_1->next != NULL)//打印蛇身

{

MoveCursor(Phead_1->x, Phead_1->y);

PRINTF

Phead_1 = Phead_1->next;

}

}


5.产生食物,随机产生食物,如果和蛇身体重合则再次随机产生食物。


#include<time.h>

int sum = 0; //计算得分

Snakexy * Food = NULL; //保存食物位置

void FoodRand(); //生成食物

void FoodRand()

{

srand((int)time(0));

int x = rand() % 27 + 2;//生成随机数

int y = rand() % 17 + 2;

Phead_1 = Phead;

for (int i = 0; i <= 200; i++)

{

if (Phead_1->x == x&&Phead_1->y == y)

{

x = rand() % 27 + 2;

y = rand() % 17 + 2;

}

else

{

Phead_1 = Phead_1->next;

}

if (Phead_1->next == NULL)

{

break;

}

}

MoveCursor(x, y);

PRINTF

Food = (Snakexy*)malloc(sizeof(Snakexy));

Food->x = x;

Food->y = y;

MoveCursor(33, 5);

printf(' ');

Showf();

sum++;

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);// 蓝

}


rand函数功能为获取一个伪随机数,如要产生[m,n]范围内的随机数num,可用int num=rand()%(n-m+1)+m;

6.游戏刷新和暂停 ,按回车可暂停游戏。


int JudgeDirection = 4; //判断方向

void ControlMove(); //控制移动和暂停

void ControlMove()

{

if (GetAsyncKeyState(VK_UP) && 0x8000)

{

if (JudgeDirection == 2)

{

}

else

{

JudgeDirection = 1;

}

}

if (GetAsyncKeyState(VK_DOWN) && 0x8000)

{

if (JudgeDirection == 1)

{

}

else

{

JudgeDirection = 2;

}

}

if (GetAsyncKeyState(VK_RIGHT) && 0x8000)

{

if (JudgeDirection == 3)

{

}

else

{

JudgeDirection = 4;

}

}

if (GetAsyncKeyState(VK_LEFT) && 0x8000)

{

if (JudgeDirection == 4)

{

}

else

{

JudgeDirection = 3;

}

}

if (GetAsyncKeyState(VK_RETURN) && 0x0D)//判断回车

{

while (1)

{

if (GetAsyncKeyState(VK_RETURN) && 0x0D)//再次回车退出死循环

{

break;

}

}

}

}


GetAsyncKeyState()确定用户当前是否按下了键盘上的一个键

7.显示分数和难度,更新分数和难度。


int sum = 0; //计算得分

int Hard = 0; //计算难度

void Showf(); //显分数以及难度

void Showf()

{

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE);// 蓝

MoveCursor(33, 5);

printf('得分:%d', sum);

MoveCursor(33, 6);

printf('难度:%d', Hard);

}


8.移动光标 ,游戏不闪的原因就是我们只绘制一次地图 然后用光标定点刷新目标点。


void MoveCursor(int x, int y); //移动光标

void MoveCursor(int x, int y)//设置光标位置(就是输出显示的开始位置)

{

COORD pos = { x * 2,y };

HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);//获得标准输出的句柄

SetConsoleCursorPosition(output, pos); //设置光标位置

}


COORD是Windows API中定义的一种结构体


9.检测,检测是否吃到食物,是否撞墙,是否撞到自己。


void Jfood(); //检测是否吃到食物

void Jwall(); //检测蛇头是否撞墙

void Jsnake(); //检测蛇头是否撞到蛇身

void Jfood()

{

Phead_1 = Phead;

if (Phead_1->x == Food->x&&Phead_1->y == Food->y)

{

FoodRand();

JudgeSum += 1;

if (JudgeSum == 5)

{

JudgeSum = 0;//如果JudgeSum等于5则从新判断

Hard += 1;

Pause -= 20000000;//每成立一次循环减少20000000

}

while (Phead_1->next != NULL)

{

Phead_1 = Phead_1->next;

}

Snakebody *S = (Snakebody*)malloc(sizeof(Snakebody));

S->x = Food->x;

S->y = Food->y;

S->next = NULL;

Phead_1->next = S;

ControlMove();

MoveCursor(Phead_1->x, Phead_1->y);

PRINTF

}

//获取食物的坐标和蛇头做对比

}

void Jwall()

{

if (Phead->x == 0 || Phead->x == 29 || Phead->y == 0 || Phead->y == 19)

{

MoveCursor(10, 20);

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);//设置红色

printf('抱歉,你撞到了自己,游戏结束! ');

system('pause>nul');

exit(0);

}

}

void Jsnake()

{

Phead_1 = Phead->next;

while (Phead_1->next != NULL)

{

if ((Phead->x == Phead_1->x) && (Phead->y == Phead_1->y))

{

MoveCursor(10, 20);

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);//设置红色

printf('抱歉,你撞到了自己,游戏结束! ');

system('pause>nul');

exit(0);

}

Phead_1 = Phead_1->next;

}

}


10.游戏循环


void Move(); //游戏运行

void Move()

{

while (1)

{

Phead_1 = Phead;

while (Phead_1->next->next != NULL)

{

Phead_1 = Phead_1->next;

}

Phead_1->next = NULL;

for (int i = 0; i < Pause; i++) {}

ControlMove();

MoveCursor(Phead_1->x, Phead_1->y);

EMPTY

//上面为消除尾部

Snakebody *Phead_2 = (Snakebody*)malloc(sizeof(Snakebody));

if (*PJ == 1)

{

Phead_2->x = Phead->x;

Phead_2->y = Phead->y - 1;

}

if (*PJ == 2)

{

Phead_2->x = Phead->x;

Phead_2->y = Phead->y + 1;

}

if (*PJ == 3)

{

Phead_2->x = Phead->x - 1;

Phead_2->y = Phead->y;

}

if (*PJ == 4)

{

Phead_2->x = Phead->x + 1;

Phead_2->y = Phead->y;

}

Phead_2->next = Phead;

Phead = Phead_2;

MoveCursor(Phead_2->x, Phead_2->y);

PRINTF

Jfood();

Jwall();

Jsnake();

MoveCursor(40, 20);

}

}


11.释放内存,


void Free(); //释放内存

void Free()

{

while (Phead->next != NULL)

{

Phead=Phead->next;

free(Phead);

}

free(Phead);

}


int main()登场

int main()

{

Front();

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);//绿

DeawMap();

Showf();

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);// 暗白

MoveCursor(34, 10);

printf('↑');

MoveCursor(31, 11);

printf('使用←↓→来控制');

MoveCursor(31, 12);

printf('蛇的移动,撞墙游');

MoveCursor(31, 13);

printf('戏结束,每5分增 ');

MoveCursor(31, 14);

printf('一个难度(速度)');

ISnake();

FoodRand();

MoveCursor(40, 20);

Move();

Free();

return 0;

}


全部代码奉上:


#include<stdio.h>

#include<time.h>

#include<Windows.h>

#define HEIGHT 20 //设置地图高度

#define WIDTH 40 //设置地图宽度

#define PRINTF printf('■');

#define LINE printf('\n');

#define EMPTY printf(' ');

typedef struct Snakebody

{

int x, y;//身体的坐标

struct Snakebody *next;//结构指针

}Snakebody;//先来创建保持身体的链表,贪吃蛇的核心代码就是该如何保存蛇的身体

typedef struct Snakexy

{

int x;

int y;

}Snakexy; //记录食物坐标

int sum = 0; //计算得分

int JudgeSum = 0; //判断是否加快

int Hard = 0; //计算难度

int Pause = 200000000; //暂停速度(移动速度)

int JudgeDirection = 4; //判断方向

int * PJ = &JudgeDirection; //用指针传值判断移动方向

Snakebody *Phead = NULL; //存储着整个蛇身 不可更改

Snakebody *Phead_1 = NULL; //指向蛇身

Snakebody *Pbady = NULL; //创建节点

Snakebody *end = NULL; //尾节点

Snakexy * Food = NULL; //保存食物位置

void Front(); //游戏开始页面1

void Jfood(); //检测是否吃到食物1

void Jwall(); //检测蛇头是否撞墙1

void Jsnake(); //检测蛇头是否撞到蛇身1

void ISnake(); //初始化蛇身1

void DeawMap(); //绘制地图1

void FoodRand(); //生成食物1

void ControlMove(); //控制移动和暂停1

void MoveCursor(int x, int y); //移动光标1

void Move(); //游戏运行1

void Showf(); //显分数以及难度1

void Free(); //释放内存

int main()

{

Front();

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);//绿

DeawMap();

Showf();

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);// 暗白

MoveCursor(34, 10);

printf('↑');

MoveCursor(31, 11);

printf('使用←↓→来控制');

MoveCursor(31, 12);

printf('蛇的移动,撞墙游');

MoveCursor(31, 13);

printf('戏结束,每5分增 ');

MoveCursor(31, 14);

printf('一个难度(速度)');

ISnake();

FoodRand();

MoveCursor(40, 20);

Move();

return 0;

}

void Front()

{

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);//设置红色

MoveCursor(18, 11);

printf(' 贪 吃 蛇 ');

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);//设置绿色

MoveCursor(18, 12);

printf('作者:花狗');

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);//设置蓝色

MoveCursor(18, 13);

printf('QQ:2506897252');

MoveCursor(18, 14);

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);//设置红色和蓝色相加

MoveCursor(18, 15);

printf('请等待......');

for (int i = 0; i <= 3000000000; i++){}

system('cls');

}

void DeawMap()

{

for (int i = 0; i < WIDTH; i++)PRINTF LINE //上边框

for (int i = 1; i < HEIGHT - 1; i++) //打印左右边框

{

for (int j = 0; j < WIDTH; j++)

{

if (j == 0 || j == WIDTH - 1 || j == WIDTH - 10)

{

PRINTF

if (j == WIDTH - 1)LINE

}

else EMPTY

}

}

for (int i = 0; i < WIDTH; i++)PRINTF LINE //下边框

}

void MoveCursor(int x, int y)//设置光标位置(就是输出显示的开始位置)

{

/* COORD是Windows API中定义的一种结构体

* typedef struct _COORD

* {

* SHORT X;

* SHORT Y;

* } COORD;

* */

COORD pos = { x * 2,y };

HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);//获得 标准输出的句柄

SetConsoleCursorPosition(output, pos); //设置控制台光标位置

}

void FoodRand()

{

srand((int)time(0));

int x = rand() % 27 + 2;

int y = rand() % 17 + 2;

Phead_1 = Phead;

for (int i = 0; i <= 200; i++)

{

if (Phead_1->x == x&&Phead_1->y == y)

{

x = rand() % 27 + 2;

y = rand() % 17 + 2;

}

else

{

Phead_1 = Phead_1->next;

}

if (Phead_1->next == NULL)

{

break;

}

}

MoveCursor(x, y);

PRINTF

Food = (Snakexy*)malloc(sizeof(Snakexy));

Food->x = x;

Food->y = y;

MoveCursor(33, 5);

printf(' ');

Showf();

sum++;

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);// 蓝

}

void ControlMove()

{

if (GetAsyncKeyState(VK_UP) && 0x8000)

{

if (JudgeDirection == 2)

{

}

else

{

JudgeDirection = 1;

}

}

if (GetAsyncKeyState(VK_DOWN) && 0x8000)

{

if (JudgeDirection == 1)

{

}

else

{

JudgeDirection = 2;

}

}

if (GetAsyncKeyState(VK_RIGHT) && 0x8000)

{

if (JudgeDirection == 3)

{

}

else

{

JudgeDirection = 4;

}

}

if (GetAsyncKeyState(VK_LEFT) && 0x8000)

{

if (JudgeDirection == 4)

{

}

else

{

JudgeDirection = 3;

}

}

if (GetAsyncKeyState(VK_RETURN) && 0x0D)

{

while (1)

{

if (GetAsyncKeyState(VK_RETURN) && 0x0D)

{

break;

}

}

}

}

void ISnake()

{

for (int i = 0; i < 5; i++)

{

Pbady = (Snakebody*)malloc(sizeof(Snakebody));

Pbady->x = 5 - i;

Pbady->y = 5;

if (Phead == NULL)

{

Phead = Pbady;

}

else

{

end->next = Pbady;

}

Pbady->next = NULL;

end = Pbady;

}

Phead_1 = Phead;

while (Phead_1->next != NULL)

{

MoveCursor(Phead_1->x, Phead_1->y);

PRINTF

Phead_1 = Phead_1->next;

}

}

void Move()

{

while (1)

{

Phead_1 = Phead;

while (Phead_1->next->next != NULL)

{

Phead_1 = Phead_1->next;

}

Phead_1->next = NULL;

for (int i = 0; i < Pause; i++) {}

ControlMove();

MoveCursor(Phead_1->x, Phead_1->y);

EMPTY

//上面为消除尾部

Snakebody *Phead_2 = (Snakebody*)malloc(sizeof(Snakebody));

if (*PJ == 1)

{

Phead_2->x = Phead->x;

Phead_2->y = Phead->y - 1;

}

if (*PJ == 2)

{

Phead_2->x = Phead->x;

Phead_2->y = Phead->y + 1;

}

if (*PJ == 3)

{

Phead_2->x = Phead->x - 1;

Phead_2->y = Phead->y;

}

if (*PJ == 4)

{

Phead_2->x = Phead->x + 1;

Phead_2->y = Phead->y;

}

Phead_2->next = Phead;

Phead = Phead_2;

MoveCursor(Phead_2->x, Phead_2->y);

PRINTF

Jfood();

Jwall();

Jsnake();

MoveCursor(40, 20);

}

}

void Jfood()

{

Phead_1 = Phead;

if (Phead_1->x == Food->x&&Phead_1->y == Food->y)

{

FoodRand();

JudgeSum += 1;

if (JudgeSum == 5)

{

JudgeSum = 0;

Hard += 1;

Pause -= 20000000;

}

while (Phead_1->next != NULL)

{

Phead_1 = Phead_1->next;

}

Snakebody *S = (Snakebody*)malloc(sizeof(Snakebody));

S->x = Food->x;

S->y = Food->y;

S->next = NULL;

Phead_1->next = S;

ControlMove();

MoveCursor(Phead_1->x, Phead_1->y);

PRINTF

}

//获取食物的坐标和蛇头做对比

}

void Jwall()

{

if (Phead->x == 0 || Phead->x == 29 || Phead->y == 0 || Phead->y == 19)

{

MoveCursor(10, 20);

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);//设置红色

printf('抱歉,你撞到了自己,游戏结束! ');

system('pause>nul');

exit(0);

}

}

void Jsnake()

{

Phead_1 = Phead->next;

while (Phead_1->next != NULL)

{

if ((Phead->x == Phead_1->x) && (Phead->y == Phead_1->y))

{

MoveCursor(10, 20);

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);//设置红色

printf('抱歉,你撞到了自己,游戏结束! ');

system('pause>nul');

exit(0);

}

Phead_1 = Phead_1->next;

}

}

void Showf()

{

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE);// 蓝

MoveCursor(33, 5);

printf('得分:%d', sum);

MoveCursor(33, 6);

printf('难度:%d', Hard);

}

void Free()

{

while (Phead->next != NULL)

{

Phead=Phead->next;

free(Phead);

}

free(Phead);

}


————————————————

版权声明:本文为CSDN博主「Fdog_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/Fdog_/article/details/102625969


点赞
收藏
回复
1
分享
举报
浏览372 发布于2019-10-24 12:57未知归属地
全部评论
最多点赞
最新发布
最早发布

哈哈哈哈这个我很喜欢

1楼回复于2019-10-25 09:46 未知归属地
写回答
新增插入模板功能
一键使用模板,快速填写内容,轻松发帖~
知道了
  • 为了保障您的信息安全,请勿上传您的敏感个人信息(如您的密码等信息)和您的敏感资产信息(如关键源代码、签名私钥、调试安装包、业务日志等信息),且您需自行承担由此产生的信息泄露等安全风险。
  • 如您发布的内容为转载内容,请注明内容来源。

我要发帖子

了解社区公约,与您携手共创和谐专业的开发者社区。