【第十五节】C语言小项目(windows控制台版本坦克大战)

目录

前言

一、项目概述

1.1 项目目标

1.2 游戏功能说明

1.3 开发环境及工具

二、游戏逻辑设计

2.1 显示输出

2.2 用户输入

2.3 数据部分设计

2.4 其他逻辑部分设计

三、运行截图和参考代码


前言

        大家可以先关注一波,后续继续更新各种技术免费专栏,涉及数据结构与算法,c/c++ QT/duilib等客户端开发,服务器开发,音视频开发,驱动开发,逆向安全,游戏开发等等有关技术栈,还有各种热门编程技术如rust, java,go, javascript, python, php, c#等等,遍及各种平台如android, ios, windows, unix, linux等等,让新手从入门到实战,从IT学习者身份顺利过渡到职场人士 。

一、项目概述

1.1 项目目标

        为了巩固之前学习的C语言知识点,提高C语言的实践能力,锻炼逻辑思维。相信大家都玩过坦克移动射击类游戏,本节我们一起来学习用C语言实现一个坦克大战小游戏。

1.2 游戏功能说明

游戏菜单选项:
1、开始游戏
2、自定义地图进行游戏
3、观看游戏操作说明
4、退出游戏

操作说明:

游戏中英文输入状态下w,s,a,d按键分别控制坦克的上下左右。
游戏中按f键攻击,按p键暂停,按空格键开始。
编辑地图中按四个箭头移动光标,t、g、r键分别创建土墙,钢墙和擦除,按空格键则结束编辑开始游戏。

游戏说明:

游戏中有土墙和钢墙,土墙可以被破坏,钢墙不能被破坏,我方坦克有生命值10,消灭一辆坦克积分加100,消灭10辆敌军坦克赢得游戏,或者自己生命值为零则结束游戏。敌军可以随机开炮移动,碰障碍物不能前进,子弹也可以互相碰撞等。详见游戏。

1.3 开发环境及工具

windows + vs + C语言

二、游戏逻辑设计

2.1 显示输出

        我们一般使用printf打印字符出现显示,结合一些windows控制台API来控制窗口大小标题,鼠标的显示颜色样式位置,文本的颜色等。如下是一些可能用到的API,具体用处可以参考MSDN文档:

SetConsoleTitle  设置控制台窗口标题
GetStdHandle  获取控制台操作句柄
GetLargestConsoleWindowSize  获取最大控制台窗口大小
SetConsoleScreenBufferSize  设置控制台缓冲区大小
SetConsoleWindowlnfo   设置控制台窗口大小
SetConsoleScreenBufferSize   设置控制台缓冲区大小
SetConsoleCursorlnfo   设置光标信息
SetConsoleTextAttribute  设置控制台文本属性
SetConsoleCursorPosition  设置控制台光标位置
SetConsoleMode  设置控制台模式  支持鼠标或者键盘响应等
ReadConsoleInput  读取控制台输入信息  读取鼠标和键盘等输入信息

system("mode con cols=90 lines=45")  windows命令提示符

mode 是一个Windows命令,用于获取或设置控制台窗口的属性。con 是控制台窗口的别名。colslines 分别用于设置窗口的列数和行数。

绘制功能 Draw.h

#pragma once
void WelcomeScreen();
void printBorder();
void printInstru();

void printBase();//打印基地
void printExist();//打印地图所有物
void printTank(Object* tank);//打印坦克
void clearTank(Object* tank);//清除坦克
void printBullet();//打印自己的子弹
void printBadBullet(Object* badBullet);//打印敌人子弹
void clearBullet(Object* object);//清除自己子弹
void clearBadBullet(int x, int y);//清除敌人坦克的子弹
void printScoreboard();

Draw.c

#include"stdio.h"
#include"stdlib.h"
#include"windows.h"
#include"TankGame.h"
#include"Utils.h"
#include"editMap.h"
#include"Draw.h"

void WelcomeScreen() {
	setEnglish();
	system("cls");
	gotoXY(20,5);
	color(14);
	printf("        〓██▄▄▄▄▄▄\n");
	gotoXY(20, 6);
	printf("    ▄▅██████▅▄▃▂\n");
	gotoXY(20, 7);
	printf("██████████████\n");
	gotoXY(20, 8);
	printf("◥⊙▲⊙▲⊙▲⊙▲⊙▲⊙▲◤\n");
	gotoXY(20, 10);
	printf("1、开始游戏\n");
	gotoXY(20, 11);
	printf("2、编辑地图\n");
	gotoXY(20, 12);
	printf("3、操作说明\n");
	gotoXY(20, 13);
	printf("4、退出游戏\n");
	gotoXY(20, 14);
	printf("请输入您的操作选项:");

	int flag = 1;
	char operate;
	while(flag) {
		operate = getchar();
		switch (operate) {
		case '1':startGame(); flag = 0; break;
		case '2':edit_map(); flag = 0; break;
		case '3':printInstru(); flag = 0; break;
		case '4':exit(0); flag = 0; break;
		default:printf("输入错误,请重新输入:");break;	
		}
	}
}

//打印操作说明
void printInstru() {

	system("cls");
	gotoXY(20,10);
	printf("游戏中wsad按键分别控制坦克的上下左右");
	gotoXY(20, 12);
	printf(" 游戏中f键攻击,p键暂停,空格键开始 ");
	gotoXY(1, 14);
	printf("编辑地图中按四个箭头移动光标,t、g、r键分别创建土墙,钢墙和擦除,空格键则结束编辑开始游戏");
	gotoXY(20, 16);
	system("pause");
	getchar();
	WelcomeScreen();
}
//打印围墙
void printBorder() {
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);//白色
	printf("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\n");
	for (int i = 0; i<38; i++)
		printf("■                                                                            ■\n");
	printf("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\n");
}


void printBase() {

	for (int i = 0; i < 3; i++)          //打印基地
		for (int j = 0; j < 3; j++)
		{
			if (base.Shape[i][j] == 2) {
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 9);
				gotoXY(36 + 2 * j, 36 + i);
				printf("■");
			}
			else {
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
				gotoXY(36 + 2 * j, 36 + i);
				printf("■");
			}
		}
}


void printExist() {
	for (int j = 0; j < 38; j++)
		for (int i = 0; i < 38; i++)
			if (existence[i][j] == 3)//土墙
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
				gotoXY(2 + 2 * j, 1 + i);
				printf("■");
			}
			else if (existence[i][j] == 4)钢墙
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
				gotoXY(2 + 2 * j, 1 + i);
				printf("■");
			}
}

//打印坦克
void printTank(Object* tank) {
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++) {
			if (tank->Shape[i][j] == 2 && tank->Camp == 2)
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);// 红色
				gotoXY(2 * tank->CoordX + 2 * j - 2, tank->CoordY + i - 1);
				printf("■");
			}
			if (tank->Shape[i][j] == 2 && tank->Camp == 1)
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 9);//淡蓝色
				gotoXY(2 * tank->CoordX + 2 * j - 2, tank->CoordY + i - 1);
				printf("■");
			}
		}
}


void clearTank(Object* tank) {
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
		{
			gotoXY(2 * tank->CoordX + 2 * j - 2, tank->CoordY + i - 1);
			printf("  ");
		}
}

//打印自己的子弹
void printBullet() {
	for (int i = 0; i < 50; i++) {
		if (ownBullet[i].CoordX != 0 && ownBullet[i].CoordY != 0) {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 6);
			gotoXY(ownBullet[i].CoordX * 2, ownBullet[i].CoordY);
			ownBullet[i].ID = i;
			printf("◎");
		}
	}
}

//打印敌人子弹
void printBadBullet(Object* badBullet) {

	if (badBullet->CoordX != 0 && badBullet->CoordY != 0) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 6);
		if (badBullet->CoordX * 2 < 80) {
			gotoXY(badBullet->CoordX * 2, badBullet->CoordY);
			printf("  ");
		}
		gotoXY(badBullet->CoordX * 2, badBullet->CoordY);
		printf("◎");
	}
}


//打印计分
void printScoreboard() {
	gotoXY(5 * 2, 41);
	printf("                               ");
	gotoXY(10 * 2, 41);
	printf("                               ");
	gotoXY(5 * 2, 41);
	printf("score: %d", score);
	gotoXY(12 * 2, 41);
	printf("HP: %d", ownTank.HealthPoint);
}


//清除自己的子弹
void clearBullet(Object* object) {
	for (int i = 0; i < 50; i++) {
		if (object[i].CoordX != 0 && object[i].CoordY != 0) {
			gotoXY(object[i].CoordX * 2, object[i].CoordY);
			printf("  ");
		}
	}
}

//清除敌方坦克子弹
void clearBadBullet(int x, int y) {
	if (x != 0 && y != 0)
	{
		gotoXY(2 * x, y);
		printf("  ");
	}
}

工具类实现

Utils.h

#pragma once

void PrintChar(int Wide, int High, char* pszChar, int color);
void setEnglish();
void gotoXY(int x, int y);
void hideCursor();
void color(int a);

Utils.c

#include"stdio.h"
#include"stdlib.h"
#include"windows.h"
#include"string.h"

void PrintChar(int Wide, int High, char* pszChar, int color) {//定位光标位置并打印
	CONSOLE_CURSOR_INFO cci;
	cci.dwSize = 1;
	cci.bVisible = FALSE;
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
	COORD loc;
	loc.X = Wide * 2;
	loc.Y = High;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), loc);
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
	printf(pszChar);

}

void setEnglish() {        //输入法切换为英文输入状态
	keybd_event(VK_SHIFT, 0, 0, 0);
	Sleep(100);
	keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
}

void hideCursor()
{
	CONSOLE_CURSOR_INFO cursor_info = { 1,0 };
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

void gotoXY(int x, int y)      //设定输出位置
{
	COORD c;   //光标位置
	c.X = x;
	c.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);//获取句柄,设置位置
	hideCursor();//取消光标闪烁
}

void color(int a)   //颜色函数
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), a);
}

2.2 用户输入

可能使用 C 库函数接收键盘输入的函数如
kbhit  键盘按下返回1,否则 0
getchar()  从键盘缓冲区获取字符  回显到屏幕
_getwch()  (unicode版本)从键盘缓冲区获取字符   不回显到屏幕
_getch()   多字节版本

控制台API
GetStdHandle  获取控制台操作句柄,有输入输出,错误等句柄
SetConsoleMode  设置控制台模式  支持鼠标或者键盘响应输入等
ReadConsoleInput  读取控制台输入信息  读取鼠标和键盘等输入信息

使用windows API 异步判断哪个键盘键按下

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

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

2.3 数据部分设计

        使用结构体位段来设计数据对象,以及使用简单的二维数组存储地图数据等。

TankGame.h

#pragma once
typedef struct _OBJECT {
	unsigned int CoordX : 6;  //物体中心点横坐标  //坦克取右下角为中心坐标
	unsigned int CoordY : 6;   //物体中心点纵坐标
	unsigned int HealthPoint : 6;  //生命值
	unsigned int Direction : 3;  //运动方向 1上2下3左4右
								 //unsigned int Collide:2; //碰撞体积
	unsigned int ID : 8;  //编号
	unsigned int Type : 4;  //对象类型 0空 1炮弹节点 2坦克节点 3土墙节点  4钢墙节点
	unsigned int Camp : 2;   //阵营  0中立   1友方    2敌方
	unsigned int Shape[3][3];   //显示形状
	int speed;//速度

}Object, *pObject;

extern int score;  //游戏分数
extern int enemyCount;//敌人数量
extern int gameMap[40][40];//游戏地图
extern int existence[38][38];//地图存在物
extern Object base;//基地
extern Object ownTank;//自己的坦克
extern Object enemyTank[3];//敌人的坦克
extern Object ownBullet[50];//自己的子弹
extern Object enemyBullet[3];//敌人坦克的子弹
void initGame();//初始化游戏

int allowGo(Object* tank);//监测某位置能不能走

void turnUp(Object* tank);//转上后刷新
void turnDown(Object* tank);//转下后刷新
void turnLeft(Object* tank);//转左后刷新
void turnRight(Object* tank);//转右后刷新

void existChange();//监测地图所有物的改变
void baseChange();//监测基地的改变

void gameOver();//游戏结束之后的操作
void checkGame();//监测游戏是否结束

void getExistMap();//获得初始化所有物地图
void renewMap();  //刷新地图
void startGame();  //开始游戏
void stopGame();  //停止游戏
int isNull();//判断地图障碍物数组是否为空

TankGame.c

#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
#include"Utils.h"
#include"windows.h"
#include"time.h"
#include"TankGame.h"
#include"Draw.h"
#include"Bullet.h"
#include"Tank.h"

int score;  //游戏分数
int enemyCount;//敌人数量
int gameMap[40][40];//游戏地图
int existence[38][38];//地图存在物
Object base;//基地
Object ownTank;//自己的坦克
Object enemyTank[3];//敌人的坦克
Object ownBullet[50];//自己的子弹
Object enemyBullet[3];//敌人坦克的子弹

void initGame() {
	enemyCount = 10;
	score = 0;
	//自己坦克的初始化
	ownTank.Camp = 1;
	ownTank.speed = 100;
	ownTank.CoordX = 6;
	ownTank.CoordY = 37;
	ownTank.Direction = 0;
	ownTank.HealthPoint = 10;

	//敌方坦克的初始化
	for (int i = 0; i < 3; i++) {
		enemyTank[i].CoordX = 2 + i * 15;
		enemyTank[i].CoordY = 2;
		enemyTank[i].Direction = 0;
		enemyTank[i].speed = 400;
		enemyTank[i].Camp = 2;
	}

	int _base[3][3] = { { 3,3,3 },{ 3,2,3 },{ 3,2,3 } };
	for (int i = 0; i < 3; i++)//基地初始化
		for (int j = 0; j < 3; j++)
			base.Shape[i][j] = _base[i][j];

	//自己子弹初始化
	for (int i = 0; i < 50; i++) {
		ownBullet[i].CoordX = 0;
		ownBullet[i].CoordY = 0;
		ownBullet[i].Direction = 0;
	}

	//敌方坦克子弹的初始化
	for (int i = 0; i < 3;i++) {
		enemyBullet[i].CoordX = 0;
		enemyBullet[i].CoordY = 0;
		enemyBullet[i].Direction = 0;
	}

	for (int i = 1; i < 39; i++)//地图清屏
		for (int j = 1; j < 39; j++)
		{
			gotoXY(2 * i, j);
			printf("  ");
		}

	if (isNull()==1) {
		getExistMap();
	}

	renewMap();
	printBase();
	printExist();
	printScoreboard();

	turnUp(&ownTank);
	turnDown(&enemyTank[0]);
	turnDown(&enemyTank[1]);
	turnDown(&enemyTank[2]);
}


int isNull() {
	for (int i = 0; i < 38; i++) {
		for (int j = 0; j < 38; j++) {
			if (existence[i][j] != 0) {
				return 0;
				break;
			}
		}
	}

	return 1;
}

void stopGame() {
	int flag = 0;
	char key;
	while (1)
	{
		for (int i = 0; i < 50; i++)
		{
			Sleep(2000);
			if (_kbhit()) //检测
			{
				key = _getch();//捕获按键
				if (key == 32)
				{
					flag = 1;
					break;
				}
			}
			if (flag)
				break;
		}
		if (flag)
			break;
	}
}



//判断该方向能不能前进
int allowGo(Object* tank) {
	switch (tank->Direction)
	{
	case 1:
		if (gameMap[tank->CoordY - 2][tank->CoordX] == 0 &&
			gameMap[tank->CoordY - 2][tank->CoordX - 1] == 0 &&
			gameMap[tank->CoordY - 2][tank->CoordX + 1] == 0)
			return 1;
		else
			return 0;
	case 2:
		if (gameMap[tank->CoordY + 2][tank->CoordX] == 0 &&
			gameMap[tank->CoordY + 2][tank->CoordX - 1] == 0 &&
			gameMap[tank->CoordY + 2][tank->CoordX + 1] == 0)
			return 1;
		else
			return 0;
	case 3:
		if (gameMap[tank->CoordY][tank->CoordX - 2] == 0 &&
			gameMap[tank->CoordY - 1][tank->CoordX - 2] == 0 &&
			gameMap[tank->CoordY + 1][tank->CoordX - 2] == 0)
			return 1;
		else
			return 0;
	case 4:if (gameMap[tank->CoordY][tank->CoordX + 2] == 0 &&
		gameMap[tank->CoordY - 1][tank->CoordX + 2] == 0 &&
		gameMap[tank->CoordY + 1][tank->CoordX + 2] == 0)
		return 1;
		   else
			   return 0;
	}
	return 0;
}

//向上后刷新
void turnUp(Object* tank1) {
	int tankUp[3][3] = { { 0,2,0 },{ 2,2,2 },{ 2,0,2 } };
	if (tank1->Direction == 1)
	{
		if (allowGo(tank1))
		{
			clearTank(tank1);
			tank1->CoordY--;
			printTank(tank1);
			renewMap();
		}
	}
	else
	{
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				tank1->Shape[i][j] = tankUp[i][j];
		clearTank(tank1);
		printTank(tank1);
		tank1->Direction = 1;
		renewMap();

	}
}


//向下后刷新
void turnDown(Object* tank2) {
	int tankDown[3][3] = { { 2,0,2 },{ 2,2,2 },{ 0,2,0 } };
	if (tank2->Direction == 2)
	{
		if (allowGo(tank2))
		{
			clearTank(tank2);
			tank2->CoordY++;
			printTank(tank2);
			renewMap();
		}
	}
	else
	{
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				tank2->Shape[i][j] = tankDown[i][j];
		clearTank(tank2);
		printTank(tank2);
		tank2->Direction = 2;
		renewMap();
	}
}

//向左后刷新
void turnLeft(Object* tank3) {
	int tankLeft[3][3] = { { 0,2,2 },{ 2,2,0 },{ 0,2,2 } };
	if (tank3->Direction == 3)
	{
		if (allowGo(tank3))
		{
			clearTank(tank3);
			tank3->CoordX--;
			printTank(tank3);
			renewMap();
		}
	}
	else
	{
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				tank3->Shape[i][j] = tankLeft[i][j];
		clearTank(tank3);
		printTank(tank3);
		tank3->Direction = 3;
		renewMap();
	}
}

//向右后刷新
void turnRight(Object* tank4) {
	int tankRight[3][3] = { { 2,2,0 },{ 0,2,2 },{ 2,2,0 } };
	if (tank4->Direction == 4)
	{
		if (allowGo(tank4))
		{
			clearTank(tank4);
			tank4->CoordX++;
			printTank(tank4);
			renewMap();
		}
	}
	else
	{
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				tank4->Shape[i][j] = tankRight[i][j];
		clearTank(tank4);
		printTank(tank4);
		tank4->Direction = 4;
		renewMap();
	}
}


//监测子弹对存在障碍物的改变,即是碰撞后的改变
void existChange() {
	for (int i = 0; i < 50; i++) {
		int m = ownBullet[i].CoordX;
		int n = ownBullet[i].CoordY;
		if (m > 0 && m < 39 && n>0 && n < 39) {//被我坦克子弹击中
			if (existence[n - 1][m - 1] == 3)//打到土墙
			{
				existence[n - 1][m - 1] = 0;
				gotoXY(2 * m, n);
				printf("  ");
				ownBullet[i].CoordX = 0, ownBullet[i].CoordY = 0;//子弹消失
				printExist();
				renewMap();
			}

			else if (existence[n - 1][m - 1] == 4)//打到钢墙
			{
				ownBullet[i].CoordX = 0, ownBullet[i].CoordY = 0;//子弹消失
			}
		}
	}


	for (int i = 0; i < 3;i++) {
	int m1 = enemyBullet[i].CoordX;
	int n1 = enemyBullet[i].CoordY;

	if (m1 > 0 && m1 < 39 && n1>0 && n1 < 39) {//被敌方各坦克的各个子弹击中
		if (existence[n1 - 1][m1 - 1] == 3)//打到土墙
		{
			existence[n1 - 1][m1 - 1] = 0;
			gotoXY(2 * m1, n1);
			printf("  ");
			enemyBullet[i].CoordX = 0, enemyBullet[i].CoordY = 0;
			printExist();
			renewMap();
		}
		else if (existence[n1 - 1][m1 - 1] == 4)//打到钢墙
		{
			enemyBullet[i].CoordX = 0, enemyBullet[i].CoordY = 0;//子弹消失
		}
		else if (existence[n1 - 1][m1 - 1] == 2)//打到坦克
		{
			enemyBullet[i].CoordX = 0, enemyBullet[i].CoordY = 0;//子弹消失
		}
	}
	else {
		if (m1>40||m1<0||n1>40||n1<0) {
		gotoXY(2 * m1, n1);
		printf("  ");
		enemyBullet[i].CoordX = 0, enemyBullet[i].CoordY = 0;
		printExist();
		renewMap();
		}
	}
	}
}

//监测基地的变化
void baseChange() {
	for (int i = 0; i < 50; i++) {
		int m = ownBullet[i].CoordX;
		int n = ownBullet[i].CoordY;
		if (m == 37 && n == 38 || m == 38 && n == 38) {
			gameOver();
			break;
		}

		for (int a = 0; a < 3; a++) {
			for (int b = 0; b < 3; b++) {//自己子弹对基地的碰撞
				if (m == 36 + 2 * a  && n == 36 + b) {
					if (base.Shape[a][b] == 3) {
						base.Shape[a][b] = 0;
						gotoXY(2 * m, n);
						printf("  ");
						ownBullet[i].CoordX = 0;
						ownBullet[i].CoordY = 0;
						printBase();
						renewMap();
					}
				}
			}
		}
	}


	for (int i = 0; i < 3;i++) {

	int m1 = enemyBullet[i].CoordX;
	int n1 = enemyBullet[i].CoordY;//敌人子弹对基地的碰撞
	if (m1 == 37 && n1 == 38 || m1 == 38 && n1 == 38) {
		gameOver();
		return;
	}

	for (int a = 0; a < 3; a++) {
		for (int b = 0; b < 3; b++) {
			if (m1 == 36 + 2 * a  && n1 == 36 + b) {
				if (base.Shape[a][b] == 3) {
					base.Shape[a][b] = 0;
					gotoXY(2 * m1, n1);
					printf("  ");
					enemyBullet[i].CoordX = 0;
					enemyBullet[i].CoordY = 0;
					printBase();
					renewMap();
				}
			}
		}
	}
	}
}


//游戏结束的显示
void gameOver() {
	system("cls");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	gotoXY(30, 17);
	printf("          游戏结束        ");

	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	gotoXY(32, 23);
	printf("    按 空格键 重新开始或者按 n 返回主菜单    ");

	while (1)
	{
		if (32 == _getch())
		{
			getExistMap();
			renewMap();
			startGame();
			break;
		}
		if('n'== _getch()){
			getExistMap();
			renewMap();
			WelcomeScreen();
			break;
		}
	}
}

//监测游戏是否结束
void checkGame() {
	if (ownTank.HealthPoint == 0)
		gameOver();
	if (enemyCount == 0) {
		printf("您获得游戏的胜利!\n");
		system("pause");
		gameOver();
	}	
}


void getExistMap() {//制造障碍物
	for (int j = 0; j < 38; j++) {
		existence[19][j] = 3;//土墙
		existence[20][j] = 3;
	}

	for (int i = 14; i < 28; i++) {
		existence[21][i] = 4;//钢墙
	}
}


void renewMap() {
	for (int i = 0; i < 40; i++)          //游戏地图初始化
		for (int j = 0; j < 40; j++)
			gameMap[i][j] = 0;

	for (int i = 0; i < 40; i++)    //围墙
	{
		gameMap[i][0] = 4;
		gameMap[i][39] = 4;
	}
	for (int j = 0; j < 40; j++)
	{
		gameMap[0][j] = 4;
		gameMap[39][j] = 4;
	}

	for (int i = 0; i < 38; i++)  //地图所有物
		for (int j = 0; j < 38; j++)
			gameMap[i + 1][j + 1] = existence[i][j];

	for (int i = 0; i < 3; i++)   //基地
		for (int j = 0; j < 3; j++)
			gameMap[i + 36][j + 18] = base.Shape[i][j];

	switch (ownTank.Direction)          //坦克
	{
	case 1:
	{
		gameMap[ownTank.CoordY - 1][ownTank.CoordX - 1] = 0;  gameMap[ownTank.CoordY - 1][ownTank.CoordX] = 2;      gameMap[ownTank.CoordY - 1][ownTank.CoordX + 1] = 0;
		gameMap[ownTank.CoordY][ownTank.CoordX - 1] = 2;    gameMap[ownTank.CoordY][ownTank.CoordX] = 2;        gameMap[ownTank.CoordY][ownTank.CoordX + 1] = 2;
		gameMap[ownTank.CoordY + 1][ownTank.CoordX - 1] = 2;  gameMap[ownTank.CoordY + 1][ownTank.CoordX] = 0;      gameMap[ownTank.CoordY + 1][ownTank.CoordX + 1] = 2;

	}break;
	case 2:
	{
		gameMap[ownTank.CoordY - 1][ownTank.CoordX - 1] = 2;  gameMap[ownTank.CoordY - 1][ownTank.CoordX] = 0;      gameMap[ownTank.CoordY - 1][ownTank.CoordX + 1] = 2;
		gameMap[ownTank.CoordY][ownTank.CoordX - 1] = 2;    gameMap[ownTank.CoordY][ownTank.CoordX] = 0;        gameMap[ownTank.CoordY][ownTank.CoordX + 1] = 2;
		gameMap[ownTank.CoordY + 1][ownTank.CoordX - 1] = 0;  gameMap[ownTank.CoordY + 1][ownTank.CoordX] = 2;      gameMap[ownTank.CoordY + 1][ownTank.CoordX + 1] = 0;

	}break;
	case 3:
	{
		gameMap[ownTank.CoordY - 1][ownTank.CoordX - 1] = 0;  gameMap[ownTank.CoordY - 1][ownTank.CoordX] = 2;      gameMap[ownTank.CoordY - 1][ownTank.CoordX + 1] = 2;
		gameMap[ownTank.CoordY][ownTank.CoordX - 1] = 2;    gameMap[ownTank.CoordY][ownTank.CoordX] = 2;        gameMap[ownTank.CoordY][ownTank.CoordX + 1] = 0;
		gameMap[ownTank.CoordY + 1][ownTank.CoordX - 1] = 0;  gameMap[ownTank.CoordY + 1][ownTank.CoordX] = 2;      gameMap[ownTank.CoordY + 1][ownTank.CoordX + 1] = 2;

	}break;
	case 4:
	{
		gameMap[ownTank.CoordY - 1][ownTank.CoordX - 1] = 2;  gameMap[ownTank.CoordY - 1][ownTank.CoordX] = 2;      gameMap[ownTank.CoordY - 1][ownTank.CoordX + 1] = 0;
		gameMap[ownTank.CoordY][ownTank.CoordX - 1] = 0;    gameMap[ownTank.CoordY][ownTank.CoordX] = 2;        gameMap[ownTank.CoordY][ownTank.CoordX + 1] = 2;
		gameMap[ownTank.CoordY + 1][ownTank.CoordX - 1] = 2;  gameMap[ownTank.CoordY + 1][ownTank.CoordX] = 2;      gameMap[ownTank.CoordY + 1][ownTank.CoordX + 1] = 0;
	}break;
	}

	for (int i = 0; i < 3; i++) {
		switch (enemyTank[i].Direction)  //敌方坦克
		{
		case 1://上
		{
			gameMap[enemyTank[i].CoordY - 1][enemyTank[i].CoordX - 1] = 0;  gameMap[enemyTank[i].CoordY - 1][enemyTank[i].CoordX] = 2;      gameMap[enemyTank[i].CoordY - 1][enemyTank[i].CoordX + 1] = 0;
			gameMap[enemyTank[i].CoordY][enemyTank[i].CoordX - 1] = 2;    gameMap[enemyTank[i].CoordY][enemyTank[i].CoordX] = 2;        gameMap[enemyTank[i].CoordY][enemyTank[i].CoordX + 1] = 2;
			gameMap[enemyTank[i].CoordY + 1][enemyTank[i].CoordX - 1] = 2;  gameMap[enemyTank[i].CoordY + 1][enemyTank[i].CoordX] = 0;      gameMap[enemyTank[i].CoordY + 1][enemyTank[i].CoordX + 1] = 2;

		}break;
		case 2://下
		{
			gameMap[enemyTank[i].CoordY - 1][enemyTank[i].CoordX - 1] = 2;  gameMap[enemyTank[i].CoordY - 1][enemyTank[i].CoordX] = 0;      gameMap[enemyTank[i].CoordY - 1][enemyTank[i].CoordX + 1] = 2;
			gameMap[enemyTank[i].CoordY][enemyTank[i].CoordX - 1] = 2;    gameMap[enemyTank[i].CoordY][enemyTank[i].CoordX] = 0;        gameMap[enemyTank[i].CoordY][enemyTank[i].CoordX + 1] = 2;
			gameMap[enemyTank[i].CoordY + 1][enemyTank[i].CoordX - 1] = 0;  gameMap[enemyTank[i].CoordY + 1][enemyTank[i].CoordX] = 2;      gameMap[enemyTank[i].CoordY + 1][enemyTank[i].CoordX + 1] = 0;

		}break;
		case 3://左
		{
			gameMap[enemyTank[i].CoordY - 1][enemyTank[i].CoordX - 1] = 0;  gameMap[enemyTank[i].CoordY - 1][enemyTank[i].CoordX] = 2;      gameMap[enemyTank[i].CoordY - 1][enemyTank[i].CoordX + 1] = 2;
			gameMap[enemyTank[i].CoordY][enemyTank[i].CoordX - 1] = 2;    gameMap[enemyTank[i].CoordY][enemyTank[i].CoordX] = 2;        gameMap[enemyTank[i].CoordY][enemyTank[i].CoordX + 1] = 0;
			gameMap[enemyTank[i].CoordY + 1][enemyTank[i].CoordX - 1] = 0;  gameMap[enemyTank[i].CoordY + 1][enemyTank[i].CoordX] = 2;      gameMap[enemyTank[i].CoordY + 1][enemyTank[i].CoordX + 1] = 2;

		}break;
		case 4://右
		{
			gameMap[enemyTank[i].CoordY - 1][enemyTank[i].CoordX - 1] = 2;  gameMap[enemyTank[i].CoordY - 1][enemyTank[i].CoordX] = 2;      gameMap[enemyTank[i].CoordY - 1][enemyTank[i].CoordX + 1] = 0;
			gameMap[enemyTank[i].CoordY][enemyTank[i].CoordX - 1] = 0;    gameMap[enemyTank[i].CoordY][enemyTank[i].CoordX] = 2;        gameMap[enemyTank[i].CoordY][enemyTank[i].CoordX + 1] = 2;
			gameMap[enemyTank[i].CoordY + 1][enemyTank[i].CoordX - 1] = 2;  gameMap[enemyTank[i].CoordY + 1][enemyTank[i].CoordX] = 2;      gameMap[enemyTank[i].CoordY + 1][enemyTank[i].CoordX + 1] = 0;
		}break;
		}
	}
}

clock_t time1_start;
clock_t time1_end;
clock_t time2_start;
clock_t time2_end;

void startGame() {
	system("mode con cols=90 lines=45");
	system("title 坦克大战");
	hideCursor();
	printBorder();//打印围墙
	initGame();//初始化数据
	srand((unsigned int)time(NULL));
	while (1) {

		time1_end = clock();
		if (time1_end - time1_start > ownTank.speed)
		{
			time1_start = time1_end;
			tankMove();//自己坦克移动
			ownBulletMove();//自己子弹移动
		}

		time2_end = clock();
		if (time2_end - time2_start > enemyTank[0].speed)
		{
			time2_start = time2_end;

			badTankMove(&enemyTank[0]);//敌军移动
			badTankMove(&enemyTank[1]);
			badTankMove(&enemyTank[2]);

			badTankfire(&enemyTank[0], &enemyBullet[0]);//敌军开火
			enemyBulletMove(&enemyBullet[0]);//敌军子弹移动

			badTankfire(&enemyTank[1], &enemyBullet[1]);
			enemyBulletMove(&enemyBullet[1]);

			badTankfire(&enemyTank[2], &enemyBullet[2]);
			enemyBulletMove(&enemyBullet[2]);

		}
	}
}

int main() {
	WelcomeScreen();//游戏选项,主菜单
	system("pause");
	return 0;
}

2.4 其他逻辑部分设计

子弹逻辑设计

Bullet.h

#pragma once
#include"TankGame.h"

int checkBullet(int x, int y);//检测某位置能否打印子弹
void ownBulletMove();  //自己子弹自动移动
void enemyBulletMove(Object* badTankBullet);//敌人坦克子弹自由移动
void bulletChange();//监测子弹的改变

Bullet.c

#include"TankGame.h"
#include"Tank.h"
#include"Bullet.h"
#include"Draw.h"

int checkBullet(int x, int y)//检测能不能在此打印子弹
{
	if (gameMap[y][x])
		return 0;
	return 1;
}


void ownBulletMove() {
	for (int i = 0; i < 50; i++) {
		int m = ownBullet[i].CoordX;
		int n = ownBullet[i].CoordY;

		if (m != 0 || n != 0)
			if (gameMap[n][m] == 0)//先擦掉		
				clearBullet(ownBullet);

		switch (ownBullet[i].Direction)
		{
		case 1:ownBullet[i].CoordY--; break;
		case 2:ownBullet[i].CoordY++; break;
		case 3:ownBullet[i].CoordX--; break;
		case 4:ownBullet[i].CoordX++; break;
		}

		//检查是否击中障碍物
		existChange();
		//检查是否击中基地
		baseChange();
		//检查是否击中子弹
		bulletChange();
		//检查是否击中敌方坦克
		badTankChange();

		if (checkBullet(ownBullet[i].CoordX, ownBullet[i].CoordY))
			printBullet();
		else
			ownBullet[i].CoordX = 0, ownBullet[i].CoordY = 0;
	}
}



void enemyBulletMove(Object* badTankBullet) {
	int m = badTankBullet->CoordX;
	int n = badTankBullet->CoordY;

	if (m != 0 || n != 0)
		if (gameMap[n][m] == 0) {//先清除掉	
			clearBadBullet(m, n);
		}

	switch (badTankBullet->Direction)
	{
	case 1:badTankBullet->CoordY--; break;
	case 2:badTankBullet->CoordY++; break;
	case 3:badTankBullet->CoordX--; break;
	case 4:badTankBullet->CoordX++; break;
	}

	//检查是否击中障碍物
	existChange();

	//检查是否击中基地
	baseChange();

	//检查是否击中子弹
	bulletChange();

	//检查是否击中我的坦克
	ownTankChange();

	if (badTankBullet->CoordX != 0 && badTankBullet->CoordY != 0) {
		if (checkBullet(badTankBullet->CoordX, badTankBullet->CoordY))
			printBadBullet(badTankBullet);
		else
			badTankBullet->CoordX = 0, badTankBullet->CoordY = 0;
	}
}


//监测子弹碰撞的改变
void bulletChange() {
	for (int i = 0; i < 50; i++) {
		int m = ownBullet[i].CoordX;
		int n = ownBullet[i].CoordY;

		for (int i = 0; i < 3; i++) {//我的坦克子弹和敌人坦克子弹的碰撞

			if (enemyBullet[i].CoordX == m && m != 0 && enemyBullet[i].CoordY == n && n != 0) {
				clearBullet(&ownBullet[i]);//删除我坦克的子弹
				ownBullet[i].CoordX = 0;
				ownBullet[i].CoordY = 0;

				clearBadBullet(enemyBullet[i].CoordX, enemyBullet[i].CoordY);//删除敌方坦克的子弹
				enemyBullet[i].CoordX = 0;
				enemyBullet[i].CoordY = 0;
			}
		}
	}
}

坦克逻辑设计

Tank.h

#pragma once
#include"TankGame.h"

void ownTankChange(); //监测自己坦克的改变
void badTankChange();   //监测敌人坦克的改变
void tankMove();//自己的坦克移动
void badTankMove(Object* badTank);//敌人坦克移动
void ownTankfire();//自己坦克开火
void badTankfire(Object* badTank, Object* badTankBullet);//敌人坦克开火

Tank.c

#include"Tank.h"
#include"Draw.h"
#include"windows.h"
#include"conio.h"
#include"Utils.h"

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

//监测自己坦克状态的改变
void ownTankChange() {

	int x = ownTank.CoordX;
	int y = ownTank.CoordY;

	switch (ownTank.Direction)
	{
	case 1:    //当我的坦克方向向上时
	{
		for (int i = 0; i < 3; i++) {
			int m1 = enemyBullet[i].CoordX;
			int n1 = enemyBullet[i].CoordY;

			if (x == m1 && (y - 1) == n1 || (x - 1) == m1&&y == n1 || x == m1&&y == n1 ||
				(x + 1) == m1&&y == n1 || (x - 1) == m1 && (y + 1) == n1 || (x + 1) == m1 && (y + 1) == n1)
				enemyBullet[i].CoordX = 0,
				enemyBullet[i].CoordY = 0,
				ownTank.HealthPoint--,
				printScoreboard(),
				checkGame(),
				turnUp(&ownTank);
			//坦克子弹消失,生命值减1,检查游戏是否结束,若没结束初始化方向
		}

	}break;
	case 2:
	{
		for (int i = 0; i < 3; i++) {
			int m1 = enemyBullet[i].CoordX;
			int n1 = enemyBullet[i].CoordY;
			if (x == m1 && (y + 1) == n1 || (x - 1) == m1&&y == n1 || x == m1&&y == n1 || (x + 1) == m1&&y == n1 ||
				(x - 1) == m1 && (y - 1) == n1 || (x + 1) == m1 && (y - 1) == n1)
				enemyBullet[i].CoordX = 0,
				enemyBullet[i].CoordY = 0,
				ownTank.HealthPoint--,
				printScoreboard(),
				checkGame(),
				turnUp(&ownTank);
		}

	}break;
	case 3:
	{
		for (int i = 0; i < 3; i++) {
			int m1 = enemyBullet[i].CoordX;
			int n1 = enemyBullet[i].CoordY;
			if (x == m1 && (y - 1) == n1 || (x - 1) == m1&&y == n1 || x == m1&&y == n1 ||
				(x + 1) == m1 && (y - 1) == n1 || x == m1 && (y + 1) == n1 || (x + 1) == m1 && (y + 1) == n1)
				enemyBullet[i].CoordX = 0, enemyBullet[i].CoordY = 0, ownTank.HealthPoint--, printScoreboard(), checkGame(), turnUp(&ownTank);
		}
	}break;
	case 4:
	{
		for (int i = 0; i < 3; i++) {
			int m1 = enemyBullet[i].CoordX;
			int n1 = enemyBullet[i].CoordY;
			if (x == m1 && (y - 1) == n1 || (x - 1) == m1 && (y - 1) == n1 || x == m1&&y == n1 ||
				(x - 1) == m1 && (y + 1) == n1 || x == m1 && (y + 1) == n1 || (x + 1) == m1&&y == n1)
				enemyBullet[i].CoordX = 0,
				enemyBullet[i].CoordY = 0,
				ownTank.HealthPoint--,
				printScoreboard(),
				checkGame(),
				turnUp(&ownTank);
		}
	}break;

	}
}


//监测敌人坦克状态的改变
void badTankChange()
{

	for (int i = 0; i < 50; i++) {
		int m = ownBullet[i].CoordX;
		int n = ownBullet[i].CoordY;

		for (int j = 0; j < 3; j++) {

			int x1 = enemyTank[j].CoordX;
			int y1 = enemyTank[j].CoordY;

			switch (enemyTank[j].Direction)
			{
			case 1:
			{//以坦克中心点开始判断六个点是否与子弹坐标重合
				if (x1 == m && (y1 - 1) == n || (x1 - 1) == m && y1 == n || x1 == m&&y1 == n ||
					(x1 + 1) == m && y1 == n || (x1 - 1) == m && (y1 + 1) == n || (x1 + 1) == m && (y1 + 1) == n) {
					//如果我的坦克子弹打到敌人
					clearTank(&enemyTank[j]); //清除敌军坦克
					enemyTank[j].CoordX = 2 + j * 10;//敌军坦克回到初始位置
					enemyTank[j].CoordY = 2;
					ownBullet[i].CoordX = 0;//我的坦克子弹消失
					ownBullet[i].CoordY = 0;
					enemyCount--; //敌人坦克数量减1
					score = score + 100;//分数加100
					printScoreboard();
					checkGame();//检查游戏是否胜利
				}

			}break;
			case 2:
			{
				if (x1 == m && (y1 + 1) == n || (x1 - 1) == m&&y1 == n || x1 == m&&y1 == n ||
					(x1 + 1) == m&&y1 == n || (x1 - 1) == m && (y1 - 1) == n || (x1 + 1) == m && (y1 - 1) == n) {
					clearTank(&enemyTank[j]);
					enemyTank[j].CoordX = 2 + j * 10;
					enemyTank[j].CoordY = 2;
					ownBullet[i].CoordX = 0;
					ownBullet[i].CoordY = 0;
					enemyCount--;
					score = score + 100;
					printScoreboard();
					checkGame();
				}

			}break;
			case 3:
			{
				if (x1 == m && (y1 - 1) == n || (x1 - 1) == m&&y1 == n || x1 == m&&y1 == n ||
					(x1 + 1) == m && (y1 - 1) == n || x1 == m && (y1 + 1) == n || (x1 + 1) == m && (y1 + 1) == n) {
					clearTank(&enemyTank[j]);
					enemyTank[j].CoordX = 2 + j * 10;
					enemyTank[j].CoordY = 2;
					ownBullet[i].CoordX = 0;
					ownBullet[i].CoordY = 0;
					enemyCount--;
					score = score + 100;
					printScoreboard();
					checkGame();
				}

			}break;
			case 4:
			{
				if (x1 == m && (y1 - 1) == n || (x1 - 1) == m && (y1 - 1) == n || x1 == m&&y1 == n ||
					(x1 - 1) == m && (y1 + 1) == n || x1 == m && (y1 + 1) == n || (x1 + 1) == m&&y1 == n) {
					clearTank(&enemyTank[j]);
					enemyTank[j].CoordX = 2 + j * 10;
					enemyTank[j].CoordY = 2;
					ownBullet[i].CoordX = 0;
					ownBullet[i].CoordY = 0;
					enemyCount--;
					score = score + 100;
					printScoreboard();
					checkGame();
				}
			}break;
			}
		}
	}
}


void ownTankfire() {
	for (int i = 0; i < 50; i++) {
		int m = ownBullet[i].CoordX;
		int n = ownBullet[i].CoordY;

		if (m == 0 && n == 0)//第几个子弹没有,则重新生成子弹
		{
			switch (ownTank.Direction)
			{
			case 1:
			{
				ownBullet[i].CoordX = ownTank.CoordX;
				ownBullet[i].CoordY = ownTank.CoordY - 2;
				ownBullet[i].Direction = 1;
			}break;
			case 2:
			{
				ownBullet[i].CoordX = ownTank.CoordX;;
				ownBullet[i].CoordY = ownTank.CoordY + 2;
				ownBullet[i].Direction = 2;
			}break;
			case 3:
			{
				ownBullet[i].CoordX = ownTank.CoordX - 2;
				ownBullet[i].CoordY = ownTank.CoordY;
				ownBullet[i].Direction = 3;
			}break;
			case 4:
			{
				ownBullet[i].CoordX = ownTank.CoordX + 2;
				ownBullet[i].CoordY = ownTank.CoordY;
				ownBullet[i].Direction = 4;
			}break;
			}

			break;
		}

	}
}


void badTankfire(Object* badTank, Object* badTankBullet) {

	int m = badTankBullet->CoordX;
	int n = badTankBullet->CoordY;

	if (m == 0 && n == 0)//没有坦克的子弹,则重新发射子弹
	{
		switch (badTank->Direction)
		{
		case 1:
		{
			badTankBullet->CoordX = badTank->CoordX;
			badTankBullet->CoordY = badTank->CoordY - 2;
			badTankBullet->Direction = 1;
		}break;
		case 2:
		{
			badTankBullet->CoordX = badTank->CoordX;;
			badTankBullet->CoordY = badTank->CoordY + 2;
			badTankBullet->Direction = 2;
		}break;
		case 3:
		{
			badTankBullet->CoordX = badTank->CoordX - 2;
			badTankBullet->CoordY = badTank->CoordY;
			badTankBullet->Direction = 3;
		}break;
		case 4:
		{
			badTankBullet->CoordX = badTank->CoordX + 2;
			badTankBullet->CoordY = badTank->CoordY;
			badTankBullet->Direction = 4;
		}break;
		}
	}
}


void tankMove() {

	if (KEYDOWN('f') || KEYDOWN('F'))
	{
		ownTankfire();
		return;
	}
	if (KEYDOWN('W') || KEYDOWN('w'))
	{
		turnUp(&ownTank);
		return;
	}
	if (KEYDOWN('s') || KEYDOWN('S'))
	{
		turnDown(&ownTank);
		return;
	}
	if (KEYDOWN('a') || KEYDOWN('A'))
	{
		turnLeft(&ownTank);
		return;
	}
	if (KEYDOWN('d') || KEYDOWN('D'))
	{
		turnRight(&ownTank);
		return;
	}
	if (KEYDOWN('p') || KEYDOWN('P'))
	{
		stopGame();
		return;
	}
	if (KEYDOWN('o') || KEYDOWN('O'))
	{
		exit(0);
		return;
	}
}


void badTankMove(Object* badTank) {

	int direction = (rand() % 4 + 1);
	switch (direction)
	{
	case 1:turnUp(badTank); break;
	case 2:turnDown(badTank); break;
	case 3:turnLeft(badTank); break;
	case 4:turnRight(badTank); break;
	}
}

地图编辑逻辑

editMap.h

#pragma once
#include "windows.h"
#include "editMap.h"

void edit_map();

editMap.c

#include"stdio.h"
#include"stdlib.h"
#include"Utils.h"
#include"windows.h"
#include"conio.h"
#include"TankGame.h"
#include"Draw.h"
#include"editMap.h"

void edit_map() {
	system("cls");

	int x = 1, y = 4;//编辑地图光标的坐标
	int map[38][38] = { 0 };//自定义的地图

	char key;

	for (int i = 0; i < 38; i++)      //初始化
		for (int j = 0; j < 38; j++)
			existence[i][j] = 0;   //置空

	ownTank.CoordX = 6;//初始化坦克
	ownTank.CoordY = 37;
	ownTank.Camp = 1;
	ownTank.Direction = 0;

	//敌方坦克位置的初始化
	for (int i = 0; i < 3; i++) {
		enemyTank[i].CoordX = 2 + i * 15;
		enemyTank[i].CoordY = 2;
		enemyTank[i].Camp = 2;
		enemyTank[i].Direction = 0;
	}

	printBorder();

	int _base[3][3] = { { 3,3,3 },{ 3,2,3 },{ 3,2,3 } };
	for (int i = 0; i < 3; i++)//基地位置初始化
		for (int j = 0; j < 3; j++)
			base.Shape[i][j] = _base[i][j];

	printBase();//打印基地

	int tankUp[3][3] = { { 0,2,0 },{ 2,2,2 },{ 2,0,2 } };
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			ownTank.Shape[i][j] = tankUp[i][j];
	printTank(&ownTank);//编辑地图上打印一个我的坦克

	int tankDown[3][3] = { { 2,0,2 },{ 2,2,2 },{ 0,2,0 } };

	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++) {
			enemyTank[0].Shape[i][j] = tankDown[i][j];
			enemyTank[1].Shape[i][j] = tankDown[i][j];
			enemyTank[2].Shape[i][j] = tankDown[i][j];
		}
	printTank(&enemyTank[0]);//编辑地图上打印三个敌人坦克
	printTank(&enemyTank[1]);
	printTank(&enemyTank[2]);

//	setEnglish();

	int flag = 1;

	while (flag)
	{
		gotoXY(2 * x, y);
		switch (map[y - 1][x - 1])
		{
		case 0:
		{
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),10);
			printf("□");
		}break;
		case 3://土墙
		{
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
			printf("■");
		}break;
		case 4://钢墙
		{
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
			printf("■");
		}break;

		}

		if (_kbhit()) //检测,如果有按键就执行if里面的
		{
			key = _getch();//捕获按键
			switch (key)
			{
			case 72: //上箭头
			{
				if (map[y - 1][x - 1] == 0) {
					gotoXY(2 * x, y);
					printf("  ");
				}
				if (y > 4)    y--;//编辑光标活动范围
			}break;
			case 75: //左箭头
			{
				if (map[y - 1][x - 1] == 0) {
					gotoXY(2 * x, y);
					printf("  ");
				}
				if (x > 1)    x--;//编辑光标活动范围
			}break;
			case 77: //右箭头
			{
				if (map[y - 1][x - 1] == 0) {
					gotoXY(2 * x, y);
					printf("  ");
				}
				if (x < 38)   x++;//编辑光标活动范围
			}break;
			case 80: //下箭头
			{
				if (map[y - 1][x - 1] == 0) {
					gotoXY(2 * x, y);
					printf("  ");
				}
				if (y < 38)   y++;//编辑光标活动范围
			}break;
			case 32: //按空格开始游戏
			{
				if (map[y - 1][x - 1] == 0) {
					gotoXY(2 * x, y);
					printf("  ");
				}
				flag = 0;
			}break;
			case 116:  //t键设置土墙
			{
				map[y - 1][x - 1] = 3;
			}break;
			case 103:  //g 键设置钢墙
			{
				map[y - 1][x - 1] = 4;
			}break;
			case 114:  //r 键清空位置
			{
				map[y - 1][x - 1] = 0;
			}break;
			default:;
			}
		}
	}

	for (int i = 0; i < 38; i++)
		for (int j = 0; j < 38; j++)
			existence[i][j] = map[i][j];//将自定义地图数据保存至地图所有物数组

	renewMap();//刷新地图

	startGame();//开始游戏

	system("cls");

}

三、运行截图和参考代码

游戏运行界面

游戏界面

地图编辑

参考代码下载:

https://download.csdn.net/download/linshantang/88611711

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

攻城狮7号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值