C语言——坦克大战
Posted 机智蛋蛋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言——坦克大战相关的知识,希望对你有一定的参考价值。
最近在学习C语言,闲来无事,花了3天搞了个坦克大战。代码粗陋,大佬勿喷~
坦克大战效果图:
坦克大战流程图:
1、键盘信号获取
由 _kbhit(),_getch() ,函数获取
_kbhit()检测有没有键按下
_getch()读取键值
2、坦克模型
typedef struct Tank
{
int id;//坦克ID
int x;
int y;
int tankType;//0 普通坦克 1 打三次才会爆炸的坦克 2速度型坦克
int blood;//血条
int moveSpeed;//移动速度
int moveCount;//计数,当计数等于moveSpeed 则移动一步
int lives;//生命
int distance;//移动距离 1 ~ 20 格
int invincibleCount;//无敌时间计数
Bullet bullet;//子弹 结构体
bool overLapping;//检测坦克刚出来时敌我双方是否重叠
bool hasShow;//坦克是否已经显示在地图上
bool propsTank;//爆炸后随机出现道具
BYTE camp;//阵营 0 我方 1 敌方
BYTE direction; //移动方向 0 上 1 右 2下 3左
Tank *pNextTank;
}TANK, *PTANK;
(1)坦克在控制台上表现是9个方块,显示上下左右的图案。
(2)敌方坦克数据使用链表存储
(3)敌方坦克自动移动,随机移动距离,随机移动方向
3、子弹模型
struct Bullet
{
int x;
int y;
int speed;//子弹速度
int speedCount;//子弹速度计数,当计数等于speed则子弹移动一步
int shootCount;//发射子弹倒计时
BYTE direction;//子弹方向 0 上 1 右 2下 3左
bool fly;//子弹是否还在飞行
};
(1)在控制台上表现是一个小方块,随着线程循环移动
4、道具模型
typedef struct Props
{
int x;
int y;
int disappear;//道具消失计时
BYTE type;//道具类型 0 生命+1 1 城堡临时加固 2无敌金身 3地雷敌军全体爆炸
Props* pNext;
}PROPS, *PPROPS;
(1)条件有限,道具就在控制台上打印了中文字符:生命、地雷、加固、无敌,共4种道具
5、光标跳转到指定位置
void gotoxy(int x, int y, int ForgC)
{
if(ForgC == -1)
{
ForgC = LIGHTGREEN;
}
// 更新光标位置
COORD pos;
WORD wColor;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(hOutput, pos);
CONSOLE_SCREEN_BUFFER_INFO csbi;
if(GetConsoleScreenBufferInfo(hOutput, &csbi))
{
//设置字体颜色
wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);
SetConsoleTextAttribute(hOutput, wColor);
}
// 隐藏光标
CONSOLE_CURSOR_INFO cursor;
cursor.bVisible = FALSE;
cursor.dwSize = 1; //值介于1 ~ 100 之间 单元格底部为下划线 ~ 完全填充单元格
SetConsoleCursorInfo(hOutput, &cursor);
}
这样方便将光标移动到指定位置打印字符或者删除字符。
6、判断游戏是否结束
(1)敌方全部消灭
(2)我方生命清零
(3)城堡被攻陷
7、子弹碰撞检测
(1)检测子弹是否碰到游戏边界
(2)检测子弹是否碰到游戏障碍物(砖块或铁块)
(3)检测我方子弹是否碰到敌方坦克,敌方子弹是否碰到我方坦克
(4)检测我方子弹是否碰到敌方坦克
(5)检测子弹是否攻入城堡
8、坦克碰撞检测
(1)检测坦克是否撞到游戏边界
(2)检测坦克是否撞到地图内障碍物(砖块或铁块)
(3)检测坦克是否互撞
以下是坦克大战游戏完整C语言源代码:
// 坦克大战.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "string.h"
#include "stdlib.h"
#include "windows.h"
#include "conio.h"
#include "time.h"
#include "math.h"
#define FilePath "C:\\\\GameTank.dat"
#define GameX 36
#define GameY 36
#define ENEMYNUM 8 //地图中敌人数量
#define DISAPPEAR 1000 //道具消失时间间隔
//颜色
enum
{
BLACK,
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
LIGHTGRAY,
DARKGRAY,
LIGHTBLUE,
LIGHTGREEN,
LIGHTCYAN,
LIGHTRED,
LIGHTMAGENTA,
YELLOW,
WHITE
};
typedef struct Props
{
int x;
int y;
int disappear;//道具消失计时
BYTE type;//道具类型 0 生命+1 1 城堡临时加固 2无敌金身 3地雷敌军全体爆炸
Props* pNext;
}PROPS, *PPROPS;
struct CastleWall//城墙结构体
{
int x;
int y;
int* pScreenPoint;//指针指向城墙中每个砖块的内存,方便后续改变城墙材质
};
struct Bullet
{
int x;
int y;
int speed;//子弹速度
int speedCount;//子弹速度计数,当计数等于speed则子弹移动一步
int shootCount;//发射子弹倒计时
BYTE direction;//子弹方向 0 上 1 右 2下 3左
bool fly;//子弹是否还在飞行
};
typedef struct Tank
{
int id;//坦克ID
int x;
int y;
int tankType;//0 普通坦克 1 打三次才会爆炸的坦克 2速度型坦克
int blood;//血条
int moveSpeed;//移动速度
int moveCount;//计数,当计数等于moveSpeed 则移动一步
int lives;//生命
int distance;//移动距离 1 ~ 20 格
int invincibleCount;//无敌时间计数
Bullet bullet;//子弹 结构体
bool overLapping;//检测坦克刚出来时敌我双方是否重叠
bool hasShow;//坦克是否已经显示在地图上
bool propsTank;//爆炸后随机出现道具
BYTE camp;//阵营 0 我方 1 敌方
BYTE direction; //移动方向 0 上 1 右 2下 3左
Tank *pNextTank;
}TANK, *PTANK;
TANK G_Tank;//我方坦克
PTANK G_pEnemyTankHead;//敌方坦克链表头
PPROPS G_PropsHead;//道具链表头
char name[200];
int score;//得分
//指令集: w 向上 a 向左 s 向下 d 向右 o 结束游戏并保存 p 暂停游戏 空格 开炮
char KEYVALUESET[] = {'w', 'a', 's', 'd', 'o', 'p', ' '};
BYTE DIRECTIONDATA[4][9] = {0};//坦克各个方向的状态图
int G_ScreenMap[GameX + 1][GameY + 1] = {0};//初始化标记地图上的点 1 砖头 2 铁块 3地图墙壁 0 无障碍物
int G_xArr[] = {1, GameX / 2, GameX - 3};//敌方坦克随机出现的X轴位置
CastleWall G_CastleWallArr[26];//城堡围墙结构体
int G_CastleWallChangeCount = 1000;//城堡围墙从铁块变成砖头的时间计数
//函数声明
void createProps();//生成道具
/************************************************************************/
/*光标跳转到指定位置*/
/************************************************************************/
void gotoxy(int x, int y, int ForgC)
{
if(ForgC == -1)
{
ForgC = LIGHTGREEN;
}
// 更新光标位置
COORD pos;
WORD wColor;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(hOutput, pos);
CONSOLE_SCREEN_BUFFER_INFO csbi;
if(GetConsoleScreenBufferInfo(hOutput, &csbi))
{
//设置字体颜色
wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);
SetConsoleTextAttribute(hOutput, wColor);
}
// 隐藏光标
CONSOLE_CURSOR_INFO cursor;
cursor.bVisible = FALSE;
cursor.dwSize = 1; //值介于1 ~ 100 之间 单元格底部为下划线 ~ 完全填充单元格
SetConsoleCursorInfo(hOutput, &cursor);
}
/************************************************************************/
/*光标跳转到指定位置(函数重载)*/
/************************************************************************/
void gotoxy(int x, int y)
{
gotoxy(x, y, -1);
}
/************************************************************************/
/*指定位置打印游戏边框*/
/************************************************************************/
int switchFlag = 0;
void gotoprint(int x, int y, int color)
{
gotoxy(x * 2, y, color);
printf("■");
}
void gotoprint(int x, int y)
{
int color = (switchFlag = ! switchFlag) ? LIGHTGRAY : LIGHTRED;
gotoprint(x, y, color);
}
/************************************************************************/
/*从指定位置开始清除指定长度元素*/
/************************************************************************/
void gotodelete(int x, int y, int length)
{
int i;
gotoxy(x * 2, y);
for (i = 0; i < length; i++)
{
printf(" ");
}
}
/************************************************************************/
/*清除指定位置元素*/
/************************************************************************/
void gotodelete(int x, int y)
{
gotodelete(x, y, 1);
}
/************************************************************************/
/* 绘制游戏边框 */
/************************************************************************/
void drawGameMap()
{
int i, j, count;
//初始化游戏地图
for (i = 0; i < GameX; i++)
{
gotoprint(i, 0);
G_ScreenMap[i][0] = 3;//墙壁
}
for (i = 0; i < GameX; i++)
{
gotoprint(i, GameY);
G_ScreenMap[i][GameY] = 3;//墙壁
}
for (i = 0; i < GameY; i++)
{
gotoprint(0, i);
G_ScreenMap[0][i] = 3;//墙壁
}
for (i = 0; i <= GameY; i++)
{
gotoprint(GameX, i);
G_ScreenMap[GameX][i] = 3;//墙壁
}
//初始化图内砖块
for (i = 0; i < GameX; i++)
{
for (j = 0; j < GameY; j++)
{
if((i >= 5 && i <= 10 || i >= 15 && i <= 20 || i >= 25 && i <= 30) && j >=6 && j <= 30)
{
gotoprint(i, j, LIGHTGRAY);
G_ScreenMap[i][j] = 1;//砖块
}
}
}
//初始化城堡
count = 0;
for (i = GameX / 2 - 3; i <= GameX / 2 + 3; i++)
{
for (j = GameY - 5; j < GameY; j ++)
{
if(! (i >= GameX / 2 - 1 && i <= GameX / 2 + 1 && j >= GameY - 3))
{
G_ScreenMap[i][j] = 1;//砖块
G_CastleWallArr[count].x = i;
G_CastleWallArr[count].y = j;
G_CastleWallArr[count].pScreenPoint = &G_ScreenMap[i][j];
count++;
gotoprint(i, j , LIGHTGRAY);
}
else if(i == GameY / 2 || j == GameY - 2)
{
gotoprint(i, j , LIGHTGREEN);
}
}
}
}
/************************************************************************/
/*游戏读档后恢复地图*/
/************************************************************************/
void recoveryScreenMap()
{
int i, j, count;
count = 0;
for (i = 0; i < GameX + 1; i++)
{
for (j = 0; j < GameY + 1; j++)
{
if(G_ScreenMap[i][j] == 1)//砖块
{
gotoprint(i, j, LIGHTGRAY);
}
else if(G_ScreenMap[i][j] == 2)//铁块
{
gotoprint(i, j, YELLOW);
}
else if(G_ScreenMap[i][j] == 3)//游戏边界
{
if(i == 0 || i == GameX)
{
gotoprint(i, j);
}
else
{
gotoprint(i, j, i % 2 == 1 ? LIGHTRED : LIGHTGRAY);
}
}
}
}
//恢复城堡数据
for (i = GameX / 2 - 3; i <= GameX / 2 + 3; i++)
{
for (j = GameY - 5; j < GameY; j ++)
{
if(! (i >= GameX / 2 - 1 && i <= GameX / 2 + 1 && j >= GameY - 3))
{
G_CastleWallArr[count].x = i;
G_CastleWallArr[count].y = j;
G_CastleWallArr[count].pScreenPoint = &G_ScreenMap[i][j];
count++;
}
else if(i == GameY / 2 || j == GameY - 2)
{
gotoprint(i, j , LIGHTGREEN);
}
}
}
}
/************************************************************************/
/* 初始化游戏开始界面*/
/************************************************************************/
bool initGameScreen(bool state)
{
bool result;
char keyValue;
PTANK p1, p2;
PPROPS pProps1, pProps2;
system("title 坦克大战 by 机智蛋");
result = false;
gotoxy(GameX - 10, 10);
printf("/**********************************************/");
gotoxy(GameX - 10, 22);
printf("/**********************************************/");
gotoxy(GameX- 5, 13);
printf("WELCOME TO THE BATTLE OF TANKS");
gotoxy(GameX - 10, 16);
printf("W:左移 D:右移 S:下移 空格:开炮 P暂停 O结束游戏并保存");
gotoxy(GameX - 5, 18);
if(state)
{
printf("游戏有存档,是否读取?Y/N");
while(1)
{
keyValue = _getch();
if(keyValue == 'Y' || keyValue == 'y')//同意读档
{
result = true;
break;
}
else if(keyValue == 'N' || keyValue == 'n')//不同意读档
{
//DeleteFileA(FilePath); //删除存档
//以下清除已读取的数据
score = 0;
p1 = G_pEnemyTankHead;
while(p1->pNextTank != NULL)
{
p2 = p1->pNextTank;
p1->pNextTank = p1->pNextTank->pNextTank;
free(p2);
}
pProps1 = G_PropsHead;
while(pProps1->pNext != NULL)
{
pProps2 = pProps1->pNext;
pProps1->pNext C/C++游戏项目完整教程:《坦克大战》