游戏循环控制
游戏循环结束后,让循环能够重新开始。
目前游戏循环用的bool变量gameover,现在需要创建一个变量gameQuit标记程序是否退出,想让游戏循环结束后能够重启必须在原来循环的外面再套一个循环,用do-while做外循环,游戏循环结束后不会马上退出程序
接下来看如何对游戏结束后状态进行控制,这里引入一个控制按键的while循环
运行下来的效果
似乎出问题了,在结束游戏这里打个断点,游戏开始时怎么蛇身长度不是0,说明初始化的工作没有做好
用initial函数做一下参数的初始化
为什么游戏重新开始后背景怪怪的
检查一下之前调用gameOver_info()函数时 没有把字体属性还原,现重新书写一下
预留一个问题,游戏进行过程中如何暂停游戏,如何恢复暂停的游戏进程?
代码维护与管理
比如希望游戏的整体界面能够往屏幕右下方方向偏移若干位置,比如对某个游戏窗口进行大小变化如果逐行代码去阅读然后修改,工作量会很大,所以为了工作便利,对代码中的参数做规范处理,此处采用宏定义的方式对后续可能要修改的参数做一个宏定义,这样做的好处是后面要修改参数,直接在文件头部修改就行,不用去代码堆中寻找数值。
未用宏定义
用了宏定义
#include <iostream>
#include <windows.h>
#include <conio.h>
#define STAGE_WIDTH 20
#define STAGE_HEIGHT 20
#define WINDOW_WIDTH 80
#define WINDOW_HEIGHT 25
#define CORNER_X 1
#define CORNER_Y 1
#define THICHKNESS 1
#define MAXLENGTH 100
#define COLOR_WALL 0X06
#define COLOR_TEXT 0X0F
#define COLOR_TEXT2 0XEC
#define COLOR_SCORE 0X0C
#define COLOR_FRUIT 0X04
#define COLOR_SNAKE_HEAD 0X09
#define COLOR_SHAKE_BODY 0X0A
using namespace std;
bool gameOver, fruitFlash; //判断游戏是否结束
const int width = STAGE_WIDTH;
const int height = STAGE_HEIGHT;
int x, y, fruitX, fruitY, score;
int tailX[MAXLENGTH], tailY[MAXLENGTH];
int nTail = 1;
enum eDirection { STOP = 0, LEFT, RIGHT, UP, DOWN };
eDirection dir;
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
void Initial()
{
SetConsoleTitleA("Console_贪吃蛇");
COORD dSize = { WINDOW_WIDTH,WINDOW_HEIGHT };
SetConsoleScreenBufferSize(h, dSize);
CONSOLE_CURSOR_INFO _cursor = { 1,false };
gameOver = false;
fruitFlash = false;
dir = STOP;
x = width / 2;
y = height / 2;
fruitX = rand() % width;
fruitY = rand() % height;
score = 0;
nTail = 1;
for (int i=0;i<MAXLENGTH;i++)
{
tailX[i] = 0;
tailY[i] = 0;
}
}
//光标位置
void setPos(int X, int Y)
{
COORD pos;
pos.X = CORNER_X + X +THICHKNESS; //pos.X=X+1
pos.Y = CORNER_X + Y + THICHKNESS; //pos.Y = Y + 1;
SetConsoleCursorPosition(h, pos); //设置控制台上光标的位置
}
void DrawMap()
{
system("cls");
int textColor = COLOR_WALL;
SetConsoleTextAttribute(h, textColor);
setPos(-THICHKNESS, -THICHKNESS);//绘制顶部的墙
for (int i = 0; i < width + THICHKNESS * 2; i++)
cout << "#";
\
for (int i = 0; i < height; i++)
{
setPos(-THICHKNESS, i);//绘制左右的墙
for (int j = 0; j < width + THICHKNESS * 2; j++)
{
if (j == 0)
cout << "#";
else if (j == width + THICHKNESS)
cout << "#";
else
cout << " ";
}
cout << endl;
}
setPos(-THICHKNESS, STAGE_HEIGHT);//绘制下方的墙
for (int i = 0; i < width + THICHKNESS * 2; i++)
cout << "#";
/*cout << endl;
cout << "游戏得分" << score << endl;*/
}
void eraseSnake()
{
for (int i = 0; i < nTail; i++)
{
setPos(tailX[i], tailY[i]);
cout << " ";
}
}
void DrawLocally()
{
if (!fruitFlash)
{
setPos(fruitX, fruitY);
SetConsoleTextAttribute(h, COLOR_FRUIT);
cout << "F";
fruitFlash = true;
}
else
{
setPos(fruitX, fruitY);
SetConsoleTextAttribute(h, COLOR_FRUIT);
cout << " ";
fruitFlash = false;
}
setPos(fruitX, fruitY);
SetConsoleTextAttribute(h, COLOR_FRUIT);
cout << "F";
for (int i = 0; i < nTail; i++)
{
setPos(tailX[i], tailY[i]);
if (i == 0)
{
SetConsoleTextAttribute(h, COLOR_SNAKE_HEAD);
cout << "0";
}
else
{
SetConsoleTextAttribute(h, COLOR_SHAKE_BODY);
cout << "o";
}
}
setPos(0, STAGE_HEIGHT + THICHKNESS);
SetConsoleTextAttribute(h, COLOR_TEXT);
cout << "游戏得分" << score;
}
void Input()
{
if (_kbhit())
{
switch (_getch())
{
case 'a':
dir = LEFT;
break;
case 'd':
dir = RIGHT;
break;
case 'w':
dir = UP;
break;
case 's':
dir = DOWN;
break;
case 'x':
gameOver = true;
break;
default:
break;
}
}
}
void Logic()
{
int prevX = tailX[0];
int prevY = tailY[0];
int prev2X, prev2Y;
tailX[0] = x;
tailY[0] = y;//把新增的蛇身坐标存放在0位
switch (dir)
{
//case STOP:
//break; 为什么这两行不要
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP: //向上居然是y--
y--;
break;
case DOWN:
y++;
break;
default:
break;
}
//if (x > width || x<0 || y>height || y < 0) //蛇头遇到墙壁则停止
//{
// gameOver = true;
//}
if (x == fruitX && y == fruitY) //蛇头遇到果子
{
score += 10;
fruitX = rand() % width;
fruitY = rand() % height;
nTail++;
}
for (int i = 1; i < nTail; i++)
{
prev2X = tailX[i];
prev2Y = tailY[i];
tailX[i] = prevX;
tailY[i] = prevY;
prevX = prev2X;
prevY = prev2Y;
}
for (int i = 1; i < nTail; i++)
{
if (tailX[i] == x && tailY[i] == y)
gameOver = true;
}
if (x >= width) x = 0; else if (x < 0)x = width - 1;
if (y >= height) y = 0; else if (y < 0)y = height - 1;
}
void Prompt_info(int _x, int _y)
{
int initialX = 20, initialY = 0;
SetConsoleTextAttribute(h, COLOR_TEXT);
setPos(_x + initialX, _y + initialY);
cout << "■游戏说明:";
initialY++; //空一行,可以根据需要调整
setPos(_x + initialX, _y + initialY);
cout << " A.蛇身自撞,游戏结束";
initialY++;
setPos(_x + initialX, _y + initialY);
cout << " B.蛇可撞墙";
initialY++;
setPos(_x + initialX, _y + initialY);
cout << "■操作说明:";
initialY++;
setPos(_x + initialX, _y + initialY);
cout << " □向左移动:←A";
initialY++;
setPos(_x + initialX, _y + initialY);
cout << " □向右移动:→D";
initialY++;
setPos(_x + initialX, _y + initialY);
cout << " □向下移动:↓S";
initialY++;
setPos(_x + initialX, _y + initialY);
cout << " □向上移动:↑W";
initialY++;
setPos(_x + initialX, _y + initialY);
cout << " □开始游戏,任意方向键";
initialY++;
setPos(_x + initialX, _y + initialY);
cout << " □退出游戏: x键退出";
initialY++;
setPos(_x + initialX, _y + initialY);
cout << "☆ 当前难度:";
SetConsoleTextAttribute(h, COLOR_TEXT);
cout << 3;
SetConsoleTextAttribute(h, COLOR_SCORE);
cout << " 级";
}
void showScore(int _x, int _y)
{
setPos(_x + 20, _y + 17);
SetConsoleTextAttribute(h, COLOR_TEXT);
cout << "当前积分";
SetConsoleTextAttribute(h, COLOR_SCORE);
cout << score;
}
void gameOver_info()
{
setPos(5, 8);
SetConsoleTextAttribute(h, COLOR_TEXT2);
cout << "游戏结束!!!";
setPos(3, 9);
cout << "Y重新开始/N退出";
SetConsoleTextAttribute(h, COLOR_TEXT);
}
int main()
{
bool gameQuit = false;
do{
Initial();
DrawMap();
Prompt_info(5, 1);
while (!gameOver)
{
//Draw();
Input();
eraseSnake();
Logic();
DrawLocally();
showScore(3, 1);
Sleep(300);
}
gameOver_info();
while (gameOver)
{
if (_kbhit())
{
switch (_getch())
{
case 'y':
case 'Y':
gameOver = false;
system("cls");
break;
case 'n':
case 'N':
gameOver = false;
gameQuit = true;
break;
default:
break;
}
}
Sleep(300);
}
}while (!gameQuit);
setPos(0, STAGE_HEIGHT +THICHKNESS * 3);
system("pause");
return 0;
}