参考视频:https://www.bilibili.com/video/av29580072/?p=1

GreedySnake.h

 #ifndef GREEDYSNAKE_H_INCLUDED
#define GREEDYSNAKE_H_INCLUDED #define SNAKE_LENGTH 20 //蛇的长度最大为20
#define true 1
#define false 0
enum {UP = -, DOWN = , LEFT = -, RIGHT = }; typedef int bool; void FirstPage(); //设置起始游戏界面
void TestSpace(); //按空格开始游戏
void ShowBackground(); //展示游戏背景
void SetSnakeRandPos(); //为蛇产生一个随机的位置
void DrawSnake(); //画蛇
void SnakeMove(); //蛇动
void DestroySnake(); //销毁蛇
void ChangeDir(); //蛇随着方向键动起来
bool IsSnakeDie(); //判断蛇是否死亡
void ProduceFood(); //随机位置产生食物
void SnakeGrowUp(); //蛇变长
void PrintScore(); //打印分数 #endif // GREEDYSNAKE_H_INCLUDED

GreedySnake.c

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
#include <time.h>
#include "GreedySnake.h" //把所有元素置为0
//snake[0][0]表示蛇头的行,snake[0][1]表示蛇头的列,snake[0][2]表示蛇头移动的方向
int g_arrSnake[SNAKE_LENGTH][] = { }; int g_iSnakeLength = ; //初始长度为3,但数组下标从0开始,故此处为2 char g_arrBackGround[][] =
{
"████████████████████████\n", //一个█占两个字节,占两个字符的位置
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"█ █\n",
"████████████████████████\n"
}; int g_iSnakeDir = LEFT; //蛇的方向,默认向左
bool g_bIsProFood = true; //蛇产生食物的标记
int g_iRow; //食物的行坐标
int g_iCol; //食物的列坐标 int g_iScore = ; //分数 void FirstPage() //设置起始游戏界面
{
for (int i = ; i < ; ++i)
printf(" ");
for (int i = ; i < ; ++i)
printf("*");
printf("\n"); for (int j = ; j < ; ++j)
{
for (int i = ; i < ; ++i)
printf(" ");
printf("*");
for (int i = ; i < ; ++i)
printf(" ");
printf("*\n");
} for (int i = ; i < ; ++i)
printf(" ");
printf("*");
for (int i = ; i < ; ++i)
printf(" ");
printf("《 欢迎来到贪吃蛇的世界!》");
for (int i = ; i < ; ++i)
printf(" ");
printf("*\n"); for (int i = ; i < ; ++i)
printf(" ");
printf("*");
for (int i = ; i < ; ++i)
printf(" ");
printf("《 请按空格键开始游戏 》");
for (int i = ; i < ; ++i)
printf(" ");
printf("*\n"); for (int j = ; j < ; ++j)
{
for (int i = ; i < ; ++i)
printf(" ");
printf("*");
for (int i = ; i < ; ++i)
printf(" ");
printf("*\n");
} for (int i = ; i < ; ++i)
printf(" ");
for (int i = ; i < ; ++i)
printf("*");
for (int i = ; i < ; ++i)
printf("\n");
} void TestSpace() //按空格开始游戏
{
char c;
while ((c = getch()) != ' ') //getch()在头文件<conio>内
{ }
system("cls"); //清屏
} void ShowBackground() //展示游戏背景
{
for (int i = ; i < ; ++i)
printf(g_arrBackGround[i]);
} void SetSnakeRandPos() //设置蛇的初始位置,默认蛇的身子为三节,向左移动
{
int x, y;
srand((unsigned)time(NULL));
x = rand()% + ; //因为蛇的身子起始为三节,所以x的范围为1-20(蛇不能起始就撞墙)
y = rand()% + ; g_arrSnake[][] = y; //行 注意:x,y和初始背景中的行列刚好是反的
g_arrSnake[][] = x * ; //列 注意:一个█占两个字节,所以算其坐标时要乘以2
g_arrSnake[][] = LEFT; //方向 g_arrSnake[][] = y;
g_arrSnake[][] = x * + ;
g_arrSnake[][] = LEFT; g_arrSnake[][] = y;
g_arrSnake[][] = x * + ;
g_arrSnake[][] = LEFT; DrawSnake();
} void DrawSnake() //展示蛇
{
//因为一个█占两个字节,所以不能直接用strcpy(&arrBackGround[arrSnake[i][0]][arrSnake[i][1]],"█");否则会把\0拷贝进来,导致出错
//由于前面把arrSnake的所有元素都置为了0,所以当arrSnake[i][0]为0时,代表那个坐标处没有蛇的身子
for (int i = ; g_arrSnake[i][] != ; ++i)
strncpy(&g_arrBackGround[g_arrSnake[i][]][g_arrSnake[i][]], "█", ); //注意取地址符&不能漏掉!
} void DestroySnake() //销毁蛇
{
for (int i = ; g_arrSnake[i][] != ; ++i)
strncpy(&g_arrBackGround[g_arrSnake[i][]][g_arrSnake[i][]], " ", ); //注意取地址符&不能漏掉! } void SnakeMove() //蛇动
{
DestroySnake();
for(int i = SNAKE_LENGTH - ; i >= ; --i)
{
if(g_arrSnake[i][] != )
{
//把前一个节点的值,赋给当前节点
g_arrSnake[i][] = g_arrSnake[i-][];
g_arrSnake[i][] = g_arrSnake[i-][];
g_arrSnake[i][] = g_arrSnake[i-][];
}
} g_arrSnake[][] = g_iSnakeDir; //设置蛇头方向 //处理第一个节点(蛇头)
if(g_arrSnake[][] == LEFT || g_arrSnake[][] == RIGHT) //左右移动,列加减2
{
g_arrSnake[][] += g_arrSnake[][];
}
else
{
g_arrSnake[][] += g_arrSnake[][]; //上下移动,行加减1
} DrawSnake(); } void ChangeDir() //改变方向
{
//不能用getchar(), 会回显,并且要按回车之后才会开始读取
//不能用getch(), 同步检测 //异步检测
if(GetAsyncKeyState('W'))
{
if (g_arrSnake[][] != DOWN) //蛇不能回头
g_iSnakeDir = UP;
} if(GetAsyncKeyState('S'))
{
if (g_arrSnake[][] != UP)
g_iSnakeDir = DOWN;
} if(GetAsyncKeyState('A'))
{
if (g_arrSnake[][] != RIGHT)
g_iSnakeDir = LEFT;
} if(GetAsyncKeyState('D'))
{
if (g_arrSnake[][] != LEFT)
g_iSnakeDir = RIGHT;
}
} bool IsSnakeDie() //蛇死亡判断(包括撞墙和吃自己,两种情况)
{
if(g_arrSnake[][] == LEFT || g_arrSnake[][] == RIGHT) //如果蛇左右移动,则判断蛇头的左右是否是"█",如果是,则判定为蛇死亡
{
if(!strncmp(&g_arrBackGround[g_arrSnake[][]][g_arrSnake[][]+g_arrSnake[][]], "█", )) //注意取地址符&不能漏掉!
return true;
}
else //如果蛇上下移动,则判断蛇头的上下是否是"█"
{
if(!strncmp(&g_arrBackGround[g_arrSnake[][]+g_arrSnake[][]][g_arrSnake[][]], "█", ))
return true;
}
return false;
} void ProduceFood() //随机位置产生食物
{
//判断是否产生新的食物
if(g_bIsProFood == false)
return; bool bFlag = true;
srand((unsigned)time(NULL)); while() //产生合法的食物,即食物不与蛇的身子重合
{
g_iRow = rand()% + ; //行
g_iCol = rand()% + ; for (int i = ; g_arrSnake[i][] != ; i++) //遍历蛇
if (g_iRow == g_arrSnake[i][] && g_iCol == g_arrSnake[i][]) //如果在食物产生在蛇身上
{
bFlag = false;
break;
} if(bFlag == true)
break;
} strncpy(&g_arrBackGround[g_iRow][g_iCol*], "★", );
g_bIsProFood = false;
} void SnakeGrowUp() //蛇变长
{
if(g_iRow == g_arrSnake[][] && g_iCol* == g_arrSnake[][]) //注意:列要乘以2
{
if (UP == g_arrSnake[g_iSnakeLength][])
{
g_arrSnake[g_iSnakeLength+][] = g_arrSnake[g_iSnakeLength][]+;
g_arrSnake[g_iSnakeLength+][] = g_arrSnake[g_iSnakeLength][];
g_arrSnake[g_iSnakeLength+][] = g_arrSnake[g_iSnakeLength][];
}
else if (DOWN == g_arrSnake[g_iSnakeLength][])
{
g_arrSnake[g_iSnakeLength+][] = g_arrSnake[g_iSnakeLength][]-;
g_arrSnake[g_iSnakeLength+][] = g_arrSnake[g_iSnakeLength][];
g_arrSnake[g_iSnakeLength+][] = g_arrSnake[g_iSnakeLength][];
}
else if (LEFT == g_arrSnake[g_iSnakeLength][])
{
g_arrSnake[g_iSnakeLength+][] = g_arrSnake[g_iSnakeLength][];
g_arrSnake[g_iSnakeLength+][] = g_arrSnake[g_iSnakeLength][]+;
g_arrSnake[g_iSnakeLength+][] = g_arrSnake[g_iSnakeLength][];
}
else if (RIGHT == g_arrSnake[g_iSnakeLength][])
{
g_arrSnake[g_iSnakeLength+][] = g_arrSnake[g_iSnakeLength][];
g_arrSnake[g_iSnakeLength+][] = g_arrSnake[g_iSnakeLength][]-;
g_arrSnake[g_iSnakeLength+][] = g_arrSnake[g_iSnakeLength][];
}
g_iSnakeLength++;
g_bIsProFood = true;
g_iScore++;
} } void PrintScore() //打印分数
{
COORD rd;
//设置光标位置
rd.X = ;
rd.Y = ;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), rd);
printf("分数"); rd.X = ;
rd.Y = ;
//设置光标位置
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), rd);
//打印
printf ("%d", g_iScore);
}

main.c

 #include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <time.h>
#include "GreedySnake.h" int main()
{
FirstPage();
TestSpace();
system("cls");
SetSnakeRandPos();
ShowBackground(); while ()
{
system("cls");
ProduceFood();
SnakeGrowUp();
ChangeDir(); if(IsSnakeDie())
{
printf("snake die!\n");
break;
} SnakeMove();
ShowBackground();
PrintScore(); Sleep();
}
system("pause");
return ;
}

C语言 —— 贪吃蛇的更多相关文章

  1. c语言贪吃蛇详解3.让蛇动起来

    c语言贪吃蛇详解3.让蛇动起来 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识点. 上次 ...

  2. c语言贪吃蛇详解-2.画出蛇

    c语言贪吃蛇详解-2.画出蛇 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识点. 蛇的身 ...

  3. c语言贪吃蛇详解1.画出地图

    c语言贪吃蛇详解-1.画出地图 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识点. 首先 ...

  4. c语言贪吃蛇详解5.GameOver功能与显示成绩

    c语言贪吃蛇详解5.GameOver功能与显示成绩 以前我们已经做出来了一个能吃东西变长的蛇.不过它好像不会死... 现在就来实现一下game over的功能吧. 写个函数判断蛇是否撞到自己或者撞到墙 ...

  5. c语言贪吃蛇详解4.食物的投放与蛇的变长

    c语言贪吃蛇详解4.食物的投放与蛇的变长 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识 ...

  6. 程序游戏推荐(C语言贪吃蛇,python天天酷跑(需要安装pygame),js是狠人就坚持30s)

    下面是下载位置,我把他们上传到我的文件下了. C语言贪吃蛇:https://files.cnblogs.com/files/ITXiaoAng/%E8%B4%AA%E5%90%83%E8%9B%87. ...

  7. C/C++编程笔记:C语言贪吃蛇源代码控制台(二),分数和食物!

    接上文<C/C++编程笔记:C语言贪吃蛇源代码控制台(一),会动的那种哦!>如果你在学习C语言开发贪吃蛇的话,零基础建议从上一篇开始哦!接下来正式开始吧! 三.蛇的运动 上次我已经教大家画 ...

  8. C/C++编程笔记:C语言贪吃蛇源代码控制台(一),会动的那种哦!

    前几天有个同学加我QQ私聊我说他们老师布置了一个贪吃蛇,他不知道怎么写所以来找我求解,我给他简单讲解了思路和一些难点之后他也能够自己独立将项目完成了!考虑到更多同学可能有贪吃蛇上的问题,今天有时间就来 ...

  9. c语言贪吃蛇

    思路:函数gotoxy(x,y)使光标移植屏幕的x,y坐标(屏幕左上角为0,0),用来绘制蛇和界面,color()函数用来设置绘制的颜色.设有snakelong节,第i节蛇的x坐标为x[i],y坐标为 ...

  10. [C语言]贪吃蛇_结构数组实现

    一.设计思路 蛇身本质上就是个结构数组,数组里存储了坐标x.y的值,再通过一个循环把它打印出来,蛇的移动则是不断地刷新重新打印.所以撞墙.咬到自己只是数组x.y值的简单比较. 二.用上的知识点 结构数 ...

随机推荐

  1. HDU 1569 - 方格取数(2) - [最大点权独立集与最小点权覆盖集]

    嗯,这是关于最大点权独立集与最小点权覆盖集的姿势,很简单对吧,然后开始看题. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1569 Time Limi ...

  2. 为小程序开发创建本地mock数据服务器

    开发时使用easy-mock的服务,不是大厂就不是大厂,实在恶心,每天都会有卡的这么一段时间 于是,自己建个本地mock服务算了,想使用express 但是必须把json数据里面的不同对象,分配到不同 ...

  3. Spring 注解<context:annotation-config> 和 <context:component-scan>的作用与区别

    <context:annotation-config> 是用于激活那些已经在spring容器里注册过的bean(无论是通过xml的方式还是通过packagesanning的方式)上面的注解 ...

  4. 【windows核心编程】系统消息与自定义钩子(Hook)使用

    一.HOOk Hook是程序设计中最为灵活多变的技巧之一,在windows下,Hook有两种含义: 1.系统提供的消息Hook机制 2.自定义的Hook编程技巧 其中,由系统提供的消息钩子机制是由一系 ...

  5. 解析如何在C语言中调用shell命令的实现方法【转】

    本文转自:http://www.jb51.net/article/37404.htm 1.system(执行shell 命令)相关函数 fork,execve,waitpid,popen表头文件 #i ...

  6. springboot系列五、springboot常用注解使用说明

    一.controller相关注解 1.@Controller 控制器,处理http请求. 2.@RespController Spring4之后新加的注解,原来返回json需要@ResponseBod ...

  7. mysql系列十一、mysql优化笔记:表设计、sql优化、配置优化

    可以从这些方面进行优化: 数据库(表)设计合理 SQL语句优化 数据库配置优化 系统层.硬件层优化 数据库设计 关系数据库三范式 1NF:字段不可分; 2NF:有主键,非主键字段依赖主键; 3NF:非 ...

  8. Tpcc-MySQL对mysql数据库进行性能测试报告、分析及使用gnuplot生成图表展示

    TPC-C是专门针对联机交易处理系统(OLTP系统)的规范,一般情况下我们也把这类系统称为业务处理系统. tpcc-mysql是percona基于TPC-C(下面简写成TPCC)衍生出来的产品,专用于 ...

  9. centos中selinux功能及常用服务配置

    SELinux: Secure Enhenced Linux 常用命令 获取selinux的当前状态: # getenforce 临时启用或禁用: # setenfoce 0|1 永久性启用,需要修改 ...

  10. Java用四种方法实现阶乘n! (factorial)

    1. 引言 实现阶乘的方法很多,这边介绍四种方法,分别是递归,尾递归,循环和BigDecimal. 2. 代码 public class Test { public static void main( ...