C++实现坦克大战(新手思路)

C++实现坦克大战(新手思路)

第一次写,写的不好,还请多多包涵,本人也是第一次学习C++,因为在15派学习原因才接触到这个,本文仅仅提供我个人的一个思路。

效果图

C++实现坦克大战(新手思路)
C++实现坦克大战(新手思路)

项目实现的功能

实现的功能:
坦克可以随意移动 可以发射炮弹 炮弹发射后自己向前移动
坦克移动的时有碰撞检测,可以被建筑物挡住
检测 坦克和障碍物 坦克和炮弹 炮弹和炮弹的碰撞
多种地形(河流,草丛 土墙 铁墙)
炮弹发射可以摧毁一部分地形
有简单的地图 有敌军随机移动
有双人模式 计分系统 自定义地图
多种敌军(在显示要区分) 读档存档 具有关卡概念

项目设计:

1.这个项目我设计了四个类:地图 坦克 游戏 子弹 还有一个所有类都要工具的函数(这里也可以建个类然后继承这个类)
地图 我采用双地图 一张静态地图存储不会动的障碍物 一张静态地图存储子弹和坦克这些会动的
坦克 要用类型区分坦克的属性,移动 碰撞 的方法
子弹 同样也是这样,子弹可以重载两个运算符(=,==)一个是初始化子弹用,一个子弹碰撞坦克使用
游戏类 操作坦克类对象和子弹类对象

上代码

C++实现坦克大战(新手思路)

地图类

cpp#pragma once
#include"工具.h"
class CMap
{
public:
	//静态地图
	bool SetMapValue(int nPox, int nPoY,int nValue);
	int GetMapValue(int nPox, int nPoY);
	//动态地图
	bool SetDMapValue(int nPox, int nPoY, int nValue);
	int GetDMapValue(int nPox, int nPoY);
	//画边界
	bool DrawMap();
	//画草
	void DRAWgrass();
	//画河流
	void DrawRiver();
	//画墙
	void DrawWall();
	//画堡垒
	void DrawFortress();
private:
	int m_nMap[Mapx][Mapy] = {}; //静态地图
	int m_dMap[Mapx][Mapy] = {};	//动态地图
};

//上面是.h的文件 下面是.cpp的文件
#include "CMap.h"
//修改动态地图上的地标
bool CMap::SetDMapValue(int nPox, int nPoY, int nValue)
{
	m_dMap[nPox][nPoY] = nValue;
	return true;
}
//修改静态地图上的地标
bool CMap::SetMapValue(int nPox, int nPoY, int nValue)
{
	m_nMap[nPox][nPoY] = nValue;
	return true;
}
//获得动态地图上的地标
int CMap::GetDMapValue(int nPox, int nPoY)
{
	return m_dMap[nPox][nPoY];
}
//获得静态地图上的地标
int CMap::GetMapValue(int nPox, int nPoY)
{
	return m_nMap[nPox][nPoY];
}
//画地图
bool CMap::DrawMap()
{
	for (int i = 0;i < Mapx;i++)
	{
		for (int j = 0;j < Mapy;j++)
		{
			if (i == 0 || j == 0 || i == Mapx-1 || j == Mapy-1)
			{
				SetMapValue(i,j,边界);
				writeChar(i, j, "■",15);
			}
			else
			{
				SetMapValue(i, j, 空地);
			}
		}
	}
	
	return true;
}
//画草
void CMap::DRAWgrass()
{
	for (int j = 19;j < 23;j++)
	{
		for (int i = 1;i < 11;i++)
		{
			SetMapValue(i, j, 丛林);
			writeChar(i, j, "WW", 2);
		}
		for (int i = 30;i < 39;i++)
		{
			SetMapValue(i, j, 丛林);
			writeChar(i, j, "WW", 2);
		}
	}
}
//画河流
void CMap::DrawRiver()
{
	for (int j = 10;j < 13;j++)
	{
		for (int i = 1;i < 11;i++)
		{
			SetMapValue(i, j, 河流);
			writeChar(i, j, "~~", 1);
		}
		for (int i = 30;i < 39;i++)
		{
			SetMapValue(i, j, 河流);
			writeChar(i, j, "~~", 1);
		}
	}
}
//画墙
void CMap::DrawWall()
{
	for (int j = 16;j < 18;j++)
	{
		for (int i = 14;i < 26;i++)
		{
			SetMapValue(i, j, 边界);
			writeChar(i, j, "■", 15);
		}
	}
}
//画堡垒
void CMap::DrawFortress()
{

	for (int j = 36;j < 39;j++)
	{
		for (int i = 19;i < 22;i++)
		{
			SetMapValue(i, j, 木墙);
			writeChar(i, j, "□", 6);
		}
	}
	writeChar(20, 38, "◆", 4);
	SetMapValue(20, 38, 老鹰);
}

坦克类

#pragma once
#include"CBullet.h"
#include"CMap.h"
#include<Windows.h>
#include<vector>
using std::vector;
class CMap;
enum Dir
{
	UP=119, DOWN=115, LEFT=97, RIGHT=100
};
class CTank
{	
public:
	CBullet Bullet;
public:
	//初始化玩家坦克
	void CTankINFO(int type);
	//初始化AI坦克
	void AICTankINFO(int type,int num);
	//擦坦克
	void ClsTank(CTank Tank, CMap& map);
	//画坦克
	void DrawTank(CTank Tank, CMap& map);
	//坦克移动
	void MoveTank(CTank& Tank, CMap& map, vector<CTank*> CTanklist);
	//AI坦克移动
	void MoveAITank(CTank& Tank, CMap& map);
	//坦克的碰撞
	int  TankCollision(CTank Tank,int dir,CMap &map);
	//坦克的保存
	void SaveCTank(vector<CTank*> CTanklist, CMap& map);
	//坦克接口
	Dir GetDIR();
	int GetAlignment();
	int GetPosX();
	int GetPosY();
	int Getbool();
	int Getlive();
	void Setbool(int n);
	void Setlive(int n);
public:
	bool m_Live;   //坦克是否存活
	int m_Alignment;//坦克的阵营
	int m_PosX;
	int m_PosY;     //坦克坐标
	Dir m_Dir;		//坦克方向
	int m_Type;		//坦克类型
	int m_Blood;	//坦克血量
	int m_Scores;	//坦克杀敌分数
	int m_TSpeed;   //坦克速度
	int m_TPast;	//坦克的时钟
	int m_Num;		//坦克序号
	int m_color;		//坦克颜色
};
//上面是.h的文件 下面是.cpp的文件
#include"工具.h"
#include "CTank.h"
#include<time.h>
//TAnk的接口
Dir CTank::GetDIR()
{
	return m_Dir;
}
int CTank::GetAlignment()
{
	return m_Alignment;
}
int CTank::GetPosX()
{
	return m_PosX;
}
int CTank::GetPosY()
{
	return m_PosY;
}
int CTank::Getbool()
{
	return m_Blood;
}
int CTank::Getlive()
{
	return m_Live;
}
void CTank::Setbool(int n)
{
	m_Blood = n;
}
void CTank::Setlive(int n)
{
	m_Live = n;
}

//画坦克
void CTank::DrawTank(CTank Tank, CMap& map)
{
	int x = Tank.m_PosX;
	int y = Tank.m_PosY;
	switch (Tank.m_Dir)
	{
	case UP:
	{
		
		writeChar(x - 1, y - 1, "  ■  ", Tank.m_color);
	
		writeChar(x - 1, y, "■■■", Tank.m_color);
	
		writeChar(x - 1, y + 1, "■  ■", Tank.m_color);
		
		
	}break;
	case DOWN:
		
			writeChar(x - 1, y - 1, "■  ■", Tank.m_color);
		
			writeChar(x - 1, y, "■■■", Tank.m_color);
		
			writeChar(x - 1, y + 1, "  ■  ", Tank.m_color);
		
		
		break;
	case LEFT:

		
			writeChar(x - 1, y - 1, "  ■■", Tank.m_color);
		
			writeChar(x - 1, y, "■■  ", Tank.m_color);
		
			writeChar(x - 1, y + 1, "  ■■", Tank.m_color);
		
		break;
	case RIGHT:
		
			writeChar(x - 1, y - 1, "■■  ", Tank.m_color);
		
			writeChar(x - 1, y, "  ■■", Tank.m_color);
		
			writeChar(x - 1, y + 1, "■■  ", Tank.m_color);
		
		
		break;
	}
	for (int i = 0;i < 3;i++)
	{
		for (int i = 0;i < 3;i++)
		{
			if (Tank.m_Alignment == 100)
			{
				map.SetDMapValue(Tank.m_PosX + i - 1, Tank.m_PosY + i - 1, 100);
			}
			else
			{
				map.SetDMapValue(Tank.m_PosX + i - 1, Tank.m_PosY + i - 1, 200 + Tank.m_Num);
			}
		}
	}

}
//我方坦克初始化
void CTank::CTankINFO(int type)
{
	m_Live = 1;
	m_Alignment = 100;
	m_Dir = UP;
	m_Type = type;
	m_Blood = 3;
	m_Scores = 0;
	m_TSpeed = 500;
	if (type == 0)
	{
		m_PosX = 10;
		m_PosY = 30;
		m_color = 7;
	}
	else
	{
		m_PosX = 30;
		m_PosY = 30;
		m_color = 7;
	}
}
//敌方坦克初始化
void CTank::AICTankINFO(int type, int num)
{
	m_Live = 1;
	m_Alignment = 200;
	m_Dir = DOWN;
	m_Type = type;
	m_Scores = 0;

	m_Num = num;
	if (type == 2)
	{
		m_Blood = 1;
		m_PosX = 3;
		m_PosY = 3;
		m_TSpeed = 500;
		m_color = 3;
	}
	else
	{
		m_Blood = 2;
		m_PosX = 30;
		m_PosY = 3;
		m_TSpeed = 200;
		m_color = 0x04;
	}
}
//擦除坦克
void CTank::ClsTank(CTank Tank, CMap& map)
{
	int x = Tank.m_PosX;
	int y = Tank.m_PosY;
	
		writeChar(x - 1, y - 1, "      ");
	
		writeChar(x - 1, y, "      ");
	
		writeChar(x - 1, y + 1, "      ");
	for (int i = 0;i < 3;i++)
	{
		for (int j = 0;j < 3;j++)
		{
			map.SetDMapValue(Tank.m_PosX + i - 1, Tank.m_PosY + i - 1, 空地);
		}
	}

}

//坦克的碰撞检测
int CTank::TankCollision(CTank Tank, int dir, CMap& map)
{
	int x = Tank.m_PosX;
	int y = Tank.m_PosY;
	switch (dir)
	{
	case UP:
		 if ((map.GetMapValue(x - 1, y - 2) == 丛林 || map.GetMapValue(x, y - 2) == 丛林 || map.GetMapValue(x + 1, y - 2) == 丛林)
		|| (map.GetMapValue(x - 1, y + 2) == 丛林 || map.GetMapValue(x, y + 2) == 丛林 || map.GetMapValue(x + 1, y + 2) == 丛林))
		{
		return 2;
		}
		 else if ((map.GetMapValue(x, y - 2) == 0 && map.GetMapValue(x - 1, y - 2) == 0 && map.GetMapValue(x + 1, y - 2) == 0) &&
			(map.GetDMapValue(x, y - 2) == 0 && map.GetDMapValue(x - 1, y - 2) == 0 && map.GetDMapValue(x + 1, y - 2) == 0))
		{
			return 1;
		}
		else 
		{
			return 0;
		}
	case DOWN:
		 if ((map.GetMapValue(x - 1, y + 2) == 丛林 || map.GetMapValue(x, y + 2) == 丛林 || map.GetMapValue(x + 1, y + 2) == 丛林)
		|| (map.GetMapValue(x - 1, y - 2) == 丛林 || map.GetMapValue(x, y - 2) == 丛林 || map.GetMapValue(x - 1, y - 2) == 丛林))
		{
		return 2;
		}
		 else if ((map.GetMapValue(x, y + 2) == 0 && map.GetMapValue(x - 1, y + 2) == 0 && map.GetMapValue(x + 1, y + 2) == 0) &&
			(map.GetDMapValue(x, y + 2) == 0 && map.GetDMapValue(x - 1, y + 2) == 0 && map.GetDMapValue(x + 1, y + 2) == 0))
		{
			return 1;
		}	
		
		else
		{
			return 0;
		}
	case LEFT:
		 if ((map.GetMapValue(x - 2, y) == 丛林 || map.GetMapValue(x - 2, y - 1) == 丛林 || map.GetMapValue(x - 2, y + 1) == 丛林)
		|| (map.GetMapValue(x + 2, y) == 丛林 || map.GetMapValue(x + 2, y - 1) == 丛林 || map.GetMapValue(x + 2, y + 1) == 丛林))
		{
		return 2;
		}
		 else if ((map.GetMapValue(x - 2, y) == 0 && map.GetMapValue(x - 2, y - 1) == 0 && map.GetMapValue(x - 2, y + 1) == 0) &&
			(map.GetDMapValue(x - 2, y) == 0 && map.GetDMapValue(x - 2, y - 1) == 0 && map.GetDMapValue(x - 2, y + 1) == 0))
		{
			return 1;
		}
		
		else
			return 0;
	case RIGHT:
		 if ((map.GetMapValue(x + 2, y) == 丛林 || map.GetMapValue(x + 2, y - 1) == 丛林 || map.GetMapValue(x + 2, y + 1) == 丛林)
		|| (map.GetMapValue(x - 2, y) == 丛林 || map.GetMapValue(x - 2, y - 1) == 丛林 || map.GetMapValue(x - 2, y + 1) == 丛林))
		{
		return 2;
		}
		 else if ((map.GetMapValue(x + 2, y) == 0 && map.GetMapValue(x + 2, y - 1) == 0 && map.GetMapValue(x + 2, y + 1) == 0) &&
			(map.GetDMapValue(x + 2, y) == 0 && map.GetDMapValue(x + 2, y - 1) == 0 && map.GetDMapValue(x + 2, y + 1) == 0))
		{
			return 1;
		}
		else
			return 0;
	default:
		return 1;
	}

}
//坦克移动
void CTank::MoveTank(CTank& Tank, CMap& map,vector<CTank*> CTanklist)
{
	int oper = 0;
	if (Tank.m_Type == 0)
	{
		 oper = waitkey();
	}
	else
	{
		int oper1 = waitkey();
		switch (oper1)
		{
		case 'i':
			oper = 119;
			break;
		case 'k':
			oper = 115;
			break;
		case 'j':
			oper = 97;
			break;
		case 'l':
			oper = 100;
			break;
		case 'h':
			oper = 102;
			break;
			
		}
	}
	
	if (oper != 0)
	{
			ClsTank(Tank, map);
	}
	if (TankCollision(Tank,oper ,map))
	{
		switch (oper)
		{
		case 'w':
		{
			if (Tank.m_Dir != UP)
			{
				Tank.m_Dir = UP;
			}
			else
			{
				Tank.m_PosY--;
			}
		}break;
		case 's':
		{
			if (Tank.m_Dir != DOWN)
			{
				Tank.m_Dir = DOWN;
			}
			else
			{
				Tank.m_PosY++;
			}
		}break;
		case 'a':
		{
			if (Tank.m_Dir != LEFT)
			{
				Tank.m_Dir = LEFT;
			}
			else
			{
				Tank.m_PosX--;
			}
		}break;
		case 'd':
		{
			if (Tank.m_Dir != RIGHT)
			{
				Tank.m_Dir = RIGHT;
			}
			else
			{
				Tank.m_PosX++;
			}
		}break;
		case 'f':
		{
			if (Bullet.Getm_bIsDie() == 0)
			{
				Bullet.CreateBullet(Tank);
			}

		}break;
		case 'p':
		{
			SaveCTank(CTanklist,map);

		}break;
		}
	}
	if (oper != 0)
	{
		int a = TankCollision(Tank, oper, map);
			DrawTank(Tank, map);
			if (a == 2)
			{
				map.DRAWgrass();
		}
	}
}
//AI坦克移动
void CTank::MoveAITank(CTank& Tank, CMap& map)
{
	if (Tank.m_Live != 0)
	{
	if (clock() - Tank.m_TPast > Tank.m_TSpeed)
	{
		Tank.m_TPast = clock();
		int oper = rand()%5+1;
		//int oper = 5;
	if (oper != 0)
	{
		ClsTank(Tank, map);
	}
	switch (oper)
	{
	case 1:
		oper = 119;
		break;
	case 2:
		oper = 115;
		break;
	case 3:
		oper = 97;
		break;
	case 4:
		oper = 100;
		break;
	case 5:
		oper = 102;
		break;
	default:
		break;
	}
	if (TankCollision(Tank, oper, map))
	{
		switch (oper)
		{
		case 'w':
		{
			if (Tank.m_Dir != UP)
			{
				Tank.m_Dir = UP;
			}
			else
			{
				Tank.m_PosY--;
			}
		}break;
		case 's':
		{
			if (Tank.m_Dir != DOWN)
			{
				Tank.m_Dir = DOWN;
			}
			else
			{
				Tank.m_PosY++;
			}
		}break;
		case 'a':
		{
			if (Tank.m_Dir != LEFT)
			{
				Tank.m_Dir = LEFT;
			}
			else
			{
				Tank.m_PosX--;
			}
		}break;
		case 'd':
		{
			if (Tank.m_Dir != RIGHT)
			{
				Tank.m_Dir = RIGHT;
			}
			else
			{
				Tank.m_PosX++;
			}
		}break;
		case 'f':
			{
			if (Bullet.Getm_bIsDie() == 0)
			{
				Bullet.CreateBullet(Tank);
			}
			}

		}
	}
	if (oper != 0)
	{
		DrawTank(Tank, map);
	}
	}
	}
}
//保存坦克地图
void CTank::SaveCTank( vector<CTank*> CTanklist,CMap& map)
{
	FILE* fp = nullptr;
	fopen_s(&fp, "CTank.txt", "wb+");
	fwrite(&map, sizeof(CMap), 1, fp);
	int nSize = CTanklist.size();
	fwrite(&nSize, sizeof(int), 1, fp);
	for (int i = 0;i < CTanklist.size();i++)
	{
		fwrite(&(CTanklist[i]->m_Alignment), sizeof(int), 1, fp);
		fwrite(&(CTanklist[i]->m_Blood), sizeof(int), 1, fp);
		fwrite(&(CTanklist[i]->m_Dir), sizeof(Dir), 1, fp);
		fwrite(&(CTanklist[i]->m_Live), sizeof(int), 1, fp);
		fwrite(&(CTanklist[i]->m_Num), sizeof(int), 1, fp);
		fwrite(&(CTanklist[i]->m_PosX), sizeof(int), 1, fp);
		fwrite(&(CTanklist[i]->m_PosY), sizeof(int), 1, fp);
		fwrite(&(CTanklist[i]->m_Scores), sizeof(Dir), 1, fp);
		fwrite(&(CTanklist[i]->m_TPast), sizeof(int), 1, fp);
		fwrite(&(CTanklist[i]->m_TSpeed), sizeof(int), 1, fp);
		fwrite(&(CTanklist[i]->m_Type), sizeof(int), 1, fp);
		fwrite(&(CTanklist[i]->m_color), sizeof(int), 1, fp);
	}
	fclose(fp);
	fp = nullptr;
}

子弹类

#pragma once
#include<time.h>
class CTank;
class CMap;
#include<vector>
using std::vector;
class CBullet
{
public:
	//接口
	int Getm_bIsDie();
	int GetbALignment();
	//运算符重载
	bool operator=(CTank &Tank);
	bool operator==(CTank& Tank);
	//生成子弹
	CBullet CreateBullet(CTank &Tank);
	//擦子弹
	void ClsBullet(CBullet& Bullet, CMap& map);
	//画子弹
	void DrawBullet(CBullet& Bullet, CMap& map);
	//移动子弹
	void MoveBullet(CBullet& Bullet,CMap &map, vector<CTank*> CTanklist);
	//子弹碰撞检测
	bool BulletColloson(CBullet& Bullet,CMap& map, vector<CTank*> CTanklist);
private:
	bool m_bIsDie=0;//子弹是否存在
	int m_bALignment;//子弹所在的阵营
	int m_bPosX;
	int m_bPosY;//子弹坐标
	int m_bDir;//子弹方向
	int m_bType;//子弹类型
	int m_bATK;//子弹攻击力
	int m_bSpeed;//子弹的速度
	int m_bPast;	//子弹的时钟
	int m_color;

};
//上面是.h的文件 下面是.cpp的文件
#include "CBullet.h"
#include"CTank.h"
#include"工具.h"

//接口
int CBullet::Getm_bIsDie()
{
	return m_bIsDie;
}
int CBullet::GetbALignment()
{
	return m_bALignment;
}
//运算符重载
bool CBullet::operator=(CTank &Tank)
{
	m_bDir = Tank.GetDIR();
	m_bPosX = Tank.GetPosX();
	m_bPosY = Tank.GetPosY();
	m_bALignment = Tank.GetAlignment();
	m_bIsDie = 0;
	m_color = Tank.m_color;
	switch (Tank.GetDIR())
	{
	case UP:
		m_bPosY -= 2;
		break;
	case DOWN:
		m_bPosY += 2;
		break;
	case LEFT:
		m_bPosX -= 2;
		break;
	case RIGHT:
		m_bPosX += 2;
		break;
	}
	return true;
}
bool CBullet::operator==(CTank& Tank)
{
	int nTankPosX = Tank.GetPosX();
	int nTankPosY = Tank.GetPosY();
	if (Tank.GetDIR())
	{
		for (int nposY = nTankPosY - 1;nposY < nTankPosY + 2;nposY++)
		{
			for (int nposX = nTankPosX - 1;nposX < nTankPosX + 2;nposX++)
			{
				if ((m_bPosX == nposX) && (m_bPosY == nposY))
				{
					return true;
				}
			}
		}
	}
	return false;
}

//生成子弹
CBullet CBullet::CreateBullet(CTank& Tank)
{
	*this = Tank;
	this->m_bIsDie = 1;
	this->m_bSpeed = 50;
	this->m_bPast = clock();
	if (Tank.m_Type > 2)
	{
		this->m_bATK = 3;
	}
	else
	{
		this->m_bATK = 1;
	}
	return *this;
}

//擦子弹
void CBullet::ClsBullet(CBullet& Bullet, CMap& map)
{
	writeChar(Bullet.m_bPosX, Bullet.m_bPosY, "  ");
	map.SetDMapValue(Bullet.m_bPosX, Bullet.m_bPosY, 0);
}
//画子弹
void CBullet::DrawBullet(CBullet& Bullet, CMap& map)
{
	writeChar(Bullet.m_bPosX, Bullet.m_bPosY, "oo",Bullet.m_color);
	map.SetDMapValue(Bullet.m_bPosX, Bullet.m_bPosY, 10);
}
//移动子弹
void CBullet::MoveBullet(CBullet& Bullet,CMap& map,  vector<CTank*> CTanklist)
{
	if (Bullet.m_bIsDie == 1)
	{
		if (clock() - Bullet.m_bPast > Bullet.m_bSpeed)
		{
			Bullet.m_bPast = clock();
			if (map.GetMapValue(Bullet.m_bPosX, Bullet.m_bPosY) == 河流 || map.GetMapValue(Bullet.m_bPosX, Bullet.m_bPosY) == 丛林)
			{
				
			}
			else
			{
				ClsBullet(Bullet, map);
			}
			
			if (BulletColloson(Bullet, map,  CTanklist))
			{
				switch (Bullet.m_bDir)
				{
				case UP:
					Bullet.m_bPosY--;
					break;
				case DOWN:
					Bullet.m_bPosY++;
					break;
				case LEFT:
					Bullet.m_bPosX--;
					break;
				case RIGHT:
					Bullet.m_bPosX++;
					break;
				}
				if (map.GetMapValue(Bullet.m_bPosX, Bullet.m_bPosY) == 河流 || map.GetMapValue(Bullet.m_bPosX, Bullet.m_bPosY) == 丛林)
				{
					return;
				}
				DrawBullet(Bullet, map);
			}
		}
	}
}
//子弹碰撞
bool CBullet::BulletColloson(CBullet& Bullet,CMap &map, vector<CTank*> CTanklist)
{
	int nPox = Bullet.m_bPosX;
	int nPoY = Bullet.m_bPosY;
	if (map.GetMapValue(nPox, nPoY) == 边界)
	{
		writeChar(nPox, nPoY, "■",15);
		Bullet.m_bIsDie = 0;
		return false;
	}
	if (map.GetMapValue(nPox, nPoY) == 木墙)
	{
		writeChar(nPox, nPoY, "  ");
		map.SetMapValue(nPox, nPoY, 0);
		Bullet.m_bIsDie = 0;
		return false;
	}
	if (map.GetMapValue(nPox, nPoY) == 河流)
	{
		return true;
	}
	if (map.GetMapValue(nPox, nPoY) == 丛林)
	{
		return true;
	}
	switch (Bullet.m_bDir)
	{
	case UP:
		nPoY--;
		break;
	case DOWN:
		nPoY++;
		break;
	case LEFT:
		nPox--;
		break;
	case RIGHT:
		nPox++;
		break;
	}
	//子弹和坦克的碰撞检测
	for (int i = 0;i < CTanklist.size();i++)
	{
		if (Bullet == *CTanklist[i])
		{
			if (Bullet.m_bALignment != CTanklist[i]->GetAlignment())
			{
				Bullet.m_bIsDie = 0;
				
				CTanklist[i]->m_Blood-=Bullet.m_bATK;
				if (CTanklist[i]->m_Blood == 0)
				{
					CTanklist[i]->ClsTank(*CTanklist[i], map);
					CTanklist[i]->m_Live = 0;
					CTanklist[0]->m_Scores += 50;
					
				}
				return false;
			}
			

		}
	}
	
		//子弹和子弹的碰撞
	if (map.GetDMapValue(nPox, nPoY) == 10)
	{
		writeChar(Bullet.m_bPosX, Bullet.m_bPosY, "  ");
		map.SetMapValue(Bullet.m_bPosX, Bullet.m_bPosY, 木墙);
		Bullet.m_bIsDie = 0;
		return false;
	}
	if (map.GetMapValue(nPox, nPoY) == 老鹰)
	{
		writeChar(Bullet.m_bPosX, Bullet.m_bPosY, "  ");
		Bullet.m_bIsDie = 0;
		writeChar(15, 15, "GOOD GAME!!!", 4);
		getchar();
		exit(1);
	}
	return true;
}

游戏类

#pragma once
#include"CBullet.h"
#include"CMap.h"
#include"CTank.h"
#include<vector>
using std::vector;
class CGame
{
public:
	void startGame();//单人开始游戏
	void startGame0();//第三关
	void startGame2();//双人开始游戏
	void startGame3();//编辑地图开始游戏
	void startGame4();//读档开始开始游戏

	vector<CTank*> CTanklist; //坦克列表
public://自制地图
	void KeyEventProc(KEY_EVENT_RECORD ker);
	int MessageLoop(CMap &map);
	void MouseEventProc(MOUSE_EVENT_RECORD mer, CMap& map);
public:
	//读取文件
	void readCTank(CMap& map);
};
//上面是.h的文件 下面是.cpp的文件
#include "CGame.h"
#include"工具.h"
#include<Windows.h>
#include <conio.h>

//键盘事件处理函数
void CGame::KeyEventProc(KEY_EVENT_RECORD ker)
{

}
//消息处理函数
int CGame::MessageLoop(CMap& map)
{
	writeChar(40, 7, "按任意键退出设置地图",2);
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
	INPUT_RECORD stcRecord = { 0 };
	DWORD dwRead;
	SetConsoleMode(hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
	while (1)
	{
		//等待事件
		ReadConsoleInput(hStdin, &stcRecord, 1, &dwRead);
		//处理事件
		if (stcRecord.EventType == KEY_EVENT)
		{//键盘事件
			KeyEventProc(stcRecord.Event.KeyEvent);
			return 0;
		}
		else if (stcRecord.EventType == MOUSE_EVENT)
		{//鼠标事件
			MouseEventProc(stcRecord.Event.MouseEvent, map);
		}
	}

}
//鼠标事件处理函数
void CGame::MouseEventProc(MOUSE_EVENT_RECORD mer, CMap& map)
{
	switch (mer.dwEventFlags)
	{
	case 0:
	{
		if (mer.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
		{
			writeChar(mer.dwMousePosition.X / 2, mer.dwMousePosition.Y, "■");
			map.SetMapValue(mer.dwMousePosition.X/2, mer.dwMousePosition.Y, 边界);
		}
		else if (mer.dwButtonState == RIGHTMOST_BUTTON_PRESSED)
		{
			writeChar(mer.dwMousePosition.X / 2, mer.dwMousePosition.Y, "□");
			map.SetMapValue(mer.dwMousePosition.X/2, mer.dwMousePosition.Y, 木墙);
		}
		break;
	}
	}
}


//读取文件
void CGame::readCTank(CMap &map)
{
	FILE* fp = nullptr;
	fopen_s(&fp, "CTank.txt", "rb+");
	fread(&map, sizeof(CMap), 1, fp);
	int nSize = 0;
	fread(&nSize, sizeof(int), 1, fp);
	//CTanklist.resize(nSize);
	for (int i = 0;i < nSize;i++)
	{
		CTank* tank = new CTank();
		int a = 0;
		fread(&a, sizeof(int), 1, fp);
		tank->m_Alignment = a;
		fread(&a, sizeof(int), 1, fp);
		tank->m_Blood = a;
		fread(&a, sizeof(Dir), 1, fp);
		tank->m_Dir =(Dir) a;
		fread(&a, sizeof(int), 1, fp);
		tank->m_Live = a;
		fread(&a, sizeof(int), 1, fp);
		tank->m_Num = a;
		fread(&a, sizeof(int), 1, fp);
		tank->m_PosX = a;
		fread(&a, sizeof(int), 1, fp);
		tank->m_PosY = a;
		fread(&a, sizeof(Dir), 1, fp);
		tank->m_Scores = a;
		fread(&a, sizeof(int), 1, fp);
		tank->m_TPast = a;
		fread(&a, sizeof(int), 1, fp);
		tank->m_TSpeed = a;
		fread(&a, sizeof(int), 1, fp);
		tank->m_Type = a;
		fread(&a, sizeof(int), 1, fp);
		tank->m_color = a;
		CTanklist.push_back(tank);
	}
	fclose(fp);
	fp = nullptr;
}

//单人开始游戏
void CGame::startGame()
{
	srand(time(NULL));
	CMap map1;
	map1.DrawMap();
	map1.DrawRiver();
	map1.DrawWall();
	map1.DRAWgrass();
	map1.DrawFortress();
	//MessageLoop(map1);
	CTank* Tank0 = new CTank();
	//CTank* Tank1 = new CTank();
	CTank* Tank2 = new CTank();
	CTank* Tank3 = new CTank();
	//初始化坦克
	Tank0->CTankINFO(0);
	//Tank1->CTankINFO(1);//玩家B
	Tank2->AICTankINFO(2,2);
	Tank3->AICTankINFO(3,3);
	CTanklist.push_back(Tank0);
	//CTanklist.push_back(Tank1);
	CTanklist.push_back(Tank2);
	CTanklist.push_back(Tank3);
	for (int i = 0;i < CTanklist.size();i++)
	{
		CTanklist[i]->DrawTank(*CTanklist[i], map1);
	}
	writeChar(48, 2, "第一关", 12);
	writeChar(48, 4, "分数:", 13);
	writeChar(40, 6, "游戏说明:", 11);
	writeChar(45, 6, "游戏目标:保护堡垒击杀敌方坦克", 9);
	writeChar(40, 8, "按键说明:", 14);
	writeChar(45, 8, "玩家A", 1);
	writeChar(45, 10, "w/上,s/下,a/左,d/右,f/发炮弹", 1);
	writeChar(45, 12, "P键保存", 2);
	while (true)
	{
		
		Tank0->MoveTank(*Tank0, map1,CTanklist);
		//Tank1->MoveTank(*Tank1, map1, CTanklist);
		Tank2->MoveAITank(*Tank2, map1 );
		Tank3->MoveAITank(*Tank3, map1 );
		CTanklist.clear();
		if (Tank0->Getlive() != 0)
		{
			CTanklist.push_back(Tank0);
		}
		/*if (Tank1->Getlive() != 0)
		{
			CTanklist.push_back(Tank1);
		}*/
		if (Tank2->Getlive() != 0)
		{
			CTanklist.push_back(Tank2);
		}
		if (Tank3->Getlive() != 0)
		{
			CTanklist.push_back(Tank3);
		}
		Tank0->Bullet.MoveBullet(Tank0->Bullet, map1, CTanklist);
		//Tank1->Bullet.MoveBullet(Tank1->Bullet, map1, CTanklist);
		Tank2->Bullet.MoveBullet(Tank2->Bullet, map1,  CTanklist);
		Tank3->Bullet.MoveBullet(Tank3->Bullet, map1,  CTanklist);
		writeChar2(51, 4, Tank0->m_Scores, 10);
		if (Tank0->Getbool() == 0)
		{
			writeChar(15, 15, "GOOD GAME!!!", 4);
			getchar();
			exit(1);
		}
		if (Tank2->m_Live == 0 && Tank3->m_Live == 0)
		{
			Tank0->ClsTank(*Tank0, map1);
			system("cls");
			CTanklist.clear();
			writeChar(0, 0, "恭喜通关", 4);
			writeChar(0, 1, "进入下一关", 4);
			writeChar(0, 2, "加载中....", 4);
			Sleep(1500);
			system("cls");
			return;
		}
	}
}
//双人开始游戏
void CGame::startGame2()
{
	srand(time(NULL));
	CMap map1;
	map1.DrawMap();
	map1.DrawRiver();
	map1.DrawWall();
	map1.DRAWgrass();
	map1.DrawFortress();
	//MessageLoop(map1);
	CTank* Tank0 = new CTank();
	CTank* Tank1 = new CTank();
	CTank* Tank2 = new CTank();
	CTank* Tank3 = new CTank();
	//初始化坦克
	Tank0->CTankINFO(0);
	Tank1->CTankINFO(1);//玩家B
	Tank2->AICTankINFO(2, 2);
	Tank3->AICTankINFO(3, 3);
	CTanklist.push_back(Tank0);
	CTanklist.push_back(Tank1);
	CTanklist.push_back(Tank2);
	CTanklist.push_back(Tank3);
	for (int i = 0;i < CTanklist.size();i++)
	{
		CTanklist[i]->DrawTank(*CTanklist[i], map1);
	}
	writeChar(48, 2, "第一关", 12);
	writeChar(48, 4, "分数:", 13);
	writeChar(40, 6, "游戏说明:", 11);
	writeChar(45, 6, "游戏目标:保护堡垒击杀敌方坦克", 9);
	writeChar(40, 8, "按键说明:", 14);
	writeChar(45, 8, "玩家A", 1);
	writeChar(45, 10, "w/上,s/下,a/左,d/右,f/发炮弹", 1);
	writeChar(45, 12, "玩家B", 13);
	writeChar(45, 14, "i/上,k/下,j/左,l/右,h/发炮弹", 13);
	writeChar(45, 16, "P键保存", 2);
	while (true)
	{
		CTanklist.clear();
		Tank0->MoveTank(*Tank0, map1, CTanklist);
		Tank1->MoveTank(*Tank1, map1, CTanklist);
		Tank2->MoveAITank(*Tank2, map1);
		Tank3->MoveAITank(*Tank3, map1);
		if (Tank0->Getlive() != 0)
		{
			CTanklist.push_back(Tank0);
		}
		if (Tank1->Getlive() != 0)
		{
			CTanklist.push_back(Tank1);
		}
		if (Tank2->Getlive() != 0)
		{
			CTanklist.push_back(Tank2);
		}
		if (Tank3->Getlive() != 0)
		{
			CTanklist.push_back(Tank3);
		}
		Tank0->Bullet.MoveBullet(Tank0->Bullet, map1, CTanklist);
		Tank1->Bullet.MoveBullet(Tank1->Bullet, map1, CTanklist);
		Tank2->Bullet.MoveBullet(Tank2->Bullet, map1,  CTanklist);
		Tank3->Bullet.MoveBullet(Tank3->Bullet, map1,  CTanklist);
		if (Tank0->Getbool() == 0)
		{
			writeChar(15, 15, "GOOD GAME!!!", 4);
			getchar();
			exit(1);
		}
		if (Tank2->m_Live == 0 && Tank3->m_Live == 0)
		{
			writeChar(15, 15, "GOOD GAME!!!", 4);
			getchar();
			exit(1);
		}
	}
}
//自制地图开始游戏
void CGame::startGame3()
{
	srand(time(NULL));
	CMap map1;
	map1.DrawMap();
	MessageLoop(map1);
	CTank* Tank0 = new CTank();
	//CTank* Tank1 = new CTank();
	CTank* Tank2 = new CTank();
	CTank* Tank3 = new CTank();
	//初始化坦克
	Tank0->CTankINFO(0);
	//Tank1->CTankINFO(1);//玩家B
	Tank2->AICTankINFO(2, 2);
	Tank3->AICTankINFO(3, 3);
	CTanklist.push_back(Tank0);
	//CTanklist.push_back(Tank1);
	CTanklist.push_back(Tank2);
	CTanklist.push_back(Tank3);
	for (int i = 0;i < CTanklist.size();i++)
	{
		CTanklist[i]->DrawTank(*CTanklist[i], map1);
	}
	writeChar(48, 2, "第一关", 12);
	writeChar(48, 4, "分数:", 13);
	writeChar(40, 6, "游戏说明:", 11);
	writeChar(45, 6, "游戏目标:保护堡垒击杀敌方坦克", 9);
	writeChar(40, 8, "按键说明:", 14);
	writeChar(45, 8, "玩家A", 1);
	writeChar(45, 10, "w/上,s/下,a/左,d/右,f/发炮弹", 1);
	writeChar(45, 12, "P键保存", 2);
	while (true)
	{
		CTanklist.clear();
		Tank0->MoveTank(*Tank0, map1, CTanklist);
		//Tank1->MoveTank(*Tank1, map1, CTanklist);
		Tank2->MoveAITank(*Tank2, map1);
		Tank3->MoveAITank(*Tank3, map1);
		if (Tank0->Getlive() != 0)
		{
			CTanklist.push_back(Tank0);
		}
		/*if (Tank1->Getlive() != 0)
		{
			CTanklist.push_back(Tank1);
		}*/
		if (Tank2->Getlive() != 0)
		{
			CTanklist.push_back(Tank2);
		}
		if (Tank3->Getlive() != 0)
		{
			CTanklist.push_back(Tank3);
		}
		Tank0->Bullet.MoveBullet(Tank0->Bullet, map1, CTanklist);
		//Tank1->Bullet.MoveBullet(Tank1->Bullet, map1, CTanklist);
		Tank2->Bullet.MoveBullet(Tank2->Bullet, map1, CTanklist);
		Tank3->Bullet.MoveBullet(Tank3->Bullet, map1, CTanklist);
		if (Tank0->Getbool() == 0)
		{
			writeChar(15, 15, "GOOD GAME!!!", 4);
			getchar();
			exit(1);
		}
		if (Tank2->m_Live == 0 && Tank3->m_Live == 0)
		{
			writeChar(15, 15, "GOOD GAME!!!", 4);
			getchar();
			exit(1);
		}
	}
}
//读档开始游戏
void CGame::startGame4()
{
	srand(time(NULL));
	CMap map1;
	readCTank(map1);
	map1.DrawMap();
	map1.DrawRiver();
	map1.DrawWall();
	map1.DRAWgrass();
	map1.DrawFortress();
	//MessageLoop(map1);
	CTank* Tank0 = CTanklist[0];
	//CTank* Tank1 = new CTank();
	CTank* Tank2 = CTanklist[1];
	CTank* Tank3 = CTanklist[2];
	//初始化坦克
	//Tank0->CTankINFO(0);
	//Tank1->CTankINFO(1);//玩家B
	//Tank2->AICTankINFO(2, 2);
	//Tank3->AICTankINFO(3, 3);
	//CTanklist.push_back(Tank0);
	//CTanklist.push_back(Tank1);
	//CTanklist.push_back(Tank2);
	//CTanklist.push_back(Tank3);

	for (int i = 0;i < CTanklist.size();i++)
	{
		CTanklist[i]->DrawTank(*CTanklist[i], map1);
	}
	writeChar(48, 2, "第一关", 12);
	writeChar(48, 4, "分数:", 13);
	writeChar(40, 6, "游戏说明:", 11);
	writeChar(45, 6, "游戏目标:保护堡垒击杀敌方坦克", 9);
	writeChar(40, 8, "按键说明:", 14);
	writeChar(45, 8, "玩家A", 1);
	writeChar(45, 10, "w/上,s/下,a/左,d/右,f/发炮弹", 1);
	writeChar(45, 12, "玩家B", 13);
	writeChar(45, 14, "i/上,k/下,j/左,l/右,h/发炮弹", 13);
	writeChar(45, 16, "P键保存", 2);
	while (true)
	{
		Tank0->MoveTank(*Tank0, map1,CTanklist);
		//Tank1->MoveTank(*Tank1, map1,CTanklist);
		Tank2->MoveAITank(*Tank2, map1);
		Tank3->MoveAITank(*Tank3, map1);
		CTanklist.clear();
		if (Tank0->Getlive() != 0)
		{
			CTanklist.push_back(Tank0);
		}
		/*if (Tank1->Getlive() != 0)
		{
			CTanklist.push_back(Tank1);
		}*/
		if (Tank2->Getlive() != 0)
		{
			CTanklist.push_back(Tank2);
		}
		if (Tank3->Getlive() != 0)
		{
			CTanklist.push_back(Tank3);
		}
		Tank0->Bullet.MoveBullet(Tank0->Bullet, map1, CTanklist);
		//Tank1->Bullet.MoveBullet(Tank1->Bullet, map1, bulletlist, CTanklist);
		Tank2->Bullet.MoveBullet(Tank2->Bullet, map1, CTanklist);
		Tank3->Bullet.MoveBullet(Tank3->Bullet, map1, CTanklist);
		if (Tank0->Getbool() == 0)
		{
			writeChar(15,15,"GOOD GAME!!!",4);
			getchar();
			exit(1);
		}
		if (Tank2->m_Live == 0 && Tank3->m_Live == 0)
		{
			writeChar(25, 25, "GOOD GAME!!!", 4);
			getchar();
			exit(1);
		}
	}
}
//第二关
void CGame::startGame0()
{
	srand(time(NULL));
	CMap map1;
	map1.DrawMap();
	map1.DrawRiver();
	//map1.DrawWall();
	map1.DRAWgrass();
	map1.DrawFortress();
	//MessageLoop(map1);
	CTank* Tank0 = new CTank();
	//CTank* Tank1 = new CTank();
	CTank* Tank2 = new CTank();
	CTank* Tank3 = new CTank();
	//初始化坦克
	Tank0->CTankINFO(0);
	//Tank1->CTankINFO(1);//玩家B
	Tank2->AICTankINFO(2, 2);
	Tank3->AICTankINFO(3, 3);
	CTanklist.push_back(Tank0);
	//CTanklist.push_back(Tank1);
	CTanklist.push_back(Tank2);
	CTanklist.push_back(Tank3);
	for (int i = 0;i < CTanklist.size();i++)
	{
		CTanklist[i]->DrawTank(*CTanklist[i], map1);
	}
	writeChar(48, 2, "第二关", 12);
	writeChar(48, 4, "分数:", 13);
	writeChar(40, 6, "游戏说明:", 11);
	writeChar(45, 6, "游戏目标:保护堡垒击杀敌方坦克", 9);
	writeChar(40, 8, "按键说明:", 14);
	writeChar(45, 8, "玩家A", 1);
	writeChar(45, 10, "w/上,s/下,a/左,d/右,f/发炮弹", 1);
	writeChar(45, 12, "P键保存", 2);
	while (true)
	{

		Tank0->MoveTank(*Tank0, map1, CTanklist);
		//Tank1->MoveTank(*Tank1, map1, CTanklist);
		Tank2->MoveAITank(*Tank2, map1);
		Tank3->MoveAITank(*Tank3, map1);
		CTanklist.clear();
		if (Tank0->Getlive() != 0)
		{
			CTanklist.push_back(Tank0);
		}
		/*if (Tank1->Getlive() != 0)
		{
			CTanklist.push_back(Tank1);
		}*/
		if (Tank2->Getlive() != 0)
		{
			CTanklist.push_back(Tank2);
		}
		if (Tank3->Getlive() != 0)
		{
			CTanklist.push_back(Tank3);
		}
		Tank0->Bullet.MoveBullet(Tank0->Bullet, map1, CTanklist);
		//Tank1->Bullet.MoveBullet(Tank1->Bullet, map1, CTanklist);
		Tank2->Bullet.MoveBullet(Tank2->Bullet, map1, CTanklist);
		Tank3->Bullet.MoveBullet(Tank3->Bullet, map1, CTanklist);
		writeChar2(51, 4, Tank0->m_Scores, 10);
		if (Tank0->Getbool() == 0)
		{
			writeChar(15, 15, "GOOD GAME!!!", 4);
			getchar();
			exit(1);
		}
		if (Tank2->m_Live == 0 && Tank3->m_Live == 0)
		{
			writeChar(15, 15, "恭喜通关", 4);
			getchar();
			exit(1);
			
		}
	}
}

工具函数

#pragma once
#define Mapx 40
#define Mapy 40
#define 空地  0
#define 边界  1
#define 河流  2
#define 丛林  3
#define 木墙  4
#define 老鹰  5
//打印文字和图形
void writeChar(int x, int y, const char* szBuf, int color=0);
//打印变量的值
void writeChar2(int x, int y, int a, int color = 0);
//获取按键
int waitkey();
//隐藏光标
void ShouCursor(bool isShow);
//上面是.h的文件 下面是.cpp的文件
#include"工具.h"
#include<Windows.h>
#include <conio.h>
#include<iostream>
#include<time.h>
//打印文字和图形
void writeChar(int x, int y, const char* szBuf, int color)
{
	COORD pos = { x * 2,y };
	HANDLE hStout = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hStout, pos);
	SetConsoleTextAttribute(hStout, color);
	printf(szBuf);
}
//打印变量的值
void writeChar2(int x, int y, int a , int color)
{
	COORD pos = { x * 2,y };
	HANDLE hStout = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hStout, pos);
	SetConsoleTextAttribute(hStout, color);
	printf("%d",a);
}
//获取按键
int waitkey()
{
	if (_kbhit())
	{
		return _getch();
	}
	return 0;
}
//隐藏光标
void ShouCursor(bool isShow) {
	HANDLE hOutStd = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO cci;
	cci.dwSize = 1;
	cci.bVisible = isShow;
	SetConsoleCursorInfo(hOutStd, &cci);
}

主函数

#include<iostream>
#include<Windows.h>
#include <conio.h>
#include"CTank.h"
#include"CBullet.h"
#include"工具.h"
#include "CMap.h"
#include"CGame.h"
#pragma comment(lib,"winmm.lib")
int main()
{
	system("mode con cols=120 lines=50");
	PlaySoundA("D:/C语言项目/坦克大战C/坦克大战/坦克大战/菊次郎的夏天.wav", NULL, SND_ASYNC | SND_NODEFAULT);
	ShouCursor(0);
	while (true)
	{
	CGame game1;
	writeChar(10, 10, "坦克大战",7);
	writeChar(10, 11, "1.开始游戏",7);
	writeChar(10, 12, "2.双人游戏",7);
	writeChar(10, 13, "3.自制地图",7);
	writeChar(10, 14, "4.继续游戏",7);
	writeChar(10, 15, "5.退出游戏",7);
	writeChar(10, 16, "",7);
	int oper = getchar();
	switch (oper)
	{
	case '1':
	{
		system("cls");
		game1.startGame();
		game1.startGame0();
	}
	case '2':
	{
		system("cls");
		game1.startGame2();
	}
	case '3':
	{
		system("cls");
		game1.startGame3();
	}
	case '4':
	{
		system("cls");
		game1.startGame4();
	}
	case '5':
	{
		system("cls");
		writeChar(10, 10, "再来玩哟");
		exit(1);
	}
	default:
		break;
	}
	}
}

项目总结

1 代码过于繁琐 可以精简 。
2.可以使用继承和多态进行优化。
3.注释太少(估计过段时间也就上帝能看得懂我的代码了)。
4.敌方坦克太傻了 可以加入Astart算法让他自行寻路。
5.取名字虽然是个难事 尽量见名知意 或者就多注释。

上一篇:实验:图的创建


下一篇:图——邻接表表示(C++代码)