首先是保存地图的文件
map.h头文件
#pragma once
#include<windows.h>
#define N 39
#define 边界 0
#define 空地 1
#define 土墙 2
#define 铁墙 3
int g_Map[N + 2][N + 2] ;
int g_Map1[N + 2][N + 2];
//初始化边界
void Init();
//打印地图
void PtfMap();
//绘制地图
void DrawMap();
map.c源文件
#include"map.h"
g_Map1[41][41] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 3, 3, 3, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 3, 3, 3, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 3, 3, 3, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
, 0, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 0
, 0, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 0
, 0, 3, 3, 3, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 3, 3, 0
, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0
, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
//初始化边界
void Init()
{
memset(g_Map, 0, sizeof(g_Map));
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
g_Map[i][j] = 1;
}
}
Color(0xF);
for (int i = 0; i <= N + 1; i++)
{
Posxy(i, 0);
printf("━");
Posxy(i, N + 1);
printf("━");
}
for (int i = 0; i <= N + 1; i++)
{
Posxy(0, i);
printf("┃");
Posxy(N + 1, i);
printf("┃");
}
Posxy(0, 0);
printf("┏");
Posxy(N + 1, 0);
printf("┓");
Posxy(0, N + 1);
printf("┗");
Posxy(N + 1, N + 1);
printf("┛");
}
//打印地图
void PtfMap()
{
Posxy(0, 0);
for (int i = 0; i <= N; i++)
{
for (int j = 0; j <= N; j++)
{
if (g_Map1[i][j] == 边界)
{
Color(0);
printf("□");
}
else if (g_Map1[i][j] == 空地)
{
Color(0);
printf(" ");
}
else if (g_Map1[i][j] == 土墙)
{
Color(6);
printf("■");
}
else if (g_Map1[i][j] == 铁墙)
{
Color(7);
printf("■");
}
}
putchar('\n');
}
}
//绘制地图
void DrawMap()
{
int tEND = 1;//判断是否结束画墙
memset(g_Map1, 0, sizeof(g_Map1));
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
g_Map1[i][j] = 1;
}
}
int Arr[3] = { 土墙,铁墙 };
int nColor = 6;
int List = 0;
system("cls");
Init();
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD stcRecord = { 0 };
DWORD dwRead;
SetConsoleMode(hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);//sxq
Posxy(42, 3);
printf("按1切换为土墙");
Posxy(42, 5);
printf("按2切换为铁墙");
Posxy(42, 7);
printf("右键清除为空地");
Posxy(42, 9);
printf("按B保存地图");
while (tEND)
{
ReadConsoleInput(hStdin, &stcRecord, 1, &dwRead);
if (stcRecord.EventType == KEY_EVENT)
{
KEY_EVENT_RECORD ker = stcRecord.Event.KeyEvent;
//键盘事件
if (ker.bKeyDown)
{
switch (ker.wVirtualKeyCode)
{
case '1':
List = 0;
nColor = 6;
break;
case '2':
List = 1;
nColor = 7;
break;
case 'b':case 'B':
tEND = 0;
break;
}
}
}
if (stcRecord.EventType == MOUSE_EVENT)
{
//鼠标事件
MOUSE_EVENT_RECORD mer = stcRecord.Event.MouseEvent;
if (mer.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
{
if (mer.dwMousePosition.X / 2 < N + 1 && mer.dwMousePosition.Y < N + 1)
{
if (mer.dwMousePosition.X / 2 != 0 && mer.dwMousePosition.Y != 0)
{
Posxy(mer.dwMousePosition.X / 2, mer.dwMousePosition.Y);
Color(nColor);
printf("■");
g_Map1[mer.dwMousePosition.Y ][mer.dwMousePosition.X/2] =Arr[List];
}
}
}
else if (mer.dwButtonState == RIGHTMOST_BUTTON_PRESSED)
{
if (mer.dwMousePosition.X / 2 < N + 1 && mer.dwMousePosition.Y < N + 1)
{
if (mer.dwMousePosition.X / 2 != 0 && mer.dwMousePosition.Y != 0)
{
Posxy(mer.dwMousePosition.X / 2, mer.dwMousePosition.Y);
printf(" ");
g_Map1[mer.dwMousePosition.Y ][mer.dwMousePosition.X/2] = 1;
}
}
}
}
}
//system("pause");
}
tank.h头文件
#pragma once
#include<windows.h>
#include"map.h"
#define UP 1
#define DOWN 2
#define LEFT 3
#define RIGHT 4
typedef struct
{
COORD Pos;
int Direction; //坦克方向
unsigned int BulletCD; //判断发射CD
char IfMe;
char Life;
int HP;
}Tank;
int TankAINum ;
Tank TankAI[80];
//打印坦克并将对应数据写入地图
void TankPtfA(Tank tank);
//擦除坦克并将对应数据从地图中擦除
void ErasureTank(Tank tank);
//判断坦克移动是否有效,如果无效则将坦克坐标返回
void IfMove(Tank* tank);
//坦克移动
void TankMove(Tank* tank);
//创建坦克AI
int CreatTankAI(Tank *tank);
//坦克AI移动
void TankAIMove(Tank *tank);
tank.c文件
#include"tank.h"
TankAINum = 0;
//打印坦克并将对应数据写入地图
void TankPtfA(Tank tank)
{
if (tank.IfMe)
{
Color(0xF);
}
else
{
Color(10);
}
if (tank.Direction == 1)
{
Posxy(tank.Pos.X - 1, tank.Pos.Y - 1);
printf("┏ ↑┓");//←→↓
Posxy(tank.Pos.X - 1, tank.Pos.Y);
printf("┃ ○┃");
Posxy(tank.Pos.X - 1, tank.Pos.Y + 1);
printf("┗ ━ ┛");
}
else if (tank.Direction == 2)
{
Posxy(tank.Pos.X - 1, tank.Pos.Y - 1);
printf("┏ ━ ┓");//←→↓
Posxy(tank.Pos.X - 1, tank.Pos.Y);
printf("┃ ○┃");
Posxy(tank.Pos.X - 1, tank.Pos.Y + 1);
printf("┗ ↓┛");
}
else if (tank.Direction == 3)
{
Posxy(tank.Pos.X - 1, tank.Pos.Y - 1);
printf("┏ ━ ┓");//←→↓
Posxy(tank.Pos.X - 1, tank.Pos.Y);
printf("←○┃");
Posxy(tank.Pos.X - 1, tank.Pos.Y + 1);
printf("┗ ━ ┛");
}
else if (tank.Direction == 4)
{
Posxy(tank.Pos.X - 1, tank.Pos.Y - 1);
printf("┏ ━ ┓");//←→↓
Posxy(tank.Pos.X - 1, tank.Pos.Y);
printf("┃ ○→");
Posxy(tank.Pos.X - 1, tank.Pos.Y + 1);
printf("┗ ━ ┛");
}
g_Map1[tank.Pos.Y][tank.Pos.X - 1] = 9;
g_Map1[tank.Pos.Y][tank.Pos.X] = 9;
g_Map1[tank.Pos.Y][tank.Pos.X + 1] = 9;
g_Map1[tank.Pos.Y - 1][tank.Pos.X - 1] = 9;
g_Map1[tank.Pos.Y - 1][tank.Pos.X] = 9;
g_Map1[tank.Pos.Y - 1][tank.Pos.X + 1] = 9;
g_Map1[tank.Pos.Y + 1][tank.Pos.X - 1] = 9;
g_Map1[tank.Pos.Y + 1][tank.Pos.X] = 9;
g_Map1[tank.Pos.Y + 1][tank.Pos.X + 1] = 9;
}
//擦除坦克并将对应数据从地图中擦除
void ErasureTank(Tank tank)
{
Posxy(tank.Pos.X - 1, tank.Pos.Y - 1);
printf(" ");
Posxy(tank.Pos.X - 1, tank.Pos.Y);
printf(" ");
Posxy(tank.Pos.X - 1, tank.Pos.Y + 1);
printf(" ");
g_Map1[tank.Pos.Y][tank.Pos.X - 1] = 1;
g_Map1[tank.Pos.Y][tank.Pos.X] = 1;
g_Map1[tank.Pos.Y][tank.Pos.X + 1] = 1;
g_Map1[tank.Pos.Y - 1][tank.Pos.X - 1] = 1;
g_Map1[tank.Pos.Y - 1][tank.Pos.X] = 1;
g_Map1[tank.Pos.Y - 1][tank.Pos.X + 1] = 1;
g_Map1[tank.Pos.Y + 1][tank.Pos.X - 1] = 1;
g_Map1[tank.Pos.Y + 1][tank.Pos.X] = 1;
g_Map1[tank.Pos.Y + 1][tank.Pos.X + 1] = 1;
}
//判断坦克移动是否有效,如果无效则将坦克坐标返回
void IfMove(Tank* tank)
{
COORD TPos = tank->Pos;
switch (tank->Direction)
{
case UP:
{
if (g_Map1[TPos.Y - 1][TPos.X - 1] != 1 || g_Map1[TPos.Y - 1][TPos.X] != 1 || g_Map1[TPos.Y - 1][TPos.X + 1] != 1)
tank->Pos.Y++;
break;
}
case DOWN:
{
if (g_Map1[TPos.Y + 1][TPos.X - 1] != 1 || g_Map1[TPos.Y + 1][TPos.X] != 1 || g_Map1[TPos.Y + 1][TPos.X + 1] != 1)
tank->Pos.Y--;
break;
}
case LEFT:
{
if (g_Map1[TPos.Y - 1][TPos.X - 1] != 1 || g_Map1[TPos.Y][TPos.X - 1] != 1 || g_Map1[TPos.Y + 1][TPos.X - 1] != 1)
tank->Pos.X++;
break;
}
case RIGHT:
{
if (g_Map1[TPos.Y - 1][TPos.X + 1] != 1 || g_Map1[TPos.Y][TPos.X + 1] != 1 || g_Map1[TPos.Y + 1][TPos.X + 1] != 1)
tank->Pos.X--;
break;
}
}
}
//坦克移动
void TankMove(Tank* tank)
{
ErasureTank(*tank);
switch (tank->Direction)
{
case UP:tank->Pos.Y--; break;
case DOWN:tank->Pos.Y++; break;
case LEFT:tank->Pos.X--; break;
case RIGHT:tank->Pos.X++; break;
}
IfMove(tank);
TankPtfA(*tank);
}
//创建坦克AI
int CreatTankAI(Tank *tank)
{
switch (rand() % 3)
{
case 0:
{
tank->Pos.X = 3;
tank->Pos.Y = 2;
break;
}
case 1:
{
tank->Pos.X = 38;
tank->Pos.Y = 2;
break;
}
case 2:
{
tank->Pos.X = 20;
tank->Pos.Y = 2;
break;
}
}
tank->Direction = rand() % 4 + 1;
tank->IfMe = 0;
tank->Life = 1;
tank->BulletCD = 0;
tank->HP = 1;
if (g_Map1[tank->Pos.Y][tank->Pos.X] == 1
&& g_Map1[tank->Pos.Y - 1][tank->Pos.X - 1] == 1
&& g_Map1[tank->Pos.Y - 1][tank->Pos.X] == 1
&& g_Map1[tank->Pos.Y - 1][tank->Pos.X + 1] == 1
&& g_Map1[tank->Pos.Y][tank->Pos.X - 1] == 1
&& g_Map1[tank->Pos.Y][tank->Pos.X + 1] == 1
&& g_Map1[tank->Pos.Y + 1][tank->Pos.X + 1] == 1
&& g_Map1[tank->Pos.Y + 1][tank->Pos.X - 1] == 1
&& g_Map1[tank->Pos.Y + 1][tank->Pos.X] == 1)
{
g_Map1[tank->Pos.Y][tank->Pos.X] = 9;
g_Map1[tank->Pos.Y - 1][tank->Pos.X - 1] = 9;
g_Map1[tank->Pos.Y - 1][tank->Pos.X] = 9;
g_Map1[tank->Pos.Y - 1][tank->Pos.X + 1] = 9;
g_Map1[tank->Pos.Y][tank->Pos.X - 1] = 9;
g_Map1[tank->Pos.Y][tank->Pos.X + 1] = 9;
g_Map1[tank->Pos.Y + 1][tank->Pos.X + 1] = 9;
g_Map1[tank->Pos.Y + 1][tank->Pos.X - 1] = 9;
g_Map1[tank->Pos.Y + 1][tank->Pos.X] = 9;
return 1;
}
else
{
return 0;
}
}
//坦克AI移动
void TankAIMove(Tank *tank)
{
ErasureTank(*tank);
switch (tank->Direction)
{
case UP:tank->Pos.Y--; break;
case DOWN:tank->Pos.Y++; break;
case LEFT:tank->Pos.X--; break;
case RIGHT:tank->Pos.X++; break;
}
IfMove(tank);
if (rand() % 5 == 0)
{
switch (rand() % 5)
{
case UP:tank->Direction = UP; break;
case DOWN:tank->Direction = DOWN; break;
case LEFT:tank->Direction = LEFT; break;
case RIGHT:tank->Direction = RIGHT; break;
default:break;
}
}
TankPtfA(*tank);
}
void CreatPlayer(Tank *Player)
{
Player->Pos.X = 14;
Player->Pos.Y = 38;
Player->Direction = 1;
Player->BulletCD = 0;
Player->IfMe = 1;
Player->Life = 1;
}
bullet.h
#pragma once
#include<windows.h>
#include"tank.h"
typedef struct
{
COORD Pos;
int Direction;
char IfMe;
}Bullet;
int g_BulletNum ;
Bullet g_BulletArr[20];
//子弹移动
void BulletMove(Bullet* bullet);
//创建子弹
void CreatBullet(Tank *tank);
//判断子弹碰撞箱
int Box(COORD BoxA, COORD BoxB);
//子弹碰撞判断
void BulletTest(Tank* tank);
bullet.c
#include"bullet.h"
g_BulletNum = 0;
//子弹移动
void BulletMove(Bullet* bullet)
{
Posxy(bullet->Pos.X, bullet->Pos.Y);
printf(" ");
switch (bullet->Direction)
{
case UP:bullet->Pos.Y--; break;
case DOWN:bullet->Pos.Y++; break;
case LEFT:bullet->Pos.X--; break;
case RIGHT:bullet->Pos.X++; break;
}
Posxy(bullet->Pos.X, bullet->Pos.Y);
if (bullet->IfMe == 1)
{
Color(0xF);
}
else
{
Color(10);
}
printf("*");
}
//创建子弹
void CreatBullet(Tank *tank)
{
g_BulletArr[g_BulletNum].Direction = tank->Direction;
g_BulletArr[g_BulletNum].IfMe = tank->IfMe;
if (tank->IfMe == 0)
{
tank->BulletCD += 15;
}
switch (tank->Direction)
{
case UP:
if (tank->Pos.Y - 2 > 0)
{
g_BulletArr[g_BulletNum].Pos.X = tank->Pos.X;
g_BulletArr[g_BulletNum].Pos.Y = tank->Pos.Y - 2;
g_BulletNum++;
}
break;
case DOWN:
if (tank->Pos.Y + 2 < N + 1)
{
g_BulletArr[g_BulletNum].Pos.X = tank->Pos.X;
g_BulletArr[g_BulletNum].Pos.Y = tank->Pos.Y + 2;
g_BulletNum++;
}
break;
case LEFT:
if (tank->Pos.X - 2 > 0)
{
g_BulletArr[g_BulletNum].Pos.X = tank->Pos.X - 2;
g_BulletArr[g_BulletNum].Pos.Y = tank->Pos.Y;
g_BulletNum++;
}
break;
case RIGHT:
if (tank->Pos.X + 2 < N + 1)
{
g_BulletArr[g_BulletNum].Pos.X = tank->Pos.X + 2;
g_BulletArr[g_BulletNum].Pos.Y = tank->Pos.Y;
g_BulletNum++;
}
break;
}
}
//判断子弹碰撞箱
int Box(COORD BoxA, COORD BoxB)
{
if (BoxA.X == BoxB.X || BoxA.X == BoxB.X - 1 || BoxA.X == BoxB.X + 1)
{
if (BoxA.Y == BoxB.Y || BoxA.Y == BoxB.Y - 1 || BoxA.Y == BoxB.Y + 1)
{
return 1;
}
}
return 0;
}
//子弹碰撞判断
void BulletTest(Tank* tank)
{
int IfMove = 1;
if (GetAsyncKeyState(VK_SHIFT) && tank->BulletCD <= 1)
{
CreatBullet(tank);
tank->BulletCD += 7;
}
for (int i = 0; i < g_BulletNum; i++) //遍历子弹坐标
{
if (g_Map1[g_BulletArr[i].Pos.Y][g_BulletArr[i].Pos.X] == 2) //判断子弹击中土墙
{
switch (g_BulletArr[i].Direction) //判断子弹方向
{
case UP:
case DOWN:
{
g_Map1[g_BulletArr[i].Pos.Y][g_BulletArr[i].Pos.X] = 1; //如果为上下则判断击中土墙左右是否为土墙
Posxy(g_BulletArr[i].Pos.X, g_BulletArr[i].Pos.Y); //如果是土墙则清除
printf(" ");
if (g_Map1[g_BulletArr[i].Pos.Y][g_BulletArr[i].Pos.X - 1] == 2)
{
g_Map1[g_BulletArr[i].Pos.Y][g_BulletArr[i].Pos.X - 1] = 1;
Posxy(g_BulletArr[i].Pos.X - 1, g_BulletArr[i].Pos.Y);
printf(" ");
}
if (g_Map1[g_BulletArr[i].Pos.Y][g_BulletArr[i].Pos.X + 1] == 2)
{
g_Map1[g_BulletArr[i].Pos.Y][g_BulletArr[i].Pos.X + 1] = 1;
Posxy(g_BulletArr[i].Pos.X + 1, g_BulletArr[i].Pos.Y);
printf(" ");
}
break;
}
case LEFT:
case RIGHT:
{
g_Map1[g_BulletArr[i].Pos.Y][g_BulletArr[i].Pos.X] = 1; //如果方向为左右则判断土墙上下是否为土墙
Posxy(g_BulletArr[i].Pos.X, g_BulletArr[i].Pos.Y); //如果有土墙则清除
printf(" ");
if (g_Map1[g_BulletArr[i].Pos.Y - 1][g_BulletArr[i].Pos.X] == 2)
{
g_Map1[g_BulletArr[i].Pos.Y - 1][g_BulletArr[i].Pos.X] = 1;
Posxy(g_BulletArr[i].Pos.X, g_BulletArr[i].Pos.Y - 1);
printf(" ");
}
if (g_Map1[g_BulletArr[i].Pos.Y + 1][g_BulletArr[i].Pos.X] == 2)
{
g_Map1[g_BulletArr[i].Pos.Y + 1][g_BulletArr[i].Pos.X] = 1;
Posxy(g_BulletArr[i].Pos.X, g_BulletArr[i].Pos.Y + 1);
printf(" ");
}
break;
}
}
for (int j = i; j < g_BulletNum - 1; j++) //最后将该子弹清除
{
g_BulletArr[j] = g_BulletArr[j + 1];
}
g_BulletNum--;
IfMove = 0;
}
else if (g_Map1[g_BulletArr[i].Pos.Y][g_BulletArr[i].Pos.X] == 3) //判断击中铁墙
{
Posxy(g_BulletArr[i].Pos.X, g_BulletArr[i].Pos.Y); //将铁墙打印出来后,清除该子弹
Color(7);
printf("■");
for (int j = i; j < g_BulletNum - 1; j++)
{
g_BulletArr[j] = g_BulletArr[j + 1];
}
g_BulletNum--;
IfMove = 0;
}
if (IfMove)
{
BulletMove(&g_BulletArr[i]); //子弹根据方向移动
}
for (int j = 0; j < g_BulletNum; j++) //再次遍历所有子弹坐标
{
if (j == i) //如果i==j则判断是同一个子弹数据
{
continue;
}
//判断两个子弹的坐标相同
if (g_BulletArr[i].Pos.X == g_BulletArr[j].Pos.X&&g_BulletArr[i].Pos.Y == g_BulletArr[j].Pos.Y)
{
if (g_BulletArr[i].IfMe != g_BulletArr[j].IfMe) //坐标相同子弹的敌我判定,决定是否清除
{
Posxy(g_BulletArr[i].Pos.X, g_BulletArr[i].Pos.Y);
printf(" "); //先将对应坐标图案擦除
if (j > i) //判断子弹在数组中的先后决定清除顺序
{ //防止清除靠前的数据后,靠后的数据清除错误
for (int t = j; t < g_BulletNum - 1; t++)
{
g_BulletArr[t] = g_BulletArr[t + 1];
}
g_BulletNum--;
for (int t = i; t < g_BulletNum - 1; t++)
{
g_BulletArr[t] = g_BulletArr[t + 1];
}
g_BulletNum--;
}
else
{
for (int t = i; t < g_BulletNum - 1; t++)
{
g_BulletArr[t] = g_BulletArr[t + 1];
}
g_BulletNum--;
for (int t = j; t < g_BulletNum - 1; t++)
{
g_BulletArr[t] = g_BulletArr[t + 1];
}
g_BulletNum--;
}
return 0;
}
}
}
if (g_BulletArr[i].IfMe == 1) //判断子弹为我方
{
for (int Temp = 0; Temp < TankAINum; Temp++) //遍历AI坦克坐标
{
if (Box(g_BulletArr[i].Pos, TankAI[Temp].Pos)) //如果我方子弹击中AI坦克碰撞箱
{
TankAI[Temp].HP = 0;
ErasureTank(TankAI[Temp]);
for (int TempB = Temp; TempB < TankAINum - 1; TempB++)
{
TankAI[TempB] = TankAI[TempB + 1];
}
TankAINum--;
Posxy(g_BulletArr[i].Pos.X, g_BulletArr[i].Pos.Y);
printf(" ");
for (int j = i; j < g_BulletNum - 1; j++) //该子弹清除
{
g_BulletArr[j] = g_BulletArr[j + 1];
}
g_BulletNum--;
return 0;
}
}
}
else //判断子弹为敌方
{
if (Box(g_BulletArr[i].Pos, tank->Pos)) //判断子弹是否击中玩家坦克碰撞箱
{
tank->HP--;
tank->Life = 0;
ErasureTank(*tank);
Posxy(g_BulletArr[i].Pos.X, g_BulletArr[i].Pos.Y);
printf(" ");
for (int j = i; j < g_BulletNum - 1; j++) //清除该子弹
{
g_BulletArr[j] = g_BulletArr[j + 1];
}
g_BulletNum--;
return 0;
}
}
if (g_Map[g_BulletArr[i].Pos.X][g_BulletArr[i].Pos.Y] == 0) //如果子弹打到边界
{
if (g_BulletArr[i].Pos.X == 0 || g_BulletArr[i].Pos.X == N + 1)
{
Posxy(g_BulletArr[i].Pos.X, g_BulletArr[i].Pos.Y);
Color(0xF);
printf("┃");
}
else
{
Posxy(g_BulletArr[i].Pos.X, g_BulletArr[i].Pos.Y);
Color(0xF);
printf("━");
}
for (int j = i; j < g_BulletNum - 1; j++) //将子弹数组依次覆盖当前被消除的下标
{
g_BulletArr[j] = g_BulletArr[j + 1];
}
g_BulletNum--; //子弹总数自减1
}
}
}
control.h
#pragma once
#include<windows.h>
#include<stdio.h>
#include"tank.h"
#include"bullet.h"
//隐藏光标
void ShowCursorA();
//移动光标
void Posxy(int x, int y);
//更改输出颜色
void Color(int color);
//设置控制台窗口及缓冲区大小
int SetWindowsSize(char *pszWindowTitle, int nX, int nY);
//获取键盘输入
void GetPlayerInput(Tank* tank);
//控制游戏进行
void Game(int IfLoad);
//菜单
void Menu();
//暂停
void Pause();
//存档
void Save(Tank *tank);
//读档
void Load(Tank *tank);
control.c
#include"control.h"
void ShowCursorA()
{
HANDLE hOutStd = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cci;
cci.dwSize = 1;
cci.bVisible = 0;
SetConsoleCursorInfo(hOutStd, &cci);
}
void Posxy(int x, int y)
{
COORD Pos;
HANDLE hOus = GetStdHandle(STD_OUTPUT_HANDLE);
Pos.X = x * 2;
Pos.Y = y;
SetConsoleCursorPosition(hOus, Pos);
}
void Color(int color)
{
HANDLE hOutstd = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOutstd, color);
}
//设置控制台窗口及缓冲区大小
int SetWindowsSize(char *pszWindowTitle,int nX,int nY)
{
//设置控制台标题
SetConsoleTitleA(pszWindowTitle);
HANDLE hStdin, hStdout;
hStdin = GetStdHandle(STD_INPUT_HANDLE);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
//获取最大控制台窗口大小
COORD pos = GetLargestConsoleWindowSize(hStdout);
COORD BufferSize = { pos.X + 1, pos.Y + 1 };
//设置控制台缓冲区大小
if (!SetConsoleScreenBufferSize(hStdout, BufferSize))
{
//设置控制台缓冲区失败
printf("buffer err(%d %d) %d\n", BufferSize.X, BufferSize.Y, GetLastError());
return 0;
}
SMALL_RECT srctWindow = { 0, 0, nX, nY };
if (!SetConsoleWindowInfo(hStdout, 1, &srctWindow))
{
//设置控制台窗口大小
printf("size err %d\n", GetLastError());
return 0;
}
COORD Buffer = { nX + 1, nY + 1 };
//设置控制台缓冲区大小
if (!SetConsoleScreenBufferSize(hStdout, Buffer))
{
//设置控制台窗口缓冲区失败
printf("buffer err(%d %d) %d\n", BufferSize.X, BufferSize.Y, GetLastError());
return 0;
}
return 1;
}
//获取键盘输入
void GetPlayerInput(Tank* tank)
{
COORD A = { 30, 30 };
if (GetAsyncKeyState(VK_SPACE))
{
Save(tank);
Pause();
}
else if (GetAsyncKeyState(VK_DOWN))
{
tank->Direction = 2;
TankMove(tank);
}
else if (GetAsyncKeyState(VK_LEFT))
{
tank->Direction = 3;
TankMove(tank);
}
else if (GetAsyncKeyState(VK_RIGHT))
{
tank->Direction = 4;
TankMove(tank);
}
else if (GetAsyncKeyState(VK_ESCAPE))
{
exit(0);
}
else if (GetAsyncKeyState(VK_UP))
{
tank->Direction = 1;
TankMove(tank);
}
}
//控制游戏进行
void Game(int IfLoad)
{
int nCount = 0; //计数器,防止坦克移动过快
Tank Player; //坦克初始化
if (IfLoad == 1)
{
Player.HP = 3;
CreatPlayer(&Player);
}
else
{
Load(&Player);
/*for (int i = 0; i < TankAINum; i++)
{
TankPtfA(TankAI[i]);
}*/
}
PtfMap(); //打印地图
Init(); //初始化边界
TankPtfA(Player);
while (1)
{
if (Player.HP > 0)
{
if (Player.Life == 0)
{
if (g_Map1[38][14] == 1
&& g_Map1[37][13] == 1
&& g_Map1[37][14] == 1
&& g_Map1[37][15] == 1
&& g_Map1[38][13] == 1
&& g_Map1[38][15] == 1
&& g_Map1[39][13] == 1
&& g_Map1[39][15] == 1
&& g_Map1[39][14] == 1)
{
CreatPlayer(&Player);
TankPtfA(Player);
}
}
}
else
{
Posxy(0, 43);
printf("Game Over!");
system("pause");
break;
}
if (TankAINum == 0)
{
if (CreatTankAI(&TankAI[TankAINum]))
{
TankPtfA(TankAI[TankAINum]);
TankAINum++;
}
}
if (nCount % 1 == 0)
{
if (TankAINum < 80)
{
if (CreatTankAI(&TankAI[TankAINum]))
{
TankPtfA(TankAI[TankAINum]);
TankAINum++;
}
}
}
if (nCount % 2 == 0)
{
for (int i = 0; i < TankAINum; i++)
{
TankAIMove(&TankAI[i]);
if (TankAI[i].BulletCD >= 1)
TankAI[i].BulletCD--;
if (TankAI[i].BulletCD <= 1)
{
CreatBullet(&TankAI[i]);
}
}
}
BulletTest(&Player);
if (Player.BulletCD != 0)
Player.BulletCD--;
nCount++;
if (nCount % 2 == 0 && Player.Life == 1) //每循环两次才能移动
{
GetPlayerInput(&Player);
}
Sleep(60);
Posxy(43, 7);
Color(0xF);
printf("HP:%3d", Player.HP);
}
}
//菜单
void Menu()
{
while (1)
{
system("cls");
Color(0xF);
printf("1.开始游戏\n");
printf("2.读取存档\n");
printf("3.绘制地图\n");
printf("4.退出游戏\n");
char ch = getchar();
switch (ch)
{
case '1':
system("cls");
Game(1);
break;
case '2':
system("cls");
Game(0);
break;
case '3':
system("cls");
DrawMap();
break;
case '4':exit(0); break;
}
}
}
//暂停
void Pause()
{
//Posxy(0, 44);
//printf("再次按下空格回到游戏");
while (1)
{
Sleep(200);
if (GetAsyncKeyState(VK_SPACE))break;
}
}
void Save(Tank *tank)
{
FILE *fp;
for (int i = 0; i < TankAINum; i++)
{
ErasureTank(TankAI[i]);
}
ErasureTank(*tank);
if (fopen_s(&fp, "INFO.txt", "wb"))printf("error");
fwrite(g_Map1, sizeof(g_Map1), 1, fp);
fwrite(&g_BulletNum, sizeof(int), 1, fp);
fwrite(g_BulletArr, sizeof(g_BulletArr), 1, fp);
fwrite(&TankAINum, sizeof(int), 1, fp);
fwrite(TankAI, sizeof(TankAI), 1, fp);
fwrite(tank, sizeof(Tank), 1, fp);
fclose(fp);
for (int i = 0; i < TankAINum; i++)
{
TankPtfA(TankAI[i]);
}
TankPtfA(*tank);
//Posxy(0, 43);
//printf("OK");
}
void Load(Tank *tank)
{
FILE *fp;
if (fopen_s(&fp, "INFO.txt", "rb"))printf("error");
fread(g_Map1, sizeof(g_Map1), 1, fp);
fread(&g_BulletNum, sizeof(int), 1, fp);
fread(&g_BulletArr[0], sizeof(g_BulletArr), 1, fp);
fread(&TankAINum, sizeof(int), 1, fp);
fread(TankAI, sizeof(TankAI), 1, fp);
fread(tank, sizeof(Tank), 1, fp);
fclose(fp);
}
main.c
#include<windows.h>
#include<time.h>
#include"Map.h"
#include"control.h"
#include"tank.h"
#include"bullet.h"
int main()
{
srand((unsigned)time(NULL));
//system("mode con cols=100 lines=43");
SetWindowsSize("坦克小战", 100, 43);
ShowCursorA();
Menu();
return 0;
}