第五章 循环控制与代码管控

游戏循环控制

游戏循环结束后,让循环能够重新开始。

目前游戏循环用的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;
}

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值