C++STL之贪吃蛇小游戏

写一个贪吃蛇小游戏

源.cpp

#include<iostream>
#include"wall.h"
#include"Snake.h"
#include"Food.h"
#include<ctime>
#include<conio.h>
#include<Windows.h>
#include<time.h>
using namespace std;

void gotoxy3(HANDLE hOut3, int x, int y)
{
	COORD pos;
	pos.X = x;             //横坐标
	pos.Y = y;            //纵坐标
	SetConsoleCursorPosition(hOut3, pos);
}//光标定位函数
HANDLE hOut3 = GetStdHandle(STD_OUTPUT_HANDLE);



int main() {
	srand((unsigned int)time(NULL));
	//判断是否死亡标志
	bool isDead = false;
	char preKey = NULL;
	int preSleepTime = 0;
	//char lastKey = NULL;
	//测试
	Wall walltmp;
	walltmp.initWall();
	walltmp.DrawWall();
	//walltmp.SetWall(5, 4, "@");
	//walltmp.SetWall(5, 5, "=");
	//walltmp.SetWall(5, 6, "=");
	
	Food food(walltmp);
	food.setFood();

	Snake snaketmp(walltmp,food);
	snaketmp.initSnake();

	//接收用户输入

	while (!isDead) {
		char KeyTmp = _getch();
		//lastKey = KeyTmp;
		if (snaketmp.LEFT== KeyTmp && preKey == NULL) {
			continue;
		}
		do {
			if (KeyTmp==snaketmp.UP || KeyTmp == snaketmp.DOWN || KeyTmp == snaketmp.LEFT || KeyTmp == snaketmp.RIGHT) {
				//判断本次文件是否与上次冲突
				if ((KeyTmp == snaketmp.UP && preKey == snaketmp.DOWN)
					||(KeyTmp == snaketmp.DOWN && preKey == snaketmp.UP)
					||(KeyTmp == snaketmp.LEFT && preKey == snaketmp.RIGHT)
					||(KeyTmp == snaketmp.RIGHT && preKey == snaketmp.LEFT)) {
					KeyTmp = preKey;
				}
				else {
					preKey = KeyTmp;
				}
				
				if (snaketmp.move(KeyTmp) == true) {
					//system("cls");
					//walltmp.DrawWall();
					gotoxy3(hOut3, 2 * walltmp.COL_Tmp, 11);
					cout << "本局游戏得分:" << snaketmp.getScore() << "分!" << endl;
					if (snaketmp.getSleepTime() < 160) { 
						Sleep(preSleepTime); 
					}
					else { 
						Sleep(snaketmp.getSleepTime());
						preSleepTime = snaketmp.getSleepTime();
					}
					gotoxy3(hOut3, 2 * walltmp.COL_Tmp, 12);
					cout << "现在的速度等级为:" << snaketmp.getSpeech(preSleepTime);
					if (snaketmp.getSpeech(preSleepTime) == 4) {
						gotoxy3(hOut3, 2 * walltmp.COL_Tmp, 13);
						cout << "——当前已经是最高速度!";
					}
				}
				else {
					isDead = true;
					break;
				}
			}
			else {
				KeyTmp = preKey;
			}
		} while (!_kbhit());//当没有键盘输入的时候返回 0
	}
	//snaketmp.delPoint();
	//snaketmp.move('w');
	//snaketmp.move('w');
	//snaketmp.move('w');
	//snaketmp.move('d');

	
	//cout << endl << walltmp.GetWall(5,4)<< endl;

	system("pause");
	return EXIT_SUCCESS;
}

wall.h

#pragma once
#ifndef _WALL_H
#define _WALL_H
#include<iostream>
using namespace std;

class Wall {
public:
	enum {
		ROW_Tmp = 26,
		COL_Tmp = 26
	};
	//初始化墙壁
	void initWall();
	//画出墙壁
	void DrawWall();
	//根据索引设置二维数组内容
	void SetWall(int x, int y, char c);
	//根据索引获取当前位置的符号
	char GetWall(int x, int y);
private:
	char gameArray[ROW_Tmp][COL_Tmp];
};
#endif // !_WALL_H

wall.cpp

#include"wall.h"

void Wall::initWall() {
	for (int i = 0; i < ROW_Tmp; i++) {
		for (int j = 0; j < COL_Tmp; j++) {
			//
			if (i==0 || j==0 || i==ROW_Tmp-1 || j==COL_Tmp-1) {
				gameArray[i][j] = '*';
			}
			else {
				gameArray[i][j] = ' ' ;
			}
		}
	}

}

void Wall::DrawWall()
{
	for (int i = 0; i < ROW_Tmp;i++) {
		for (int j = 0; j < COL_Tmp;j++) {
			cout << gameArray[i][j] << " ";
		}
		if (i == 5) {
			cout << "杨子江手打!";
		}
		if (i == 6) {
			cout << "一定要切换成英文输入法!";
		}
		if (i == 7) {
			cout << "按键 A :Left";
		}
		if (i == 8) {
			cout << "按键 D :Right";
		}
		if (i == 9) {
			cout << "按键 W :Up";
		}
		if (i == 10) {
			cout << "按键 S :Down";
		}
		cout << endl;
	}

}

void Wall::SetWall(int x, int y, char c)
{
	gameArray[x][y] = c;
}

char Wall::GetWall(int x, int y)
{
	return gameArray[x][y];
}

food.h

#pragma once
#include<iostream>
#include"wall.h"

using namespace std;

class Food {
public:
	Food(Wall &wall);
	//设置食物
	void setFood();

	Wall &wall;
	int foodX;
	int foodY;
};

food.cpp

#include "Food.h"
#include<Windows.h>

void gotoxy2(HANDLE hOut2, int x, int y)
{
	COORD pos;
	pos.X = x;             //横坐标
	pos.Y = y;            //纵坐标
	SetConsoleCursorPosition(hOut2, pos);
}//光标定位函数
HANDLE hOut2 = GetStdHandle(STD_OUTPUT_HANDLE);


Food::Food(Wall &wall): wall(wall)
{

}

void Food::setFood()
{
	while (true) {
		foodX = rand() % (Wall::ROW_Tmp - 2) + 1;
		foodY = rand() % (Wall::COL_Tmp - 2) + 1;

		//如果随机数是蛇头或者蛇身,就生成新的随机数
		if (wall.GetWall(foodX, foodY) == ' ') {
			wall.SetWall(foodX, foodY, '#');
			gotoxy2(hOut2, 2 * foodY, foodX);
			cout << "#";
			break;
		}
	}
	
}

snake.h

#pragma once
#include<iostream>
#include"wall.h"
#include"Food.h"

using namespace std;


class Snake {
public:
	Snake(Wall &pWall,Food &pFood);
	~Snake();
	enum {
		UP = 'w',DOWN = 's',LEFT = 'a',RIGHT = 'd'
	};
	//节点
	struct Point {
		//数据域
		int x;
		int y;
		//指针域
		Point *Next;
	};
	Point *pHead;
	//初始化
	void initSnake();
	//销毁节点
	void destroySnake();
	//添加节点
	void addSnake(int x1,int y1);
	//
	void delPoint();
	//
	bool move(char Key);

	Wall &wall;
	Food &food;
	bool isRool=false;//蛇本身的循环

	//辅助玩法
	//获取蛇长度和增加游戏速度
	int getSize();
	int getSleepTime();
	//显示得分
	int getScore();
	//显示速度
	int getSpeech(int a);
};

snake.cpp

#include"Snake.h"
#include<Windows.h>

void gotoxy1(HANDLE hOut1, int x, int y)
{
	COORD pos;
	pos.X = x;             //横坐标
	pos.Y = y;            //纵坐标
	SetConsoleCursorPosition(hOut1, pos);
}//光标定位函数
HANDLE hOut1 = GetStdHandle(STD_OUTPUT_HANDLE);

Snake::Snake( Wall &pWall,Food &pFood) : wall(pWall) ,food(pFood)
{
	pHead = NULL;
}

Snake::~Snake()
{

}

void Snake::initSnake()
{
	destroySnake();
	addSnake(5, 3);
	addSnake(5, 4);
	addSnake(5, 5);
}

void Snake::destroySnake()
{
	Point *pCur = pHead;
	if (pHead !=NULL) {
		pCur = pHead->Next;
		delete pHead;
		pHead = pCur;
	}
}

void Snake::addSnake(int x1, int y1)
{
	Point *NewPoint = new Point;
	NewPoint->x = x1;
	NewPoint->y = y1;
	NewPoint->Next = NULL;
	//如果头不为空,则改为身子
	if (pHead != NULL) {
		wall.SetWall(pHead->x, pHead->y, '=');
		gotoxy1(hOut1, 2 * pHead->y, pHead->x);
		cout << "=";
	}
	NewPoint->Next = pHead;
	pHead = NewPoint;
	wall.SetWall(pHead->x, pHead->y,'@');
	gotoxy1(hOut1, 2 * pHead->y, pHead->x);
	cout << "@";
}

void Snake::delPoint()
{
	//两个节点以上 才能删除操作
	if (pHead==NULL || pHead->Next==NULL) {
		return;
	}
	//找到尾节点
	Point *pCur = pHead->Next;
	Point *pPre = pHead;
	while (pCur->Next!=NULL) {
		pPre = pPre->Next;
		pCur = pCur->Next;
	}
	//删除尾结点
	wall.SetWall(pCur->x, pCur->y,' ');
	gotoxy1(hOut1, 2 * pCur->y, pCur->x);
	cout << " ";
	delete pCur;
	pCur = NULL;
	pPre->Next = NULL;

}

bool Snake::move(char Key)
{
	int x = pHead->x;
	int y = pHead->y;

	switch (Key)
	{
	case UP:
		x--;
		break;
	case DOWN:
		x++;
		break;
	case LEFT:
		y--;
		break;
	case RIGHT:
		y++;
		break;
	default:
		break;
	}
	//如果下一步碰到的是尾巴 不应该死亡
	Point *pCur = pHead->Next;
	Point *pPre = pHead;
	while (pCur->Next != NULL) {
		pPre = pPre->Next;
		pCur = pCur->Next;
	}
	if (pCur->x==x && pCur->y==y) {
		isRool = true;
	}
	else {
		//判断用户到达位置是否成功
		if (wall.GetWall(x, y) == '*' )  {
			addSnake(x, y);
			delPoint();
			//system("cls");
			//wall.DrawWall();
			gotoxy1(hOut1, 2 * wall.COL_Tmp, 11);
			cout << "本局游戏得分:" << getScore() << "分!" << endl;
			gotoxy1(hOut1, 0, wall.ROW_Tmp);	
			cout << "————你撞到墙了!————" << endl;
			cout << "———— 游戏结束!————" << endl;
			return false;
		}
		else if (wall.GetWall(x, y) == '='){
			//wall.DrawWall();
			gotoxy1(hOut1, 2 * wall.COL_Tmp, 11);
			cout << "本局游戏得分:" << getScore() << "分!" << endl;
			gotoxy1(hOut1, 0, wall.ROW_Tmp);
			cout << "————你吃到了自己的身子!————" << endl;
			cout << "————      游戏结束!    ————" << endl;
			return false;
		}
	}

	//移动成功
	//1、吃到食物;2、未吃食物
	if (wall.GetWall(x,y)=='#') {
		this->addSnake(x,y);
		//重新设置食物
		food.setFood();
	}
	else {
		this->addSnake(x, y);
		this->delPoint();
		if (isRool) {
			wall.SetWall(x, y, '@');
			gotoxy1(hOut1, 2 * y, x);
			cout << "@";
		}
	}
	return true;
}

int Snake::getSize()
{
	int size = 0;
	Point *CurPoint = pHead;
	while (CurPoint!=NULL) {
		size++;
		CurPoint = CurPoint->Next;
	}
	return size;
}

int Snake::getSleepTime()
{
	int size = getSize();
	int SleepTime = 0;
	if (size < 5) { SleepTime = 300; }
	else if(size > 5 && size < 8) { SleepTime = 240; }
	else if(size > 8 && size < 12) { SleepTime = 200; }
	else if(size > 12){ SleepTime = 160; }
	return SleepTime;
}

int Snake::getScore()
{
	int getScore = 0;
	int size = getSize();
	getScore = (size - 3) * 100;
	return getScore;
}

int Snake::getSpeech(int a)
{
	int size = 0;
	switch ( a )
	{
	case 300:
		size = 1;
		break;
	case 240:
		size = 2;
		break;
	case 200:
		size = 3;
		break;
	case 160:
		size = 4;
		break;
	default:
		break;
	}
	return size;
}

我的运行结果如下:

在这里插入图片描述

发布了113 篇原创文章 · 获赞 283 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_32642107/article/details/105443176
今日推荐