一、思路:
二、前期准备:
1、鉴于是在做游戏,则需要不同的页面:
system("cls");
(1)、此代码意为:clean screen 即 “ 清空屏幕 ” ,以便进入下一画面的描述。
2、画面的输出不可能完全按照顺序,即 “ 从左至右,从上到下 ” 输出,因此需要控制台光标移至指定位置:
void gotoxy(int x,int y){
COORD c;
c.X = x;
c.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);
}
Ps :
① set console cursor position 意为 设置控制台光标位置;
②get std handle 意为 获取标准句柄;
③std 意为 标准的 ,即 “ standard ”
④coord 意为 坐标 ,即 coordinate
(1)、该 gotoxy()函数需要自己声明定义,而 COORD结构 与 SetConsoleCursorPosition() 函数与GetStdHandle() 函数与 STD_OUTPUT_HANDLE 常量不需要自己声明定义,他们位于<windows.h>中;
(2)、该gotoxy()函数实现了对光标的任意移动;GetStdHandle()函数的返回值为 HANDLE类型。
3、鉴于游戏体验,不需要光标显示:
void CursorOut(){
CONSOLE_CURSOR_INFO cinfo;
cinfo.bVisible = 0;
cinfo.dwSize = 1;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cinfo);
}
(1)、CursorOut 函数直接使用则可消去光标;其他函数、常量、结构体均位于<windows.h>中。
三、游戏设计:
1、设置蛇盘(二维数组),并设计蛇头的x,y坐标,并设计蛇的长度,并设计方向指令:
#define mapxsize 40
#define mapysize 20
int map[mapxsize][mapysize]={0};
int headx,heady,lenth;
char mem_order;
(1)、为方便,上述变量声明为全局变量。
2、初始化蛇盘与方向指令:
void init(){
for (int i=0;i<mapxsize;i++){
for (int j=0;j<mapysize;j++){
map[i][j] = 0;
}
}
map[1][1] = 2;
map[2][1] = 1;
headx=2;heady=1;lenth=2;
map[5][10] = -1;
mem_order = 'D';
}
(1)、首先初始化蛇盘所有数值为0;此处在声明蛇盘时可一键初始化,即 = {0} ,但为什么当时并没有初始化,而在此处通过遍历初始化呢?这是因为游戏结束之后重开下一把仍需初始化,而在声明时初始化达不到此效果;
(2)、蛇身为大于零的自然数,且蛇头为1,随蛇尾方向,自然数增加;食物处赋值自然数为-1 ;
(3)、方向使用字符型 “WASD” 或 “wasd” 表示蛇头的移动;
(4)、此外,需要初始化蛇长度,蛇头坐标,以及蛇头移动方向。
3、键盘输入指令(可跳过):
if(kbhit()) mem_order = getch();
switch (mem_order) {
case 'W':case 'w': heady -= 1;break;
case 'A':case 'a': headx -= 1;break;
case 'S':case 's': heady += 1;break;
case 'D':case 'd': headx += 1;break;
}
(1)、kyhit() 函数,即 “KeyBoardHit” 若键盘已敲打则返回非0的数值,未敲打返回0,此函数头在<conio.h>中,意为 “ console input output ”;
(2)、getch() 函数的独特之处在于控制台不显示任何字符,但输入字符实际已进入缓冲区;
(3)、使用 switch 命令,快捷地更新蛇头坐标。
4、根据指令操控蛇盘:
int dispose(){
int ret = 1;
if (map[headx][heady]>0||headx==0||headx==mapxsize||heady==0||heady==mapysize) {
ret = 0;
} else if (map[headx][heady]==-1){
for (int i=1;i<mapxsize-1;i++){
for (int j=1;j<mapysize-1;j++){
if (map[i][j]>0) map[i][j]++;
}
}
map[headx][heady] = 1;
lenth++;
freshfood();
}else{
for (int i=1;i<mapxsize-1;i++){
for (int j=1;j<mapysize-1;j++){
if (map[i][j] == lenth) {
map[i][j] = 0;
}
else if (map[i][j]>=1) {
map[i][j]+=1;
}
}
}
map[headx][heady] = 1;
}
return ret;
}
(1)、该处理函数为int型,若蛇撞死返回0,未撞死返回1;
(2)、主体部分分为蛇头到达食物处 以及 蛇头未到达食物处两种情况:
①、蛇头到达食物处:
(①)、蛇身各处增加1,食物处赋值为1,即蛇头;
(②)、蛇身长度增加1;
(③)、更新食物位置。
②、蛇头未到达食物处:
(①)、蛇头新位置更新为1,其余位置(处蛇尾外)增加1;
(②)、蛇尾更新为0。
5、输出蛇盘:
void draw(){
for (int i=1;i<mapysize-1;i++){
gotoxy(1,i);
for (int j=1;j<mapxsize-1;j++){
cout << " ";
}
}
for (int i=1;i<mapxsize-1;i++){
for (int j=1;j<mapysize-1;j++){
gotoxy(i,j);
if (map[i][j] == 0) cout << " ";
else if (map[i][j] == 1) cout << "@";
else cout << "*";
}
}
}
(1)、首先清理蛇盘,即各处输出空格;
(2)、游戏边框在游戏开始时已经输出完毕,此处不赘余输出,也防止边框闪烁;
(3)、头用 “@” ,蛇身和食物使用 “ * ”。
Ps:
①、
system("title 游戏开始");
(①)、该命令可以使得控制台标题改变;
②、
Sleep(1500);
(①)、该命令行可以使得控制台暂停1500毫秒;
(②)、通过该命令可以控制蛇的移速;
(③)、freshfood() 函数可以利用时间随机数设计,不在此赘述。
废话到此位置,感谢各位神犇斧正,全代码奉上:
#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <time.h>
#define mapxsize 40
#define mapysize 20
int map[mapxsize][mapysize]={0};
int headx,heady,lenth;
char mem_order;
using namespace std;
void gotoxy();
void homepage();
void explaination();
void gamepage();
void draw();
void init();
void freshfood();
void GameBackGround();
void CursorOut();
int dispose();
int main(){
system("title 贪吃蛇 by高");
CursorOut();
homepage();
return 0;
}
void gotoxy(int x,int y){
COORD c;
c.X = x;
c.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);
}
void homepage(){
system("cls");
gotoxy(20,5);
for (int i=0;i<=16;i++){
cout << "_";
}
gotoxy(20,12);
for (int i=0;i<=16;i++){
cout << "_";
}
for (int i=6;i<=12;i++) {
gotoxy(19,i);
cout << "|";
gotoxy(37,i);
cout << "|";
}
gotoxy(21,7);
cout << "1 . 开 始 游 戏 ";
gotoxy(21,10);
cout << "2 . 游 戏 说 明 ";
gotoxy(20,15);
cout << "请 选 择 1/2 : [ ]\b\b";
int order;
cin >> order;
switch (order) {
case 1:
gamepage();
break;
case 2:
explaination();
break;
default:
gotoxy(41,15);
cout << "无效输入,请重新输入";
Sleep(1500);
homepage();
}
}
void explaination(){
system("cls");
gotoxy(20,5);
for (int i=0;i<=16;i++){
cout << "__";
}
gotoxy(20,12);
for (int i=0;i<=16;i++){
cout << "__";
}
for (int i=6;i<=12;i++) {
gotoxy(19,i);
cout << "|";
gotoxy(53,i);
cout << "|";
}
gotoxy(21,7);
cout << "1 . 蛇头撞到墙壁或蛇身死亡";
gotoxy(21,10);
cout << "2 . 请使用WASD键盘操作蛇头的移动";
gotoxy(20,15);
cout << "敲击键盘任何键可返回主页";
char temp;
temp = getch();
homepage();
}
void draw(){
for (int i=1;i<mapysize-1;i++){
gotoxy(1,i);
for (int j=1;j<mapxsize-1;j++){
cout << " ";
}
}
for (int i=1;i<mapxsize-1;i++){
for (int j=1;j<mapysize-1;j++){
gotoxy(i,j);
if (map[i][j] == 0) cout << " ";
else if (map[i][j] == 1) cout << "@";
else cout << "*";
}
}
}
void gamepage(){
system("title 游戏开始");
GameBackGround();
init();
draw();
while (1){
Sleep(200);
if(kbhit()) mem_order = getch();
switch (mem_order) {
case 'W':case 'w': heady -= 1;break;
case 'A':case 'a': headx -= 1;break;
case 'S':case 's': heady += 1;break;
case 'D':case 'd': headx += 1;break;
}
int ret = dispose();
if (ret) {
draw();
} else {
cout << "游戏结束,按任意键 返回主页";
char temp;
temp = getch();
break;
}
}
homepage();
}
void init(){
for (int i=0;i<mapxsize;i++){
for (int j=0;j<mapysize;j++){
map[i][j] = 0;
}
}
map[1][1] = 2;
map[2][1] = 1;
headx=2;heady=1;lenth=2;
map[5][10] = -1;
mem_order = 'D';
}
int dispose(){
int ret = 1;
if (map[headx][heady]>0||headx==0||headx==mapxsize||heady==0||heady==mapysize) {
ret = 0;
} else if (map[headx][heady]==-1){
for (int i=1;i<mapxsize-1;i++){
for (int j=1;j<mapysize-1;j++){
if (map[i][j]>0) map[i][j]++;
}
}
map[headx][heady] = 1;
lenth++;
freshfood();
}else{
for (int i=1;i<mapxsize-1;i++){
for (int j=1;j<mapysize-1;j++){
if (map[i][j] == lenth) {
map[i][j] = 0;
}
else if (map[i][j]>=1) {
map[i][j]+=1;
}
}
}
map[headx][heady] = 1;
}
return ret;
}
void freshfood(){
srand(time(NULL));
int x = rand()%(mapxsize-1);
int y = rand()%(mapysize-1);
if (x==0) x+=1;
if (x==mapxsize-1) x-=1;
if (y==0) y+=1;
if (y==mapysize-1) y-=1;
map[x][y] = -1;
}
void GameBackGround(){
for (int i=0;i<mapxsize;i++){
for (int j=0;j<mapysize;j++){
gotoxy(i,j);
if (i==0 || i==mapxsize-1 || j==0 || j==mapysize-1) cout << "#";
}
}
}
void CursorOut(){
CONSOLE_CURSOR_INFO cinfo;
cinfo.bVisible = 0;
cinfo.dwSize = 1;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cinfo);
}