和小白一起做贪吃蛇吧!会C++就可以上车!

小白第一次写文章,如有不足之处,欢迎大家指出!
因为本人是新手,所以尽量使用通俗易懂的话,没有太多专业术语,不太会用目录,大佬还请多多包涵!

前言:本文所有的方向用8,2,4,6表示,对应小键盘上的↑,↓,←,→,这么做可以直观地看出方向,方便程序的编写。
考虑到有读者可能不了解一些游戏必备的函数,所以我做了简要的介绍,大佬请跳过*部分。

首先,我们定义一个Snake类封装贪吃蛇游戏,并声明一些基本的变量和成员函数:

class Snake {
private:signed char**map;//游戏地图int length;//蛇的长度int head[2];//蛇头坐标int tail[2];//蛇尾坐标char direction;//描述蛇的移动方向:8-↑,2-↓,4-←,6-→char speed;//蛇的速度void print()const;    //显示游戏地图的函数int move() ;//移动函数:0-正常移动,1-撞墙,2-咬到自己void turn(int const&kbinput) ;//转弯函数void create() ;//生成食物的函数
}

核心设计思路:
游戏地图map为二维数组,如果数组元素map[ i ][ j ]的值为0,代表该位置什么也没有;如果map[ i ][ j ]的值>0,代表该位置是蛇的身体;如果 -1 == map[ i ][ j ],代表该位置是食物;如果map[ i ][ j ] > 0,代表该位置是蛇的头部。
如果把蛇的头部和身体都用一个定值来表示,则我们无法描述蛇的形状,也无从得知蛇头在哪里;所以我们不妨用8,2,4,6作为方向指针来描述蛇的身体,用-8,-2,-4,-6作为方向指针来描述蛇的头部。蛇的身体任何位置沿蛇的身体指向头部,蛇的头部指向蛇的身体,如果这段解释很难读懂,请看下面的例子:

例1:蛇头向右,长度为5的一条蛇,可以表示为:→→→→←即6 6 6 6 (-4)
例2:蛇头向右的一条蛇
→→→↓□□□→←
□□□→→→→↑
可以表示为:
6 6 6 2 0 0 0 6 (-4)
0 0 0 6 6 6 6 8

移动函数move():
我们很容易想到,蛇的移动可以通过“加头去尾”实现,即把蛇尾去掉,在蛇的移动方向加上新的蛇头。这个过程可以拆分成蛇头操作和蛇尾操作:
1)蛇头操作:先现在的蛇头,在移动后将成为蛇的身体;然后根据蛇的移动方向,生成一个新的蛇头:

int move() {//返回值:0-正常移动,1-撞墙,2-咬到自己//direction是描述蛇的移动方向的变量成员:8-↑,2-↓,4-←,6-→switch (direction) {int front;//判断蛇头前方有无障碍物的变量case 8://向上移动if (head[0]) {if ((front = map[head[0] - 1][head[1]]) > 0)return 2;//如果蛇头上方是蛇的身体,则咬到自己,返回2map[head[0]--][head[1]] = 8;//当前蛇头位置指向新蛇头位置(上)map[head[0]][head[1]] = -2;//新蛇头位置指向蛇身return 0;//正常移动,返回0}else return 1;//如果0==head[0]则撞墙,返回1case 2://向下移动if (head[0] < maxRow - 1) {if ((front = map[head[0] + 1][head[1]]) > 0)return 2;//如果蛇头下方是蛇的身体,则咬到自己,返回2map[head[0]++][head[1]] = 2;//当前蛇头位置指向新蛇头位置(下)map[head[0]][head[1]] = -8;//新蛇头位置指向蛇身return 0;//正常移动,返回0}else return 1;//如果maxRow-1==head[0]则撞墙,返回1case 4://向左移动if (head[1]) {if ((front = map[head[0]][head[1] - 1]) > 0)return 2;//如果蛇头左方是蛇的身体,则咬到自己,返回2map[head[0]][head[1]--] = 4;//当前蛇头位置指向新蛇头位置(左)map[head[0]][head[1]] = -6;//新蛇头位置指向蛇身return 0;//正常移动,返回0}else return 1;//如果0==head[1]则撞墙,返回1case 6://向右移动if (head[1] < maxCol - 1) {if ((front = map[head[0]][head[1] + 1]) > 0) return 2;//如果蛇头右方是蛇的身体,则咬到自己,返回2map[head[0]][head[1]++] = 6;//当前蛇头位置指向新蛇头位置(右)map[head[0]][head[1]] = -4;//新蛇头位置指向蛇身return 0;//正常移动,返回0}else return 1;//如果maxCol-1==head[0]则撞墙,返回1

2)蛇尾操作:由于蛇尾是沿蛇的身体指向蛇头的,所以只需要将蛇尾指向的位置设为新的蛇尾,我们将下面这段代码补充到move()函数中

switch (map[tail[0]][tail[1]]) {case 8:map[tail[0]--][tail[1]] = 0; break;//如果蛇尾指向上,则蛇尾横坐标-1case 2:map[tail[0]++][tail[1]] = 0; break;//如果蛇尾指向下,则蛇尾横坐标+1case 4:map[tail[0]][tail[1]--] = 0; break;//如果蛇尾指向左,则蛇尾纵坐标-1case 6:map[tail[0]][tail[1]++] = 0; break;//如果蛇尾指向上,则蛇尾纵坐标+1}

这样我们就完成了移动函数move()的定义,其他的函数相对简单,需要的读者可以继续往下看:

转弯函数turn():
需要注意的是,不是所有情况下都可以改变蛇的方向,比如蛇正在往右走,就不能把方向设置成左,也没必要把方向设置成右

//根据参数kbint来调整蛇的方向
void turn(int const&kbinput) {switch (kbinput) {case 8:if (4 == direction || 6 == direction)direction = 8; break;//如果蛇左右移动,则把方向设置成上case 2:if (4 == direction || 6 == direction)direction = 2; break;//如果蛇左右移动,则把方向设置成下case 4:if (8 == direction || 2 == direction)direction = 4; break;//如果蛇上下移动,则把方向设置成左case 6:if (8 == direction || 2 == direction)direction = 6; break;//如果蛇上下移动,则把方向设置成右}}

生成食物的函数create():
*食物是随机生成的,需要用到rand()函数,该函数在头文件或<stdlib.h>中,rand()函数的功能是返回一个0~RAND_MAX的随机值,RAND_MAX是一个很大的值,在本文中不做介绍,请读者自行查阅。
*需要注意的是,rand()函数返回的是一个假随机值,要得到相对真的随机值,需要设置随机数的种子为随机值,时间是随机的,所以我们用时间作为种子:

#include<cstdlib>
//将下面的代码放在游戏开始前
srand((unsigned)time(NULL));

设置了随机数的种子后,我们就可以使用随机数了:

void create() {int position[2];//食物的坐标do {position[0] = rand() % maxRow;//食物的行坐标为随机数除最大行数的余数,这样可以得到0到maxRow-1的一个随机数position[1] = rand() % maxCol;//食物的列坐标为随机数除最大列数的余数,这样可以得到0到maxCol-1的一个随机数} while (map[position[0]][position[1]]);//不能在蛇的身体上生成食物map[position[0]][position[1]] = -1;//按照我们的规定,在地图上把食物用-1表示}

完成了生成食物函数的书写,我们需要进一步完善移动函数move():
还记得move()函数的实现原理吗?“加头去尾”。那么吃到了食物后,我们希望蛇的长度增加,为了实现这个功能,应该"加头不去尾":

//在move()函数中加入条件判断语句,向上移动为例:
if (front < 0) { create(); length++; }//如果蛇头前方是食物,则食物会被吃掉->调用create()新生成一个食物,蛇的长度增加
//以下部分不变
else switch (map[tail[0]][tail[1]]) {
case 8:map[tail[0]--][tail[1]] = 0; break;
case 2:map[tail[0]++][tail[1]] = 0; break;
case 4:map[tail[0]][tail[1]--] = 0; break;
case 6:map[tail[0]][tail[1]++] = 0; break;
}

显示游戏地图的函数print()很简单,读者可以根据自己的喜好书写。

有了移动,转弯,生成食物和显示的函数,游戏的核心已经完备,下面我们在Snake类中添加一个GameStart()函数,用来集成这些函数,实现基本的游戏功能,不过在这之前我们先了解2个重要的函数:
*_getch()函数,和getchar()函数相似,不过_getch()函数可以直接读取键盘输入的字符,不用再敲击回车键,适合用来做控制台游戏。
*_kbhit()函数,如果有键盘输入,则返回一个非零值,否则返回零值。这个函数是非阻塞的,它不会暂停游戏的进程。我们希望不按键盘时蛇也会动,所以这个函数是必要的。
*以上2个函数在头文件<conio.h>中,这是一个非标准库。
用_getch()函数和_kbhit()函数完成基本游戏功能:

#include<conio.h>
public:void GameStart() {srand((unsigned)time(NULL));//设置随机数的种子while (true) {print();//显示地图//如果_kbhit()函数检测到键盘输入,则调用_getch()函数读取,否则游戏进程继续if (_kbhit())switch (_getch()) {case'w':case'W':turn(8); break;//如果输入w,则调用转弯函数turn(),参数为上case's':case'S':turn(2); break;//如果输入s,则调用转弯函数turn(),参数为下case'a':case'A':turn(4); break;//如果输入a,则调用转弯函数turn(),参数为左case'd':case'D':turn(6); break;//如果输入d,则调用转弯函数turn(),参数为右}if (move());//GameOver//如果move()函数的返回非零值,则游戏失败,游戏失败后怎么做请读者自行设计}}

有了游戏的基本框架,我们再来设计一些能丰富游戏性的功能:
我们希望蛇的长度增加时,游戏速度会加快,在设计这个功能之前,我们先了解Sleep()函数,知道CLOCK_PER_SEC的读者请跳过
Sleep()函数可以暂停游戏的进程,暂停的时间取决于参数,例如:

Sleep(1000);//休眠1000个单位时间,不是1000秒!

一般来说1秒有1000个单位时间,所以暂停几秒就Sleep几千。
在GameStart()函数中加入下面的代码,达到控制游戏速度的目的:

Sleep(1000/speed);//speed是蛇的速度

蛇的速度应该和蛇的长度相关,需要一定的计算公式,但是我们第一次编程时可能不知道多少合适,所以用宏来编写:

#define _SPEED(_LENGTH) _LENGTH-3//例如:蛇的速度=蛇的长度-3,速度公式宏读者可以自由改写
//将下面的代码加在create()函数末尾,因为生成了食物则蛇的长度一定发生了改变,则速度应该随之改变
speed=_SPEED(length);

到这里,简易的贪吃蛇游戏就写完了,最后附上完整代码:

//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
/*作者的话:
**游戏名称:OC贪吃蛇/OCSnake
**游戏版本:1.0
**游戏规则:WSAD控制光标,空格暂停,ENTER确定,ESC退出
*/
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
#include<iostream>
#include<string>
#include<Windows.h>
#include<ctime>
#include<conio.h>
using namespace std;
#define _SPEED(_LENGTH) _LENGTH>6?_LENGTH:6//蛇的速度
#define _SCORE(_LENGTH) _LENGTH//游戏得分
//贪吃蛇
class Snake {
public://默认构造函数Snake() :length(3), direction(6), speed(3), maxRow(10), maxCol(15), initLength(3) {map = new signed char*[maxRow];int count;for (count = 0; count < maxRow; count++) {map[count] = new signed char[maxCol];memset(map[count], 0, maxCol);}head[0] = 0; head[1] = 2;tail[0] = 0; tail[1] = 0;for (count = 0; count < 2; count++)map[0][count] = 6;map[0][count] = -4;system("title OCSnake");system(string("mode con cols=" + to_string(2 * maxCol + 4) + " lines=" + to_string(maxRow + 2)).c_str());create();}//构造函数:MRow>=8,MCol>=10Snake(int const&MRow, int const&MCol, int const&init_length = 3) :direction(6), maxRow(MRow), maxCol(MCol), initLength(init_length) {length = initLength;map = new signed char*[maxRow];int count;for (count = 0; count < maxRow; count++) {map[count] = new signed char[maxCol];memset(map[count], 0, maxCol);}head[0] = 0; head[1] = initLength - 1;tail[0] = 0; tail[1] = 0;for (count = 0; count < initLength - 1; count++)map[0][count] = 6;map[0][count] = -4;system("title OCSnake");system(string("mode con cols=" + to_string(2 * maxCol + 4) + " lines=" + to_string(maxRow + 2)).c_str());create();}//游戏开始void GameStart() {srand((unsigned)time(NULL));LABEL_MAIN_WINDOW://主窗口标签if (MainWindow())if (QuitOrNot())goto LABEL_MAIN_WINDOW;else exit(0);else if (ChooseMode())goto LABEL_MAIN_WINDOW;Sleep(CLOCKS_PER_SEC);char pause_before_continue = 0;while (true) {print();if (pause_before_continue) { Sleep(CLOCKS_PER_SEC); pause_before_continue = 0; }if (_kbhit())switch (_getch()) {case'w':case'W':turn(8); break;case's':case'S':turn(2); break;case'a':case'A':turn(4); break;case'd':case'D':turn(6); break;case 27:case 32: LABEL_PAUSE_WINDOW://暂停窗口if (0 == pause()) {if (0 == ReturnToMainWindow())goto LABEL_MAIN_WINDOW; else goto LABEL_PAUSE_WINDOW;}pause_before_continue = 1;break;}if (move()) { Sleep(CLOCKS_PER_SEC); score(); goto LABEL_MAIN_WINDOW; }Sleep(CLOCKS_PER_SEC / speed);}}//析构函数~Snake() {int count;for (count = 0; count < maxCol; count++)delete[]map[count];delete[]map;}
private:signed char**map;//地图int length;//蛇的长度int head[2];//蛇头坐标int tail[2];//蛇尾坐标char direction;//移动方向:8-↑,2-↓,4-←,6-→char speed;//蛇的速度const char maxRow;//地图最大行数const char maxCol;//地图最大列数const char initLength;//初始蛇长char mode;//游戏模式:0-正常模式,1-无障碍模式//打印void print()const {int i, j; signed char judge;for (i = 0; i < maxCol + 2; i++)cout << "□";cout << endl;for (i = 0; i < maxRow; i++) {cout << "□";for (j = 0; j < maxCol; j++) {judge = map[i][j];if (0 == judge)cout << "  ";else if (judge > 0)cout << "■";else if (-1 == judge)cout << "◇";else cout << "¤";}cout << "□" << endl;}for (i = 0; i < maxCol + 2; i++)cout << "□";}//移动:0-正常移动,1-撞墙,2-咬到自己int move() {int front;if (0 == mode) {switch (direction) {case 8:if (head[0]) {if ((front = map[head[0] - 1][head[1]]) > 0)return 2;map[head[0]--][head[1]] = 8;map[head[0]][head[1]] = -2;if (front < 0) { create(); length++; }else switch (map[tail[0]][tail[1]]) {case 8:map[tail[0]--][tail[1]] = 0; break;case 2:map[tail[0]++][tail[1]] = 0; break;case 4:map[tail[0]][tail[1]--] = 0; break;case 6:map[tail[0]][tail[1]++] = 0; break;}return 0;}else return 1;case 2:if (head[0] < maxRow - 1) {if ((front = map[head[0] + 1][head[1]]) > 0)return 2;map[head[0]++][head[1]] = 2;map[head[0]][head[1]] = -8;if (front < 0) { create(); length++; }else switch (map[tail[0]][tail[1]]) {case 8:map[tail[0]--][tail[1]] = 0; break;case 2:map[tail[0]++][tail[1]] = 0; break;case 4:map[tail[0]][tail[1]--] = 0; break;case 6:map[tail[0]][tail[1]++] = 0; break;}return 0;}else return 1;case 4:if (head[1]) {if ((front = map[head[0]][head[1] - 1]) > 0)return 2;map[head[0]][head[1]--] = 4;map[head[0]][head[1]] = -6;if (front < 0) { create(); length++; }else switch (map[tail[0]][tail[1]]) {case 8:map[tail[0]--][tail[1]] = 0; break;case 2:map[tail[0]++][tail[1]] = 0; break;case 4:map[tail[0]][tail[1]--] = 0; break;case 6:map[tail[0]][tail[1]++] = 0; break;}return 0;}else return 1;case 6:if (head[1] < maxCol - 1) {if ((front = map[head[0]][head[1] + 1]) > 0) return 2;map[head[0]][head[1]++] = 6;map[head[0]][head[1]] = -4;if (front < 0) { create(); length++; }else switch (map[tail[0]][tail[1]]) {case 8:map[tail[0]--][tail[1]] = 0; break;case 2:map[tail[0]++][tail[1]] = 0; break;case 4:map[tail[0]][tail[1]--] = 0; break;case 6:map[tail[0]][tail[1]++] = 0; break;}return 0;}else return 1;default:return -1;}}else {char judge;switch (direction) {case 8:if (head[0]) {if ((front = map[head[0] - 1][head[1]]) > 0)return 2;map[head[0]--][head[1]] = 8;map[head[0]][head[1]] = -2;}else {if ((front = map[maxRow - 1][head[1]]) > 0)return 2;map[head[0]][head[1]] = 8; head[0] = maxRow - 1;map[head[0]][head[1]] = -2;}if (front < 0) { create(); length++; }else {judge = map[tail[0]][tail[1]]; map[tail[0]][tail[1]] = 0;switch (judge) {case 8: if (tail[0])tail[0]--; else tail[0] = maxRow - 1; break;case 2: if (tail[0] < maxRow - 1)tail[0]++; else tail[0] = 0; break;case 4: if (tail[1])tail[1]--; else tail[1] = maxCol - 1; break;case 6:if (tail[1] < maxCol - 1)tail[1]++; else tail[1] = 0; break;}}return 0;case 2:if (head[0] < maxRow - 1) {if ((front = map[head[0] + 1][head[1]]) > 0)return 2;map[head[0]++][head[1]] = 2;map[head[0]][head[1]] = -8;}else {if ((front = map[0][head[1]]) > 0)return 2;map[head[0]][head[1]] = 2; head[0] = 0;map[head[0]][head[1]] = -8;}if (front < 0) { create(); length++; }else {judge = map[tail[0]][tail[1]]; map[tail[0]][tail[1]] = 0;switch (judge) {case 8: if (tail[0])tail[0]--; else tail[0] = maxRow - 1; break;case 2: if (tail[0] < maxRow - 1)tail[0]++; else tail[0] = 0; break;case 4: if (tail[1])tail[1]--; else tail[1] = maxCol - 1; break;case 6:if (tail[1] < maxCol - 1)tail[1]++; else tail[1] = 0; break;}}return 0;case 4:if (head[1]) {if ((front = map[head[0]][head[1] - 1]) > 0)return 2;map[head[0]][head[1]--] = 4;map[head[0]][head[1]] = -6;}else {if ((front = map[head[0]][maxCol - 1]) > 0)return 2;map[head[0]][head[1]] = 4; head[1] = maxCol - 1;map[head[0]][head[1]] = -6;}if (front < 0) { create(); length++; }else {judge = map[tail[0]][tail[1]]; map[tail[0]][tail[1]] = 0;switch (judge) {case 8: if (tail[0])tail[0]--; else tail[0] = maxRow - 1; break;case 2: if (tail[0] < maxRow - 1)tail[0]++; else tail[0] = 0; break;case 4: if (tail[1])tail[1]--; else tail[1] = maxCol - 1; break;case 6:if (tail[1] < maxCol - 1)tail[1]++; else tail[1] = 0; break;}}return 0;case 6:if (head[1] < maxCol - 1) {if ((front = map[head[0]][head[1] + 1]) > 0) return 2;map[head[0]][head[1]++] = 6;map[head[0]][head[1]] = -4;}else {if ((front = map[head[0]][0]) > 0) return 2;map[head[0]][head[1]] = 6; head[1] = 0;map[head[0]][head[1]] = -4;}if (front < 0) { create(); length++; }else {judge = map[tail[0]][tail[1]]; map[tail[0]][tail[1]] = 0;switch (judge) {case 8: if (tail[0])tail[0]--; else tail[0] = maxRow - 1; break;case 2: if (tail[0] < maxRow - 1)tail[0]++; else tail[0] = 0; break;case 4: if (tail[1])tail[1]--; else tail[1] = maxCol - 1; break;case 6:if (tail[1] < maxCol - 1)tail[1]++; else tail[1] = 0; break;}}return 0;default:return -1;}}}//转弯void turn(int const&kbinput) {switch (kbinput) {case 8:if (4 == direction || 6 == direction)direction = 8; break;case 2:if (4 == direction || 6 == direction)direction = 2; break;case 4:if (8 == direction || 2 == direction)direction = 4; break;case 6:if (8 == direction || 2 == direction)direction = 6; break;}}//生成食物void create() {int position[2];do {position[0] = rand() % maxRow;position[1] = rand() % maxCol;} while (map[position[0]][position[1]]);map[position[0]][position[1]] = -1;speed = _SPEED(length);}//暂停游戏:0-返回主界面,1-继续游戏int pause() {int i, j; signed char judge;for (i = 0; i < maxCol + 2; i++)cout << "□";cout << endl;for (i = 0; i < maxRow / 2 - 3; i++) {cout << "□";for (j = 0; j < maxCol; j++)cout << "  ";cout << "□" << endl;}cout << "□"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "◣    "; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "□" << endl;cout << "□"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "■◣  "; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "□" << endl;cout << "□"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "■■◣"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "□" << endl;cout << "□"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "■■◤"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "□" << endl;cout << "□"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "■◤  "; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "□" << endl;cout << "□"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "◤    "; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "□" << endl;for (; i < maxRow - 6; i++) {cout << "□";for (j = 0; j < maxCol; j++)cout << "  ";cout << "□" << endl;}for (i = 0; i < maxCol + 2; i++)cout << "□";judge = _getch();while (judge != 27 && judge != 32)judge = _getch();return 27 == judge ? 0 : 1;}//主界面:0-开始,1-退出int MainWindow() {system("cls");char cursor = 0, position = 0;do {unsigned short i, j;for (i = 0; i < maxCol + 2; i++)cout << "■";cout << endl;for (i = 0; i < maxRow / 2 - 1; i++) {cout << "■";for (j = 0; j < maxCol; j++)cout << "  ";cout << "■" << endl;}cout << "■"; for (j = 0; j < maxCol - 8; j++)cout << ' '; cout << "OC贪吃蛇/OCSnake"; for (j = 0; j < maxCol - 8; j++)cout << ' '; cout << "■" << endl;cout << "■"; for (j = 0; j < maxCol - 4; j++)cout << ' '; cout << "开始游戏"; if (0 == position)cout << "←"; for (j = 2 - 2 * position; j < maxCol - 4; j++)cout << ' '; cout << "■" << endl;cout << "■"; for (j = 0; j < maxCol - 4; j++)cout << ' '; cout << "退出游戏";if (position)cout << "←";  for (j = 2 * position; j < maxCol - 4; j++)cout << ' '; cout << "■" << endl;for (; i < maxRow - 3; i++) {cout << "■";for (j = 0; j < maxCol; j++)cout << "  ";cout << "■" << endl;}for (i = 0; i < maxCol + 2; i++)cout << "■";cursor = _getch();if (('w' == cursor || 'W' == cursor) && position)position--;else if (('s' == cursor || 'S' == cursor) && 0 == position)position++;else if (27 == cursor)return 1;} while (cursor != '\r');return position;}//退出确认窗口:0-是,1-否int QuitOrNot() {char cursor = 0, position = 0;do {unsigned short i, j;for (i = 0; i < maxCol + 2; i++)cout << "■";cout << endl;for (i = 0; i < maxRow / 2 - 1; i++) {cout << "■";for (j = 0; j < maxCol; j++)cout << "  ";cout << "■" << endl;}cout << "■"; for (j = 0; j < maxCol - 6; j++)cout << ' '; cout << "要结束游戏吗"; for (j = 0; j < maxCol - 6; j++)cout << ' '; cout << "■" << endl;cout << "■"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "是  否"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "■" << endl;if (0 == position) { cout << "■"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "↑"; for (j = 0; j < maxCol + 1; j++)cout << ' '; cout << "■" << endl; }else { cout << "■"; for (j = 0; j < maxCol + 1; j++)cout << ' '; cout << "↑"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "■" << endl; }for (; i < maxRow - 3; i++) {cout << "■";for (j = 0; j < maxCol; j++)cout << "  ";cout << "■" << endl;}for (i = 0; i < maxCol + 2; i++)cout << "■";cursor = _getch();if (('a' == cursor || 'A' == cursor) && position)position--;else if (('d' == cursor || 'D' == cursor) && 0 == position)position++;else if (27 == cursor)return 1;} while (cursor != '\r');return position;}//返回主菜单:0-是,1-否int ReturnToMainWindow() {char cursor = 0, position = 0;do {unsigned short i, j;for (i = 0; i < maxCol + 2; i++)cout << "■";cout << endl;for (i = 0; i < maxRow / 2 - 1; i++) {cout << "■";for (j = 0; j < maxCol; j++)cout << "  ";cout << "■" << endl;}cout << "■"; for (j = 0; j < maxCol - 7; j++)cout << ' '; cout << "要返回主菜单吗"; for (j = 0; j < maxCol - 7; j++)cout << ' '; cout << "■" << endl;cout << "■"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "是  否"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "■" << endl;if (0 == position) { cout << "■"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "↑"; for (j = 0; j < maxCol + 1; j++)cout << ' '; cout << "■" << endl; }else { cout << "■"; for (j = 0; j < maxCol + 1; j++)cout << ' '; cout << "↑"; for (j = 0; j < maxCol - 3; j++)cout << ' '; cout << "■" << endl; }for (; i < maxRow - 3; i++) {cout << "■";for (j = 0; j < maxCol; j++)cout << "  ";cout << "■" << endl;}for (i = 0; i < maxCol + 2; i++)cout << "■";cursor = _getch();if (('a' == cursor || 'A' == cursor) && position)position--;else if (('d' == cursor || 'D' == cursor) && 0 == position)position++;else if (27 == cursor)return 1;} while (cursor != '\r');return position;}//结算界面void score() {int count; signed char judge;system("cls");for (count = 0; count < maxCol/2-2; count++)cout << endl;for (count = 0; count < maxCol - 2; count++)cout << ' '; cout << "游戏结束" << endl;for (count = 0; count < maxCol - 6; count++)cout << ' '; cout << "你的最终得分为:" << _SCORE(length - initLength);for (count = 0; count < maxRow; count++) {map[count] = new signed char[maxCol];memset(map[count], 0, maxCol);}head[0] = 0; head[1] = initLength - 1;tail[0] = 0; tail[1] = 0;for (count = 0; count < initLength - 1; count++)map[0][count] = 6;map[0][count] = -4;direction = 6; length = initLength; create();judge = _getch();while (judge != 27 && judge != '\r')judge = _getch();}//模式选择窗口:0-开始游戏,1-返回主菜单int ChooseMode() {char cursor = 0, position = 0;do {unsigned short i, j;for (i = 0; i < maxCol + 2; i++)cout << "■";cout << endl;for (i = 0; i < maxRow / 2 - 1; i++) {cout << "■";for (j = 0; j < maxCol; j++)cout << "  ";cout << "■" << endl;}cout << "■"; for (j = 0; j < maxCol - 7; j++)cout << ' '; cout << "请选择游戏模式"; for (j = 0; j < maxCol - 7; j++)cout << ' '; cout << "■" << endl;cout << "■"; for (j = 0; j < maxCol - 6; j++)cout << ' '; cout << "正常  无障碍"; for (j = 0; j < maxCol - 6; j++)cout << ' '; cout << "■" << endl;if (0 == position) { cout << "■"; for (j = 0; j < maxCol - 5; j++)cout << ' '; cout << "↑"; for (j = 0; j < maxCol + 3; j++)cout << ' '; cout << "■" << endl; }else { cout << "■"; for (j = 0; j < maxCol + 2; j++)cout << ' '; cout << "↑"; for (j = 0; j < maxCol - 4; j++)cout << ' '; cout << "■" << endl; }for (; i < maxRow - 3; i++) {cout << "■";for (j = 0; j < maxCol; j++)cout << "  ";cout << "■" << endl;}for (i = 0; i < maxCol + 2; i++)cout << "■";cursor = _getch();if (('a' == cursor || 'A' == cursor) && position)position--;else if (('d' == cursor || 'D' == cursor) && 0 == position)position++;else if (27 == cursor)return 1;} while (cursor != '\r');mode = position;return 0;}
};
int main() {Snake OCSnake;OCSnake.GameStart();return 0;
}

有需要的话会再写一个无障碍模式的教程,觉得我说得不明白的话请在评论区批评指正,总之希望能帮到读者,感谢阅读!

贪吃蛇详细教程-C++实现相关推荐

  1. Java GUI 贪吃蛇项目教程,详细教程,思路解析,+图片素材。

    一.实现效果 1.空格暂停, 2.上下左右控制方向 3.长度会随着食物的吃下而增加 4.定时刷新 5.累计长度和分数等等. 具体视频演示效果和教程点击跳转 二.实现思路: 1.定义所一个功能的数据 2 ...

  2. hydra九头蛇详细教程(5分钟内快速学会)

    hydra详细教程(本文的目的是使小白能一眼看懂,在5分钟之内能够直接使用hydra,在实验中更好的学习,进行大多数的破解) hydra工具介绍 hydra又名九头蛇,是一款爆破神器. 支持linux ...

  3. C#小游戏——贪吃蛇~详细过程+全部代码

    一个好玩的

  4. 贪吃蛇大作战代码java,贪吃蛇游戏,贪吃蛇java游戏代码讲解

    贪吃蛇游戏,贪吃蛇java游戏代码讲解 来源:互联网 作者:佚名 时间:2020-06-06 贪吃蛇源代码.txt这世界上除了我谁都没资格陪在你身边. 听着,我允许你喜欢我.除了白头偕老,我们... ...

  5. c语言写贪吃蛇什么水平_细致的C语言写贪吃蛇教程+详细思路-适合新手附源码...

    #史上最详细的C语言贪吃蛇教程 #前言 在有用C写贪吃蛇的一个想法之后,上网查了几个教程,觉得不是很能看懂.恩...或者说不是一下子就能看出来思路+具体怎么实现.所以,我花了早自习的时间想了想如何用最 ...

  6. 10分钟教你用python打造贪吃蛇超详细教程

    更多精彩尽在微信公众号[程序猿声] 10分钟教你用python打造贪吃蛇超详细教程 在家闲着没妹子约, 刚好最近又学了一下python,听说pygame挺好玩的.今天就在家研究一下, 弄了个贪吃蛇出来 ...

  7. c++贪吃蛇_细致的C语言写贪吃蛇教程+详细思路-适合新手附源码

    在有用C写贪吃蛇的一个想法之后,上网查了几个教程,觉得不是很能看懂.恩...或者说不是一下子就能看出来思路+具体怎么实现.所以,我花了早自习的时间想了想如何用最简单的方法实现,晚上大约两个小时写了出来 ...

  8. TypeScript 贪吃蛇游戏详细教程

    一.项目搭建 二.编写游戏界面 三.编写食物模块 四.初步编写蛇模块 五.编写计分盘模块 六.游戏控制模块的开发 前几篇博文学习了TypeScript的语法以及TypeScript的工程化实现方案,但 ...

  9. C++控制台贪吃蛇小游戏详细教程

    游戏截图     开始动画:    游戏过程:  游戏架构设计 该游戏的玩法简单,玩家通过键盘方向键控制蛇上下左右移动,吃到食物得分并增长,碰到墙或者自己的身体则死亡,游戏结束.  整个游戏其实就是一 ...

最新文章

  1. Python高级特性:切片、迭代、列表生成式、生成器与迭代器
  2. 浅析强化学习及使用Policy Network实现自动化控制
  3. 131. 分割回文串(回溯算法)
  4. nginx的模块开发
  5. MySQL索引机制:索引分类、索引的实现原理、索引的优化 - 公开课笔记
  6. 使用JDBCTemplate实现与Spring结合,方法公用 ——Spring配置(applicationContext.xml)
  7. 我的第一个项目----Java图书管理系统
  8. python工程师工资多少-2018年涨工资了吗?Python 工程师薪资最新出炉
  9. jsp和html的作用域,JSP(二):JSP九大内置对象、四个作用域对象
  10. Lightroom Classic 教程,如何在 Lightroom 中使用调整画笔?
  11. 1030: [JSOI2007]文本生成器
  12. 黑客郭盛华虚假新闻_每日新闻摘要:黑客闯入十个电信网络
  13. 给公司、领导提提意见,该怎么写?
  14. CLAHE算法代码详解
  15. java打雪仗,linux jdk安装--转载
  16. 计算机相关检测手段,计算机硬件测试的三种方法
  17. 虽说中国是礼仪之邦,但是这个礼看来还是没有几个人学透
  18. Java Obiect类--------11
  19. artisan命令大全
  20. KMP算法——很详细的讲解

热门文章

  1. mysql的时间戳_MySQL时间戳(Timestamp)函数
  2. 亚马逊开奖!应届生总包50w+
  3. 为什么《你画我猜》如此短命,该如何改进?
  4. 如何准备Google软件工程师面试?
  5. 1.JVM与Java体系结构
  6. Android Retrofit处理Token过期的问题
  7. 从YouTube算法论文反推其推荐机制
  8. opencv GrabCut 图像分割
  9. Android中查看详细的错误信息的方法
  10. 来自AI+光学技术的创新|如何用眼镜让色盲患者重新看到世界的色彩?