字符游戏——贪吃蛇
来源:互联网 发布:算法设计 克林伯格 编辑:程序博客网 时间:2024/05/21 11:11
还记得在我们小时候玩过的贪吃蛇吗?正在学C语言的我,现在虽然无法完全还原那些年玩过的贪吃蛇经典小游戏,但却可以利用字符设计出低配版贪吃蛇啦!在下用了很长时间,终于完成了自己制作的第一款C语言游戏,在这里和大家分享!
字符·贪吃蛇游戏设计及算法
在设计之前,我们首先要回忆贪吃蛇的基本玩法和细节:
1.蛇只能进行上下左右四个方向的移动
2.蛇可以吃到食物,吃到食物后会在蛇尾增加一节长度
3.蛇头碰到墙壁或者自己的身体时游戏结束
这便是最基本的贪吃蛇,此外还有很多拓展出的功能,这里不再一一赘述。
在此基础上,我制作了人工控制移动的贪吃蛇。
最开始,我们需要了解贪吃蛇的基本元素,如蛇头蛇尾,食物,边界等。
#define SNAKE_MAX_LENGTH 50#define SNAKE_HEAD 'H'#define SNAKE_BODY 'X'#define BLANK_CELL ' '#define SNAKE_FOOD '$'#define WALL_CELL '*'char map[12][13] = { "************","*HXXXX *","* *","* *","* *","* *","* *","* *","* *","* *","* *","************" };
人工蛇,顾名思义,就是自己控制蛇的走位,不断吃食物壮大自己。
因此,上述三个基本特征分别可以通过下面的方法实现:
1.输入一个字符,判断移动方向,以WASD为例:W向上,A向左,S向下,D向右
2.在地图上食物以“
3.用IF条件判断蛇头H坐标与墙壁或者与任意一处蛇身X坐标是否相同,若是,游戏结束
总体框架用伪代码表示出来就是
print map[12][13]
while(not 游戏结束)
生成食物
输入字符c
SWIHCH(c)
CASE a:蛇头向左走 break;
CASE d:蛇头向右走 break;
CASE w:蛇头向上走 break;
CASE s:蛇头向下走 break;
END switch
END WHILE
print Game Over!!!
之后,利用函数不断的完善。
其中,关于移动的函数是最重要的,算法如下:
length为蛇长;
i为循环值,初始化为0;
snakex为蛇身的x坐标,snakey为蛇身的y坐标(snakex[0] snakey[0]分别为蛇头的x坐标,y坐标);
当输入字符时,判断蛇头走向,以决定snakex[0]和snakey[0]的值变化,然后:
while(i <=length-1)DO
{snakex[i]=snakex[i-1]
snakey[i]=snakey[i-1]
}
便完成了移动。
之后,还有蛇吃食物的蛇长变化,
为使其在蛇尾部分长度+1,设计如下算法:
length++;
lastx=snakex[length-1]
lasty=snakey[length-1]
MOVE;
IF(snake eat food)THEN
snakex[length-1]=lastx;
snakey[length-1]=lasty;
这样就完成了蛇长的变化。
在总框架的基础上,完成各部分的函数,这样,贪吃蛇之人工蛇版本便完成了:
#include <stdio.h>#include <stdlib.h>#include<time.h>#define SNAKE_MAX_LENGTH 50#define SNAKE_HEAD 'H'#define SNAKE_BODY 'X'#define BLANK_CELL ' '#define SNAKE_FOOD '$'#define WALL_CELL '*'char map[12][13] ={"************","*XXXXH *","* *","* *","* *","* *","* *","* *","* *","* *","* *","************" };//全局变量:初始状态表int food = 0;//定义开始时食物数量为0int x = 0, y = 0;//定义食物的坐标(x,y)int snakex[SNAKE_MAX_LENGTH] = { 5, 4, 3, 2, 1 };//蛇身的横坐标int snakey[SNAKE_MAX_LENGTH] = { 1, 1, 1, 1, 1 };//蛇身的纵坐标int lastX = 1, lastY = 1;//表示蛇尾部的坐标int length = 5;//定义初始长度,在该变量完成蛇长的变化void move(int x, int y);//蛇移动函数void output(void);//蛇移动效果打印函数void clear(void);//蛇移动前的蛇图像清空void printmap(void);//打印int gameover(void);//判定游戏结束(碰到身子或边界)void snakefood(void);//用来生成食物void eatfood(void);//蛇吃食物后身体增长int main() { int i; printmap(); //打印初始状态图 char c; int a = 0, b = 0; while ((scanf_s("%c", &c)) != EOF)//输入字母W,A,S,D { switch (c){//进行移动 case 'a'://左移时 a = 1; b = 0; snakefood(); move(a, b); if (gameover())//判定游戏是否结束 { printf("\nGAME OVER!!!\n"); break; } else printmap(); break; case 'd'://右移 b = 1; a = 0; snakefood(); move(a, b); if (gameover())//判定游戏是否结束 { printf("\nGAME OVER!!!\n"); break; } else printmap(); break; case 's'://上移 a = -1; b = 0; snakefood(); move(a, b); if (gameover())//判定游戏是否结束 { printf("\nGAME OVER!!!\n"); break; } else printmap(); break; case 'w'://下移 b = -1; a = 0; snakefood(); move(a, b); if (gameover())//判定游戏是否结束 { printf("\nGAME OVER!!!\n"); break; } else printmap(); break; } }//判定贪吃蛇的移动(通过move函数实现)并通过output函数实现map上的变化 return 0;}void move(int a, int b){ int i; if (a == 1 && b == 0) { clear();//清空map lastX = snakex[length - 1]; lastY = snakey[length - 1];//记录当前蛇尾坐标 for (i = length - 1; i >= 1; i--) { snakex[i] = snakex[i - 1]; snakey[i] = snakey[i - 1];//移动 } snakex[0]--;//蛇头移动 eatfood();//判断是否吃了食物 output();//移动完成 } if (a == 0 && b == 1) { clear(); lastX = snakex[length - 1]; lastY = snakey[length - 1]; for (i = length - 1; i >= 1; i--) { snakex[i] = snakex[i - 1]; snakey[i] = snakey[i - 1]; } snakex[0]++; eatfood(); output(); } if (a == -1 && b == 0) { clear(); lastX = snakex[length - 1]; lastY = snakey[length - 1]; for (i = length - 1; i >= 1; i--) { snakex[i] = snakex[i - 1]; snakey[i] = snakey[i - 1]; } snakey[0]++; eatfood(); output(); } if (a == 0 && b == -1) { clear(); lastX = snakex[length - 1]; lastY = snakey[length - 1]; for (i = length - 1; i >= 1; i--) { snakex[i] = snakex[i - 1]; snakey[i] = snakey[i - 1]; } snakey[0]--; eatfood(); output(); }}void clear(void){ int i; for (i = 0; i < length; i++) map[snakey[i]][snakex[i]] = BLANK_CELL;//将蛇原来位置清空}void output(void){ int i; map[snakey[0]][snakex[0]] = SNAKE_HEAD; for (i = 1; i < length; i++) map[snakey[i]][snakex[i]] = SNAKE_BODY;//蛇移动后的位置}void printmap(void){ int i; for (i = 0; i < 12; i++) { printf("%s\n", map[i]); } //蛇可以完成移动,并打印}int gameover(void){ int i; int fail = 0; for (i = 1; i<length; i++)//用来判断是否头碰身子 { if (snakex[0] == snakex[i] && snakey[0] == snakey[i]) fail = 1; } if (snakex[0]>10 || snakey[0] > 10 || snakex[0] < 1 || snakey[0] < 1 || fail == 1)//前四个条件为是否触碰边界,后一个条件判断是否头碰身子 return 1; else return 0;}void snakefood(void){ srand(time(NULL)); if (food == 0) { x = rand() % 10 + 1; y = rand() % 10 + 1; if (map[x][y] == ' ')//确保在空白位置出现食物 { map[x][y] = SNAKE_FOOD;//在地图可到达位置上随机生成食物 food++;//确保每次只出现一个食物 } }}void eatfood(void){ if (snakey[0] == x&&snakex[0] == y)//判断蛇是否吃到食物 { length++; food = 0;//食物已经被吃掉,清空 snakex[length - 1] = lastX; snakey[length - 1] = lastY;//蛇长增加一个 }}
游戏成果如下:
在后期,可以通过引用windows函数库来优化界面,例如每次循环后清空整个界面,使其更加直观等等,大家可以尝试。
我们可以看到,先写出总控代码是多么重要,它的清晰程度决定了你设计算法以及对应函数需要的时间和思考量。
- 字符游戏—贪吃蛇
- 字符游戏——贪吃蛇
- 简单字符游戏——贪吃蛇
- 字符游戏——贪吃蛇
- 字符游戏——贪吃蛇
- 字符游戏--贪吃蛇!
- 字符游戏贪吃蛇
- 【C语言编程设计】字符游戏——贪吃蛇
- 字符游戏——简单贪吃蛇的制作
- 字符版本贪吃蛇游戏
- 游戏——贪吃蛇
- 字符版本贪吃蛇游戏设计
- 字符版本贪吃蛇游戏创新玩法
- 字符游戏-贪吃蛇算法设计
- 贪吃蛇游戏——主要代码
- 诺基亚游戏——贪吃蛇
- 简单游戏——贪吃蛇
- 经典游戏——贪吃蛇
- 硬盘数据恢复软件免费版
- cordova NFC读卡(javascript)
- java Timer(定时调用、实现固定时间执行)
- 单列模式,懒汉 ,饿汉
- LUA实现麻将胡牌判定
- 字符游戏——贪吃蛇
- NDK的基础使用(AS版)
- 让 Python 更加充分的使用 Sqlite3
- 【Python】多进程的进程池pool运行时报错:ValueError: Pool not running
- iOS热更新实现方式
- 移植块设备驱动和虚拟网卡驱动
- google浏览器cookie文件位置
- 令人智熄的智(zhi)能(zhang)蛇
- tensorflow官网进不去,因为它的地址改变了。