C++控制台游戏【贪吃蛇】-- 指针版

// 贪吃蛇(指针).cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <time.h>
#include <vector>
using namespace std;

#define KEY_DOWN(vk_code) GetAsyncKeyState(vk_code)&0x8000?1:0


int arrMap[15][15] = {
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};


//控制方向的枚举值
enum
{
	E_DIR_NONE
};
int nDir = E_DIR_NONE;


//节点的结构体
struct SNode{
	int nNodeRow;
	int nNodeCol;
	int nNodeRowBk;
	int nNodeColBk;

	SNode()
	{
		nNodeRow = 0;
		nNodeCol = 0;
		nNodeRowBk = 0;
		nNodeColBk = 0;
	}

	SNode(int nInRow, int nInCol)
	{
		nNodeRow = nInRow;
		nNodeCol = nInCol;
		nNodeRowBk = nInRow;
		nNodeColBk = nInCol;
	}

	//节点的备份
	void backup()
	{
		nNodeRowBk = nNodeRow;
		nNodeColBk = nNodeCol;
	}
};


//蛇的结构体
struct SSnake
{
	int nRow;
	int nCol;
	int nSpeed;
	int nDir;

	//用于传入参数
	SSnake(int nInRow, int nInCol)
	{
		nRow = nInRow;
		nCol = nInCol;
	}

	//节点的容器
	//vector<SNode> vecSnake;
	vector<SNode*> vecSnake;
	SNode* head = new SNode(5,5);

	//速度的构造函数
	SSnake(int nInSpeed)
	{
		//初始化压蛇头
		vecSnake.push_back(head);
		nInSpeed = nInSpeed;
		nDir = 0;
	}

	//蛇头的备份
	void backupHead()
	{
		head->backup();
		//vecSnake[0].backup();
	}

	//移动
	void move()
	{
		if (nDir <= 3)
		{
			if (0 == nDir)
			{
				head->nNodeRow--;
				//vecSnake[0].nNodeRow--;
			}
			else if (1 == nDir)
			{
				head->nNodeRow++;
				//vecSnake[0].nNodeRow++;
			}
			else if (2 == nDir)
			{
				head->nNodeCol--;
				//vecSnake[0].nNodeCol--;
			}
			else if (3 == nDir)
			{
				head->nNodeCol++;
				//vecSnake[0].nNodeCol++;
			}

		}
	}

	//是否碰到蛇头,蛇吃食物
	bool isExistHead(int nInRow, int nInCol)
	{
		if (head->nNodeRow == nInRow && head->nNodeCol == nInCol)
		{
			return true;
		}
		return false;
	}

	//长身体
	void addBody()
	{
		vecSnake.push_back(new SNode());
	}

	//跟随
	void follow()
	{
		for (int i = 1; i < vecSnake.size(); i++)
		{
			//备份当前这一节的坐标
			vecSnake[i]->backup();
		}

		for (int i = 0; i < vecSnake.size() - 1; i++)
		{
			//把当前节的坐标给下一节
			vecSnake[i + 1]->nNodeRow = vecSnake[i]->nNodeRowBk;
			vecSnake[i + 1]->nNodeCol = vecSnake[i]->nNodeColBk;
		}
	}

	//渲染蛇
	bool isExist(int nRow, int nCol)
	{
		for (int k = 0; k < vecSnake.size(); k++)
		{
			if (nRow == vecSnake[k]->nNodeRow && nCol == vecSnake[k]->nNodeCol)
			{
				return true;
			}
		}
		return false;
	}

	//蛇头撞墙
	void isCrashWall()
	{
		if (1 == arrMap[vecSnake[0]->nNodeRow][vecSnake[0]->nNodeCol])
		{
			cout << "Game over!" << endl;
		}
	}

	//蛇头撞身体
	void isCrashSelf()
	{
		for (int i = 1; i < vecSnake.size(); i++)
		{
			if ((vecSnake[0]->nNodeRow == vecSnake[i]->nNodeRow) && (vecSnake[0]->nNodeCol == vecSnake[i]->nNodeCol))
			{
				cout << "Game over!" << endl;
			}
		}
	}
};


//食物的结构体
struct SFood{
	int nFoodRow;
	int nFoodCol;

	SFood(int nInFoodRow, int nInFoodCol)
	{
		nFoodRow = nInFoodRow;
		nFoodCol = nInFoodCol;
	}

	//食物随机生成
	void randPos()
	{
		nFoodRow = rand() % 13 + 1;
		nFoodCol = rand() % 13 + 1;
	}
};

//创建一个snake对象,给两次循环的速度
//SSnake snake(2);
SSnake* snake = new SSnake(2);
SFood* sFood = new SFood(5, 6);

int _tmain(int argc, _TCHAR* argv[])
{

	//随机种子初始化
	srand(time(nullptr));

	//数据更新,要在渲染的前面
	//刷新
	while (true)
	{
		//蛇头移动之前要进行坐标备份
		snake->backupHead();

		//数据更新,要在渲染的前面
		//让蛇根据按键的方向一直动
		snake->move();

		//设置按键让贪吃蛇改变方向
		if (KEY_DOWN(VK_UP))
		{
			snake->nDir = 0;
		}
		else if (KEY_DOWN(VK_DOWN))
		{
			snake->nDir = 1;
		}
		else if (KEY_DOWN(VK_LEFT))
		{
			snake->nDir = 2;
		}
		else if (KEY_DOWN(VK_RIGHT))
		{
			snake->nDir = 3;
		}

		//蛇吃食物
		if (snake->isExistHead(sFood->nFoodRow, sFood->nFoodCol))
		{
			//再次随机生成食物,让食物的位置变化
			sFood->randPos();

			//把身体压入容器中,这里要用到前面构造的一个无参的构造函数
			snake->addBody();
		}


		//身体跟随蛇头
		snake->follow();

		//检测蛇头是否幢墙
		snake->isCrashWall();

		//蛇头与蛇身的碰撞
		snake->isCrashSelf();

		//渲染
		for (int i = 0; i < 15; i++)
		{
			for (int j = 0; j < 15; j++)
			{

				if (1 == arrMap[i][j])
				{
					cout << "■";
				}
				else if (snake->isExist(i, j))
				{
					cout << "蛇";
				}
				else if (i == sFood->nFoodRow && j == sFood->nFoodCol)
				{
					cout << "肉";
				}
				else
				{
					cout << "  ";
				}
			}
			cout << endl;//数组换行输出
		}
		Sleep(60);
		system("cls");
	}


	system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值