贪吃蛇(简易版)Leslie5205912著
# include <stdio.h>
# include <string.h>
# include <windows.h>
# include <stdlib.h>
# include <conio.h>
# include <time.h>
# include <math.h>
# include<iostream>
using namespace std;
#pragma warning(disable:4996)
#define de_lenth 5//蛇初始长度
#define Row_max 20//地图行
#define Line_max 30//地图列
char map[Row_max][Line_max];
int snake[Row_max][Line_max];
int Head_x = Line_max / 2;
int Head_y = Row_max / 2;
int Tail_x;
int Tail_y;
int Head_v = 5;//头部移动
int timen=6;//延时程度(蛇运动速度)
int food_x;
int food_y;
int score=0;//分数
char direct = 's';//蛇的运动方向
void Creatmap(char map[Row_max][Line_max]); //设置地图
void Creatsnake(int snake[Row_max][Line_max]); //设置蛇
void Creatfood(char map[Row_max][Line_max], int snake[Row_max][Line_max]);//设置食物
bool Judgewall(int Head_y, int Head_x); //判断是否撞墙
void printmap(char map[Row_max][Line_max], int snake[Row_max][Line_max]);//打印地图和蛇
void Late();
void Run(char map[Row_max][Line_max], int snake[Row_max][Line_max]);//运行
void Movetail(); //移动尾巴
bool Eatfood(char map[Row_max][Line_max]); //判断是否吃到食物
void Result(); //初识页面
void Creatmap(char map[Row_max][Line_max]) {//画地图,分别画两行 # 号
for (int i = 0; i <= Line_max - 1; ++i){
map[Row_max - 1][i] = '#';
map[0][i] = '#';
}
for (int i = 1; i <= Row_max - 2; ++i) {
map[i][0] = '#';
map[i][Line_max - 1] = '#';
}
}
void Creatsnake(int snake[Row_max][Line_max]) {//画蛇
int n = de_lenth;
for (int i = Head_y; i >= Head_y - 5; --i) {
snake[i][Head_x] = n--;
if (i == Head_y - 5) {//给蛇尾巴赋位置
Tail_y = i;
Tail_x = Head_x;
}
}
}
void Creatfood(char map[Row_max][Line_max], int snake[Row_max][Line_max]) {//肯定减2啊傻逼
do{//随机数生成食物位置
food_x = rand() % (Line_max - 2) + 1;
food_y = rand() % (Row_max - 2) + 1;
} while (snake[food_y][food_x] != 0||map[food_y][food_x]=='#');//不能出现在蛇的身上,或在地图边
map[food_y][food_x] = '*';
}
bool Eatfood(char map[Row_max][Line_max]) {//判断是否吃到食物
if (map[Head_y][Head_x] == '*'){
map[Head_y][Head_x] = ' ';
return true;
}
else return false;
}
bool Judgewall(int Head_y,int Head_x) {//判断是否撞墙
if (Head_x == 0 || Head_x == Line_max - 1 || Head_y == 0 || Head_y == Row_max - 1)
return false;
else return true;
}
void printmap(char map[Row_max][Line_max], int snake[Row_max][Line_max]) {
for (int i = 0; i <= Row_max-1; ++i) {
for (int j = 0; j <= Line_max-1; ++j) {
//地图和蛇一起打印
if (snake[i][j] == 0)cout << map[i][j];
else {
if (snake[i][j] == Head_v)cout << "Q";
else cout << "*";
}//分别打印0,#,Q
}
cout << endl;
}
}
void Movetail() {//移动尾巴,下一步使尾巴变成0
if (snake[Tail_y][Tail_x] + 1 == snake[Tail_y + 1][Tail_x]) {
snake[Tail_y][Tail_x] = 0;
++Tail_y;
}
else if (snake[Tail_y][Tail_x] + 1 == snake[Tail_y - 1][Tail_x]) {
snake[Tail_y][Tail_x] = 0;
--Tail_y;
}
else if (snake[Tail_y][Tail_x] + 1 == snake[Tail_y][Tail_x + 1]) {
snake[Tail_y][Tail_x] = 0;
++Tail_x;
}
else {
snake[Tail_y][Tail_x] = 0;
--Tail_x;
}
}
void Result() {
system("cls");//清屏操作
cout << "Game Over!" << endl;
cout << "Your score is " << score * 10 << " !" << endl << "Press any key to exit!" << endl;
getch();
}
void Run(char map[Row_max][Line_max], int snake[Row_max][Line_max]) {//蛇的移动
/*
上 -32 0xffffffe0 72 H
下 -32 0xffffffe0 80 P
左 -32 0xffffffe0 75 K
右 -32 0xffffffe0 77 M
*/
//方向键为组合键
char ch, sh;
while (1) {
if (Judgewall(Head_y,Head_x)) {
if (kbhit()) {//kbhit()函数判断键盘是否敲击,头文件"conio.h"
ch=getch();
if (ch == -32) {
sh=getch();
if (direct == 'a') {
if (sh == 'M')continue;
}
else if (direct == 'd') {
if (sh == 'K')continue;
}
else if (direct == 'w') {
if (sh == 'P')continue;
}
else {
if (sh == 'H')continue;
}
//转头
switch (sh) {
case'H':direct = 'w';
break;
case'P':direct = 's';
break;
case'K':direct = 'a';
break;
case 'M':direct = 'd';
break;
}
}
else {
if (direct == 'a') {
if (ch == 'd' || ch == 'D')continue;
}
else if (direct == 'd') {
if (ch == 'a' || ch == 'A')continue;
}
else if (direct == 'w') {
if (ch == 's' || ch == 'S')continue;
}
else {
if (ch == 'w' || ch == 'W')continue;
}
switch (ch) {
case 'a':case 'A': direct = 'a'; break;
case 'w':case 'W': direct = 'w'; break;
case 's':case 'S': direct = 's'; break;
case 'd':case 'D': direct = 'd'; break;
}
}
}
//蛇动一步
if (direct == 'a') {
if (snake[Head_y][Head_x - 1] != 0)return;//吃到自己
--Head_x;
if (Eatfood(map)) {//如果吃到了食物,尾巴不动,并加分数
++score;
snake[Head_y][Head_x] = ++Head_v;
Creatfood(map, snake);
}
else {//没吃到,只移动头和尾巴
snake[Head_y][Head_x] = ++Head_v;
Movetail();
}
}
else if (direct == 'd') {
if (snake[Head_y][Head_x + 1] != 0)return;
++Head_x;
if (Eatfood(map)) {
++score;
snake[Head_y][Head_x] = ++Head_v;
Creatfood(map, snake);
}
else {
snake[Head_y][Head_x] = ++Head_v;
Movetail();
}
}
else if (direct == 'w') {
if (snake[Head_y - 1][Head_x] != 0)return;
--Head_y;
if (Eatfood(map)) {
++score;
snake[Head_y][Head_x] = ++Head_v;
Creatfood(map, snake);
}
else {
snake[Head_y][Head_x] = ++Head_v;
Movetail();
}
}
else {
if (snake[Head_y + 1][Head_x] != 0)return;
++Head_y;
if (Eatfood(map)) {
++score;
snake[Head_y][Head_x] = ++Head_v;
Creatfood(map, snake);
}
else {
snake[Head_y][Head_x] = ++Head_v;
Movetail();
}
}
//gotoxy(30, 30);
//清屏
system("cls");
//打印一次
printmap(map, snake);
//延时
Late();
}
else return;
}
}
void Late() {//延时函数
for (int i = 0; i <= pow(18, timen); ++i)
;
}
int main() {
cout << "Press any key to start this game!" << endl;
getch();
Creatsnake(snake);
Creatmap(map);
Creatfood(map, snake);
Run(map, snake);
Result();
}
这是一条关于贪吃蛇小游戏的代码,但内容且十分简单,主要包括几个数组的调控,以及键盘输入对数组的影响。并涉及一些DOS命令的知识。简单地说是一个很不错的基础代码。但其中也涉及到多个库函数,一些不常见的库函数也说明笔者有良好的编程基础。但是,毕竟是简易版小游戏,优化不够彻底,部分地方偷工减料,单核心的地方,键盘的输入与数组的交互还是体现出来了。那么下面说一说我发现的几个点,希望能帮助大家的理解。
先说优点吧,
第一,基础库函数充足,基础知识丰富,有很对地方都值得我们借鉴。比如,conio.h头文件,就是整个程序的核心,但运用起来非常的简单方便,主要有做kbhit()、get()函数,取得输入信息。#pragma warning(disable:4996)的使用也有所查询,但不是特别的理解,根据其他作者的说法,我理解为解决一些配饰原因的警告灯问题。
第二,排版分布非常合理。以上是我减少了不必要的行数,原版的排版十分清晰,层次分明。首先他把全局变量定义,后声明函数,然后大致按顺序输入函数体,最后main运行。思路清晰,值得学习,减少了不必要的麻烦。并且在关键的地方进行注释。模块化思想体现的很好,虽然没有建立新的模块,因为没必要,但在一个模块中有单独的分布。
第三,模式值得我们学习。上述代码属于以函数体为主要内容的模式,减少了main的函数体,增大了整部程序的灵活性,我个人十分喜欢这样的模式,而且我认为这样更偏向与面向对象的程序,方便将来的处理更加复杂的代码。
第四,DOS命令的使用。方便快捷,而且方便简单的优化。
第五,对细节的处理。进行了简单的测试。尝试了按当前方向键和反方向键,都没有发生错误正常的运行。还是依赖于Run()函数,中间主要依赖于多次的 if 判定和 switch 的选择。但同时增加了过多运行时间。
关于不足的地方,(本人能力不能和这位大佬比较,只是一些小小的看法)
第一,毕竟还是一个简易版本,并不是说编程者能力不足,主要是为了我们这样的新手考虑,没有复杂的操作,所以优化就略显不足,或者说还有很大的上升空间。比较关键的是每次使用清屏操作会有闪屏出现,我认为这点可以通过其他的简单方式弥补。列入使用蛇身的重建,方法有些繁琐,在这里我就不写了。
第二,基础速度过快。游戏中蛇的移速过快,没有难度的调整。建议增减难度调整。代码如下:
void Late() {//延时函数
int n;
if(a==1)n=16;
else if(a==2)n=14;
else if(a==3)n=12;
for (int i = 0; i <= pow(n, timen); ++i);
}
int main() {
cout << "请选择难度。1:简单,2:中等。3:困难" << endl;
cin>>a;
}
总结:代码大部分为基础代码,Run函数为核心代码,比较难理解,建议多留意。经过简单的优化也是一款非常经典的游戏。还有一些其他的经典小游戏,五子棋,俄罗斯方块等,都非常适合我们现阶段的学习。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
新增:
一、代码来源
CSDN博客https://blog.csdn.net/Leslie5205912/article/details/78980006
二、代码分析过程
当我拿到代码时,先观察主题,发现是以函数体为主的代码。开始记录全局变量和定义的函数。然后逐个分析每个函数的内容。在Run()函数逻辑比较复杂,花了较多的时间。其他的是一些相对易懂的函数。
贪吃蛇(简易版)Leslie5205912著的更多相关文章
- 原生js写的贪吃蛇网页版游戏特效
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <bo ...
- c/c++ 贪吃蛇控制台版
贪吃蛇控制台版(操作系统win7 64位:编译环境gcc, vs2017通过,其它环境未测试 不保证一定通过) 运行效果: #include <iomanip> #include < ...
- js贪吃蛇-简单版
分享个用原生js写的贪吃蛇,最近在学java,按照当年写的 js的思路,转换成java,换汤不换药 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1 ...
- 贪吃蛇java版
主要的蛇的类 import java.awt.Color; import java.awt.Graphics; import java.awt.HeadlessException; import ja ...
- 如何用python制作贪吃蛇以及AI版贪吃蛇
用python制作普通贪吃蛇 哈喽,大家不知道是上午好还是中午好还是下午好还是晚上好! 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很 ...
- 原生JavaScript贪吃蛇
在实例开发过程中还是能认识到很多不足的,并且加强了一些基础. 简单写一下制作过程: 1.创建画布 2.创建蛇和老鼠 坐标不能重叠 3.让蛇移动起来 4.添加死亡方法 5.添加转点坐标和方向 6.添加吃 ...
- C语言 贪吃蛇
贪吃蛇(单人版): 本人先来介绍一个函数 -- bioskey函数: int bioskey (int cmd) 参数 (cmd) 基本功能 0 返回下一个从键盘键入的值(若不键入任何值,则将等下一个 ...
- 原生Js贪吃蛇游戏实战开发笔记
前言 本课程是通过JavaScript结合WebAPI DOM实现的一版网页游戏---贪吃蛇的开发全过程,采用面向以象的思想设计开发.通过这个小游戏的开发, 不仅可以掌握JS的语法的应用,还可以学会D ...
- JavaScript 实现简易版贪吃蛇(Day_13)
时光永远在变迁,你始终要丢下过去. 使用语言 JavaScript 概述 运用JavaScript 实现简易版<贪吃蛇>. Html 页面 1 <!DOCTYPE htm ...
随机推荐
- Python基础之re模块
什么是模块? 为了编写可维护的代码,我们把很多的函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式,在Python中,一个.py文件就称为一个模块 ...
- spring整合thymeleaf
官方文档入口:https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html 1.首先需要引入thymeleaf的依赖(据官网文档,t ...
- localStorage sessionStorage 用法
sessionStorage.getItem('key') // 获取 sessionStorage.setItem('key','value') //设置 sessionStorage.remove ...
- spring boot + easypoi两行代码excel导入导出
easypoi封装了poi让我们能够非常简单的实现Excel导出,Excel模板导出,Excel导入,Word模板导出等,具体可见官网:http://www.afterturn.cn/. 我这边实现了 ...
- 基于KMP算法的字符串模式匹配问题
基于KMP算法的字符匹配问题 反正整个清明都在纠结这玩意...差点我以为下个清明要给自己过了. 至于大体的理解,我就不再多说了(还要画图多麻烦鸭),我参考了以下两个博客,写的真的不错,我放了超链接,点 ...
- 【HP-UNIX】修改HP-UNIX主机名称
原文链接:https://blog.csdn.net/lantianbaiyunbj/article/details/53434537 HP-UX修改主机IP地址 方法一 1.set_parms ho ...
- ajax的4个字母分别是什么意思
Asynchronous JavaScript and XML 的缩写,异步的JavaScript和XML.在不重新加载整个页面的情况下 ,AJAX 与服务器交换数据并更新部分网页.
- 深度原理与框架-图像超分辨重构-tensorlayer
图像超分辨重构的原理,输入一张像素点少,像素较低的图像, 输出一张像素点多,像素较高的图像 而在作者的文章中,作者使用downsample_up, 使用imresize(img, []) 将图像的像素 ...
- k3生成解决方案时错误处理
F6一键生成,会出现进程使用的错误,关掉了游览器,bos设计器,以及重启了本机iis站点,都没解决,打开任务管理器发现,bos.ide没有关掉
- UICollectionView didSelectItemAtIndexPath实现方法
didSelectItemAtIndexPath是通过UIResponder的四个touch方法实现的(touchBegan, touchMove, touchEnd, touchCancel),因此 ...