c语言贪吃蛇自动走,C语言 贪吃蛇
贪吃蛇(单人版):
实现过程:
本人先来介绍一个函数 —— bioskey函数:
int bioskey (int cmd)
参数 (cmd)
基本功能
0
返回下一个从键盘键入的值(若不键入任何值,则将等下一个键入)它返回一个16位的二进制数,包括两个不同的值:1.当按下一个普通键时,它的低8位数存放该字符的ASCII码,高8位存放该键的扫描码;2.对于特殊键(如方向键、F1~F12等 等),低8位为0,高8位字节存放该键的扫描码
1
查询是否按下一个键,若按下一个键则返回非零值,否则返回0
2
bioskey()返回Shift、Ctrl、Alt、ScrollLock、NumLock、CapsLock、Insert键的状态。各键状态存放在返回值的低8位字节中。
在所有操作开始之前,本人先按照以往博文的惯例,编写家师所授的模仿Java中的boolean类型,自定义的伪 boolean型:
typedef unsigned char boolean;
#define TRUE 1
#define FALSE 0
本人先来构造一个可以用来表示一条蛇的结构体:
typedef struct SNAKE{
int head;//这个成员是为了我们之后判断蛇头方向用的
int len;//这个成员用来记录蛇当前 “应该”有的长度
int curlen;//这个成员用来记录蛇当前 “实际”的长度
int direct;//这个成员表示键盘输入的指令
SNAKE_BODY *snake;//这个成员是我们用来存储蛇的身体所在坐标用的
}
现在,我们构造一个能够存储蛇身体信息的结构体:
typedef struct SNAKE_BODY{
int xPostion;
int yPostion;
}SNAKE_BODY;
那么,为了,根据我们上面的蛇头和蛇方向的成员,我们现在来给出两个数组来存储蛇头的形状 和 蛇的方向:
首先,我们再来构造一个结构体,用来存储辅助蛇移动的结构体:
typedef struct DELTA_MOVE{
int deltRow;
int deltCol;
}DELTA_MOVE;
那么,现在本人就可以根据以上的结构体来给出两个数组了:
DELTA_MOVE delta[4] = {
{0, -1}, //向上运动
{0, 1}, //向下运动
{-1, 0}, //向左运动
{1, 0} //向右运动
};
char SnakeHead[4] = {
"^", "v", ""//这个数组存储的蛇头方向的 “上下左右”,分别存在下标为0、1、2、3的单元中
}
现在,根据上面的数组,我们来编写一个获取蛇头形状的函数:
char getHeadType(int snakeHeadIndex) {
return snakeHead[snakeHeadIndex];
}
那么,现在我们就可以初始化一条蛇了:
#define MAX_LEN 1000
//我们设定蛇最长为100(也可以设置地大一点,一般玩家都不会玩到100,所以本人设置最长长度是 100)
//由于最长长度是我们用宏定义定义的,所以,我们之后如果想要改的话,在这里改也比较方便
SNAKE player = {
0,//设定 开始时 蛇头信息存储在下标为0的数组空间内
5,//设定 开始时 蛇应该有5个长度
1,//因为刚开始是一个点,所以初始长度是1
3,//因为向右运动,所以设定运动方向是 右
NULL};//因为我们还没有初始化身体,所以先令身体为NULL
SNAKE_BODY snakeBody[MAX_LEN] = {{0,0}};
现在,我们来制定一下边界,使得我们做出来的游戏界面更加美观:
#define WALL -2
int screenPoint[Full_Screen_COUNT] = {0};//整个屏幕一共分为25行、80列
void init() {
int i;
int j;
int tmp;
for(i = 1; i <= 80; i++) {
for(j = 1; j <= 25; j++) {
if(!(i > 1 && i < 80 && j > 1 && j < 25)) {
tmp = (j - 1) * 80 + i - 1;
screenPoint[tmp] = WALL;
}
}
}
clrscr();
gotoxy(22, 12); /*这里的行、列值完全是一个点一个点测出来的,为了使下面的话能够在屏幕正中央显示*/
printf("Enter any char to start the game!");
}
void showBorder() {
int i;
clrscr();
for(i = 2; i < MAX_X; i++) { /*将“上下墙壁”显示出来*/
gotoxy(i, 2);
putch(223);
gotoxy(i, 25);
putch(220);
}
for(i = 2; i <= MAX_Y; i++) { /*将“左右墙壁”显示出来*/
gotoxy(1, i);
putch(219);
gotoxy(80, i);
putch(219);
}
}
现在,蛇 和 边界 的问题我们就基本上解决了,现在,我们来处理一个更为重要的事——从键盘读取有效指令,并将在未获得指令时执行上一次的指令:
#define UP 0x4800
#define DOWN 0x5000
#define LEFT 0x4b00
#define RIGHT 0x4d00
//以下两行:设置右侧数字键盘那里的+、-为加速减速键
#define PGUP 0x4900
#define PGDN 0x5100
#define ESC 0x11b
#define MAX_COUNT 20000
#define MIN_COUNT 125
#define DEFAULT_COUNT 5000
//以上的宏定义,分别将各字符定义为其“键盘扫描码”,以便我们之后的函数的使用
int readValidOrder(int key, int *tempCount, SNAKE *snake) {
int tmp;
tmp = snake->direct;
switch(key) {
case RIGHT: return tmp == 2 ? 2 : 3;
case LEFT: return tmp == 3 ? 3 : 2;
case DOWN: return tmp == 0 ? 0 : 1;
case UP: return tmp == 1 ? 1 : 0; /*上面的返回值分别对应“上”、“下”、“左”、“右”在“蛇头类型数组”中的下标*/
case PGUP: if(*tempCount > MIN_COUNT) {
*tempCount = *tempCount / 2;
}
return -1;
case PGDN: if(*tempCount < MAX_COUNT) {
*tempCount = *tempCount * 2;
}
return -1;
}
}
int main() {
int key;
int newKey;
int tempIndex;
int i = 0;//因为编译软件运行地太快,所以,为了能让我们反应地过来,我们使得计算机需运行cd次,才能有效执行一次
int cdTime = DEFAULT_COUNT;//(即:通俗来讲,就是为蛇的自动移动加一个cd,使得蛇移动速度降低)
SNAKE_BODY snakeBody[MAX_LEN] = {{0,0}};
SNAKE *player = {
0,
5,
1,
3,
NULL};
hideCursor();
init();
getch();
snakeBody[0].xPostion = headXPos;
snakeBody[0].yPostion = headYPos;
player.sb = snakeBody;
clrscr();
showBorder();
while(//TODO 蛇未死亡) {
i++;
key = bioskey(1);
if(key != 0){
newKey = bioskey(0);
if(newKey == ESC) {
break;
}
tempIndex = readValidOrder(newKey, &cdTime, &player);
if(tempIndex >= 0 && tempIndex <= 3) {
player.direct = tempIndex;
snakeHeadType = getHeadType(player.direct);
}
}
if(i > cdTime) {
//TODO 生成食物
//TODO 蛇移动
i = 0;
}
}
//善后处理
}
现在,我们来实现下蛇移动的要求:
#define BLOCK 0
void move(int *headXPos, int *headYPos, DELTA_MOVE *delta, char headType, SNAKE *snake) {
int tailRow;
int tailCol;
int tail;
int tempX;
int tempY;
tempX = snake->sb[snake->head].xPostion;
tempY = snake->sb[snake->head].yPostion;
gotoxy(tempX, tempY);
printf("*");
tempX = tempX + delta->deltRow;
tempY = tempY + delta->deltCol;
gotoxy(tempX, tempY);
printf("%c", headType);
snake->head = (snake->head + 1) % MAX_LEN;
snake->sb[snake->head].xPostion = tempX;
snake->sb[snake->head].yPostion = tempY;
*headXPos = tempX;
*headYPos = tempY;
if(snake->curLen < snake->len) {
(snake->curLen)++;
return;
}
tail = (snake->head - snake->len + MAX_LEN) % MAX_LEN;
tailRow = snake->sb[tail].xPostion;
tailCol = snake->sb[tail].yPostion;
screenPoint[(tailCol - 1) * MAX_X + tailRow - 1] = 0;
gotoxy(tailRow, tailCol);
printf(" ");
}
接下来就是产生食物的函数了:
void creatFoodNum() {
foodNum = rand()%2 ? 3 : 2;
}
void dealFood() {
dealFoodIndex();
showFood();
}
/*显示食物*/
void showFood() {
int i;
int x;
int y;
for(i = 0; i < Full_Screen_COUNT; i++) {
if(screenPoint[i] == USUAL_FOOD || screenPoint[i] == SUPER_FOOD) {
x = (i + 1) % MAX_X;
y = (i + 1) / MAX_X + 1;
gotoxy(x, y);
printf((screenPoint[i] == USUAL_FOOD) ? "#" : "$");
}
}
eatUpFood = FALSE;
}
/*放置食物*/
void dealFoodIndex() {
int randNum;
int i;
int count = 0;
int index[Full_Screen_COUNT] = {0};/*这个数组是为我们之后的“发牌算法”的使用做准备*/
int j = Full_Screen_COUNT-1;
for(i = 0; i < Full_Screen_COUNT; i++) {
if(screenPoint[i] == BLOCK) {
index[count] = i;
count++;
}
}
for(i = 0; i < foodNum; i++) {
srand(time(0) + i);
randNum = rand() % count;
screenPoint[index[randNum]] = rand()%2 ? USUAL_FOOD : SUPER_FOOD;
index[randNum] = index[j--];
count--;
}
}
那么,现在基本的准备就准备好了,我们现在来解决一下生成食物和蛇吃食变长的问题:
#define BLOCK 0
#define USUAL_FOOD 2
#define SUPER_FOOD 1
#define BODY -1
#define WALL -2
boolean dealEat(SNAKE *snake) {
int i;
int k;
int tmp;
int tempHeadX;
int tempHeadY;
tempHeadX = snake->sb[snake->head].xPostion;
tempHeadY = snake->sb[snake->head].yPostion;
tmp = (tempHeadY - 1) * MAX_X + tempHeadX - 1;
if((screenPoint[tmp] == USUAL_FOOD) || (screenPoint[tmp] == SUPER_FOOD)) {/*吃到食物*/
foodNum--;
screenPoint[tmp] = 0;
(snake->len) += (screenPoint[tmp] == USUAL_FOOD) ? 1 : 2;
}
if(screenPoint[tmp] == BODY) {/*吃到自身*/
clrscr();
gotoxy(40, 12);
printf("Game over!");
getch();
return TRUE;
}
screenPoint[(tempHeadY - 1) * MAX_X + tempHeadX - 1] = BODY;/*将这个点转换为蛇身*/
if(foodNum <= 0) {
eatUpFood = TRUE;
creatFoodNum();
}
return FALSE;
}
单人版完整代码:
那么,单人版的贪吃蛇我们就做好了。
本人现在来展示以下运行结果:
那么,作为本人的最后一篇《数据结构与算法》专栏的博文,当然不能就这么草草了事,本人既然提到了单人版,那么,在这篇博文中就要讲到进阶版——贪吃蛇(双人版)
贪吃蛇(双人版):
因为上面有本人的单人版的说明,那么接下来的双人版的代码中所用到的算法知识,就都在单人版中讲解过了,那么,本人直接上代码:
双人版完整代码:
那么,本人来展示一下运行结果:
那么,需要本篇博文两个版本贪吃蛇的完整代码的同学,请点击下方链接:
Gluttonous-Snake
做到这里,还是感慨良多的,这篇博文的内容,本应该在几个月前发布,但当时本人能力较弱,没完成这篇博文的内容,本人本来已经不打算编写这篇博文的内容了,但是,这篇博文的未完成,反而成了本人的一个心结,一直困扰着本人。于是,本人耗时一周课余时间,反复推敲、交流,终于完成了这篇博文的内容。
那么,以这篇博文做为本专栏的正式结尾篇,本人也算是可以全心全意地投入Java的学习中了。还望各位在今后的学习中能够持续关注本人的博文,谢谢一直以来一直在关注的大家啦!
那么,本专栏博文的全部内容本人就讲解完成了。
若对本专栏博文有任何疑问或者意见以及建议,请在下方评论区提出,本人将尽早予以讲解以及答复。
c语言贪吃蛇自动走,C语言 贪吃蛇相关推荐
- html贪吃蛇自动走,分享一个用html5实现的贪吃蛇特效代码
本篇小编为大家分享一个用html5实现的简单贪吃蛇特效代码,喜欢的小伙伴们可以看一下 Snake //内置大量BUG,I'm sorry. var lev=100; //定时器间隔时间 var num ...
- C语言控制怪物自动走,一起用C语言打怪物
//C语言多线程-主角和怪物 #include #include #define bool int //定义int变量为bool变量,bool不是真就是假 int a=0,b=20;//主角的坐标 i ...
- C语言多case自动跳出,C语言switch中case后跟随break语句
1.case后面的常量表达式实际上只起语句标号作用,而不起条件判断作用,即"只是开始执行处的入口标号". 因此,一旦与switch后面圆括号中表达式的值匹配,就从此标号处开始执行: ...
- c语言设置程序自动执行,c语言如何设置程序进程执行优先权
c语言如何设置程序进程执行优先权 使用setpriority()函数设置程序进程执行优先权: 头文件: #include#include 定义函数: int setpriority(int which ...
- c语言中实现自动平移,c语言实现图像的旋转与平移
y y y (4) ty≥height,图象完全移出了屏幕,不用做任何处理. 这种做法利用了位图存储的连续性,即同一行的象素在内存中是相邻的.利用 memcpy函数, 从(x ,y )-x )处,拷 ...
- c语言课程设计自动取款机,C语言课程设计………银行自动存取款机模拟.doc
C语言课程设计---银行自动存取款机模拟 作者:周鸣 需求分析: 本程序设计的任务为银行自助存取款机,程序要求实现atm机的基本功能,如 开户.查询.存款.取款.转账.容而生成操作日志. 概要设计: ...
- atm自动取款机c语言编码,ATM自动取款机C语言源代码.doc
#includevoid main() { int choice(int n,int money); int balance=1000000; int password,m=0; int n=0; p ...
- C语言小游戏大全,C语言贪吃蛇小游戏(附源码)
一.C语言小游戏大全,C语言贪吃蛇小游戏(附源码) 贪吃蛇小游戏源码和更多C语言课设项目小游戏源码免 费 下 载 链 接 如下: c语言项目课设小游戏源码资料压缩包.zip-C文档类资源-CSDN下载 ...
- 贪吃蛇的c语言程序码,C语言贪吃蛇代码下载_C语言贪吃蛇代码官方下载-太平洋下载中心...
C语言编写贪吃蛇源代码,简单易懂,文件为VC源代码.如果你正在学习c语言,就来下载吧.很经典的. C语言贪吃蛇代码原理: 产生一个固定大小没有边界的游戏区域,蛇从区域的中心开始,由玩家通过键盘控制蛇的 ...
- 基于C语言Ncurse库和链表的简单贪吃蛇小游戏
参考:基于C语言Ncurse库和链表的简单贪吃蛇小游戏 作者:三速何时sub20 发布时间:2020-09-29 10:23:51 网址:https://blog.csdn.net/weixin_44 ...
最新文章
- liunx php redis扩展,CentOS 7下安装php-redis扩展及简单使用
- 最优间隔分类器-SVM
- 《剑指Offer》用两个栈来实现队列
- 【转载】oracle normal、sys、system、sysdba、sysoperdba的区别
- python一些常用方法_收藏整理的一些Python常用方法和技巧
- TensorRT 环境搭建记录
- centos赋予访问权限
- Xcode10:library not found for -lstdc++.6.0.9 临时解决
- STM32——库函数版——数码管流动显示程序
- 常见的Markdownpad2运行破解以及This view has crashed!报错和Awesomium1.6.6SDK安装使用
- 期末复习-选择题整理(湖南大学操作系统课程雨课堂答案即期末题库)
- 网页倒计时制作(js)
- U盘未分配空间合并——U盘分区扩展卷为灰色的
- 一行搞定List<T>中的成员数量统计
- 飞地阿拉斯加的传奇故事
- Cannot execute request on any known server或DiscoveryClient_UNKNOWN/DESKTOP-MQ8D0C9:8761
- 湖北智禾教育:淘宝店铺如何找货源?
- jmeter事务控制器
- 领导驾驶舱是怎么做出来的?
- matlab算法(二维傅立叶级数变换)
热门文章
- 微信小程序,电子商城中快速实现收货地址(包含前端和后台实现)
- 测试用例设计方法——等价类划分法
- java项目开发实例基于javaweb+mysql数据库实现的宠物领养|流浪猫狗网站含论文+开题报告
- Fehelper 下载、安装与使用
- ttc、otf、ttf文件制作以及相关数据增强(OCR)
- 数学建模——相关系数(4)——斯皮尔曼相关系数(spearman)
- MacBookPro安装JDK环境
- List集合排序找出其中的最大和最小值
- 升流式水解酸化反应器设计计算_《HJ 2047-2015 水解酸化反应器污水处理工程技术规范》.pdf...
- Solidity 系列教程