C语言 —— 贪吃蛇
参考视频: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语言 —— 贪吃蛇的更多相关文章
- c语言贪吃蛇详解3.让蛇动起来
c语言贪吃蛇详解3.让蛇动起来 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识点. 上次 ...
- c语言贪吃蛇详解-2.画出蛇
c语言贪吃蛇详解-2.画出蛇 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识点. 蛇的身 ...
- c语言贪吃蛇详解1.画出地图
c语言贪吃蛇详解-1.画出地图 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识点. 首先 ...
- c语言贪吃蛇详解5.GameOver功能与显示成绩
c语言贪吃蛇详解5.GameOver功能与显示成绩 以前我们已经做出来了一个能吃东西变长的蛇.不过它好像不会死... 现在就来实现一下game over的功能吧. 写个函数判断蛇是否撞到自己或者撞到墙 ...
- c语言贪吃蛇详解4.食物的投放与蛇的变长
c语言贪吃蛇详解4.食物的投放与蛇的变长 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识 ...
- 程序游戏推荐(C语言贪吃蛇,python天天酷跑(需要安装pygame),js是狠人就坚持30s)
下面是下载位置,我把他们上传到我的文件下了. C语言贪吃蛇:https://files.cnblogs.com/files/ITXiaoAng/%E8%B4%AA%E5%90%83%E8%9B%87. ...
- C/C++编程笔记:C语言贪吃蛇源代码控制台(二),分数和食物!
接上文<C/C++编程笔记:C语言贪吃蛇源代码控制台(一),会动的那种哦!>如果你在学习C语言开发贪吃蛇的话,零基础建议从上一篇开始哦!接下来正式开始吧! 三.蛇的运动 上次我已经教大家画 ...
- C/C++编程笔记:C语言贪吃蛇源代码控制台(一),会动的那种哦!
前几天有个同学加我QQ私聊我说他们老师布置了一个贪吃蛇,他不知道怎么写所以来找我求解,我给他简单讲解了思路和一些难点之后他也能够自己独立将项目完成了!考虑到更多同学可能有贪吃蛇上的问题,今天有时间就来 ...
- c语言贪吃蛇
思路:函数gotoxy(x,y)使光标移植屏幕的x,y坐标(屏幕左上角为0,0),用来绘制蛇和界面,color()函数用来设置绘制的颜色.设有snakelong节,第i节蛇的x坐标为x[i],y坐标为 ...
- [C语言]贪吃蛇_结构数组实现
一.设计思路 蛇身本质上就是个结构数组,数组里存储了坐标x.y的值,再通过一个循环把它打印出来,蛇的移动则是不断地刷新重新打印.所以撞墙.咬到自己只是数组x.y值的简单比较. 二.用上的知识点 结构数 ...
随机推荐
- Nginx实战之让用户通过用户名密码认证访问web站点
1.Nginx实战之让用户通过用户名密码认证访问web站点 [root@master ~]# vim /usr/local/nginx/conf/extra/www.conf server { lis ...
- 手动创建binary log files和手动编辑binary log index file会有什么影响
基本环境:官方社区版MySQL 5.7.19 一.了解Binary Log结构 1.1.High-Level Binary Log Structure and Contents • Binlog包括b ...
- 如何用ModelsimSE仿真IP核-以PLL为例
我们之前介绍了如何使用Modelsim SE进行仿真和利用do文件的仿真方法,但是其中待仿真的模块是我们自己编写的Verilog模块,但是在实际工作中,我们的设计中会经常用到FPGA厂商给我们提供的现 ...
- 四、Logisitic Regssion练习(转载)
转载:http://www.cnblogs.com/tornadomeet/archive/2013/03/16/2963919.html 牛顿法:http://blog.csdn.net/xp215 ...
- 研究slatstack时踩过的坑,注意点及解决方案
运行问题 1.直接物理性移除minion或者更换minion原先连接的master,会导致先前的master始终无法ping通minion [root@localhost salt]# salt '* ...
- ajax异步请求302
我们知道,只有请求成功ajax才会进行回调处理,具体状态码为 status >= 200 && status < 300 || status === 304; 这一点通过查 ...
- windows环境变量PATH顺序的重要性
PATH是路径的意思,PATH环境变量中存放的值,就是一连串的路径.不同的路径之间,用英文的分号间隔开.系统在执行用户命令时,若用户未给出绝对路径,则首先在当前目录下寻找相应的可执行文件.批处理文件等 ...
- activiti报错ProcessEngines.getDefaultProcessEngine()为null
activiti报错ProcessEngines.getDefaultProcessEngine()为null 文件名错误,默认加载classpath下面的activiti.cfg.xml,而不是ac ...
- Eureka 开发时快速剔除失效服务
Spring Cloud 版本: Dalston.SR5 服务端配置: # 关闭保护机制 eureka.server.enable-self-preservation=false #剔除失效服务间隔 ...
- js 数组、对象转json 以及json转 数组、对象
1.JS对象转JSON 方式:JSON.stringify(obj) var json = {"name":"iphone","price" ...