(轉(zhuǎn))C++小游戲:坦克大戰(zhàn)-無敵AI自殘版(上半部分)
#include <stdio.h>
#include <windows.h>
#include <time.h>?
? ? ? ? ? ? ? ? ? ? ? ? ? ?//里規(guī)格:長39*2=78 (真坐標(biāo))(假坐標(biāo)寬為39)? 高39
? ? ? ? ? ? ? ? ? ? ? ? ? ?//外規(guī)格:長41*2=82 (真坐標(biāo))(假坐標(biāo)寬為41)? 高41
#define UP? ? 1
#define DOWN? 2
#define LEFT? 3
#define RIGHT 4
#define MAX_LEVEL 8
#define BULLET_NUM 20
#define MAX_LIFE 4
//程序中未寫入函數(shù)參數(shù)表中且未說明的變量只有map二維數(shù)組,level_info數(shù)組和level? ?
?
/*
? ? ? 此程序中涉及的x,y類的坐標(biāo)值,分為以下兩種:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
假坐標(biāo):這里的坐標(biāo)指的是以一個■長度為單位的坐標(biāo),而不是真正的coord坐標(biāo) (用于map數(shù)組的坐標(biāo))? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
真坐標(biāo):頭文件自帶的坐標(biāo)結(jié)構(gòu)coord中的坐標(biāo)(也可以說是控制臺里的真正坐標(biāo)值)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? 區(qū)別:縱坐標(biāo)y兩值一致,假橫坐標(biāo)x值與真正coord橫坐標(biāo)(真坐標(biāo))關(guān)系是 x * 2 = coord 橫坐標(biāo)? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? coord橫坐標(biāo)既指GoTo函數(shù)中的x參數(shù),因?yàn)楸境绦蛴螒蚪缑嬉砸粋€■長度為基本單位,? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? 可以說涉及的coord橫坐標(biāo)全是偶數(shù)。既假坐標(biāo)要變真坐標(biāo)(變真坐標(biāo)才能發(fā)揮真正作用),橫坐標(biāo)須乘以2? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
*/
typedef struct? ? ? ? ? ? ?//這里的出現(xiàn)次序指的是一個AI_tank變量中的次序,游戲共有四個AI_tank變量
{? ? ? ? ? ? ? ? ? ? ? ? ? //∵設(shè)定每個AI_tank每種特殊坦克只出現(xiàn)一次 ∴fast_tank & firm_tank 最多出現(xiàn)次數(shù)不超過1
? ? int fast_tank_order;? ?//fast_tank出現(xiàn)的次序(在第fast_tank_order次復(fù)活出現(xiàn),從第0次開始),且每個AI_tank只出現(xiàn)一次
? ? int firm_tank_order;? ?//firm_tank出現(xiàn)的次序,同上
} LevInfo;? ? ? ? ? ? ? ? ?//關(guān)卡信息(準(zhǔn)確說是該關(guān)出現(xiàn)的坦克信息)
LevInfo level_info [MAX_LEVEL] = {{-1,-1},{3,-1},{-1,3},{2,3},{2,3},{2,3},{2,3},{2,3}};? ?//初始化,-1代表沒有該類型坦克
?
?
typedef struct? ? ? //子彈結(jié)構(gòu)體
{
? ? int x,y;? ? ? ? //子彈坐標(biāo),假坐標(biāo)
? ? int direction;? //子彈方向變量
? ? bool exist;? ? ?//子彈存在與否的變量,1為存在,0不存在
? ? bool initial;? ?//子彈是否處于建立初狀態(tài)的值,1為處于建立初狀態(tài),0為處于非建立初狀態(tài)
? ? bool my;? ? ? ? //區(qū)分AI子彈與玩家子彈的標(biāo)記,0為AI子彈,1為玩家(我的)子彈
} Bullet;
Bullet bullet [BULLET_NUM];? //考慮到地圖上不太可能同時存在20顆子彈,所以數(shù)組元素設(shè)置20個
?
?
typedef struct? ? ? //坦克結(jié)構(gòu)體
{
? ? int x,y;? ? ? ? //坦克中心坐標(biāo)
? ? int direction;? //坦克方向
? ? int color;? ? ? //顏色參方向數(shù),1到6分別代表不同顏色,具體在PrintTank函數(shù)定義有說明
? ? int model;? ? ? //坦克圖案模型,值為1,2,3,分別代表不同的坦克圖案,0為我的坦克圖案,AI不能使用
? ? int stop;? ? ? ?//只能是AI坦克使用的參數(shù),非0代表坦克停止走動,0為可以走動
? ? int revive;? ? ?//坦克復(fù)活次數(shù)
? ? int num;? ? ? ? //AI坦克編號(固定值,為常量,初始化函數(shù)中定下)0~3
? ? int CD=0;? ? ? ? ?//發(fā)射子彈冷卻計(jì)時
? ? bool my;? ? ? ? //是否敵方坦克參數(shù),我的坦克此參數(shù)為1,為常量
? ? bool alive;? ? ?//存活為1,不存活為0
}? Tank;
Tank AI_tank[4] , my_tank;? //my_tank為我的坦克,Ai_tank 代表AI坦克
?
//∵所有的函數(shù)都有可能對全局變量map進(jìn)行讀寫(改變),
//∴函數(shù)中不另說明是否會對全局變量map讀寫
//基本操作與游戲輔助函數(shù)
void GoToxy(int x,int y);? ? //光標(biāo)移動
void HideCursor();? ? ? ? ? ?//隱藏光標(biāo)
void keyboard ();? ? ? ? ? ? //接受鍵盤輸入
void Initialize();? ? ? ? ? ?//初始化(含有對多個數(shù)據(jù)的讀寫)
void Stop();? ? ? ? ? ? ? ? ?//暫停
void Getmap();? ? ? ? ? ? ? ?//地圖數(shù)據(jù)存放與獲取
void Frame ();? ? ? ? ? ? ? ?//打印游戲主體框架
void PrintMap();? ? ? ? ? ? ?//打印地圖(地圖既地圖障礙物)(含對level的讀取)
void SideScreen ();? ? ? ? ? //副屏幕打印
void GameCheak();? ? ? ? ? ? //檢測游戲輸贏
void GameOver( bool home );? //游戲結(jié)束
void ClearMainScreen();? ? ? //主屏幕清屏函數(shù)∵system("cls")后打印框架有一定幾率造成框架上移一行的錯誤∴單獨(dú)編寫清屏函數(shù)
void ColorChoose(int color); //顏色選擇函數(shù)
void NextLevel();? ? ? ? ? ? //下一關(guān)(含有對level全局變量的讀寫)
?
//子彈部分
void BuildAIBullet(Tank *tank);? ? ? ? ? ? ? ? //AI坦克發(fā)射子彈(含有對my_tank的讀取,只讀取了my_tank坐標(biāo))
void BuildBullet? (Tank tank);? ? ? ? ? ? ? ? ?//子彈發(fā)射(建立)(人機(jī)共用)(含全局變量bullet的修改)我的坦克發(fā)射子彈直接調(diào)用該函數(shù),AI通過AIshoot間接調(diào)用
void BulletFly? ? (Bullet bullet[BULLET_NUM]); //子彈移動和打擊(人機(jī)共用),
void BulletHit? ? (Bullet* bullet);? ? ? ? ? ? //子彈碰撞(人機(jī)共用)(含Tank全局變量的修改),只通過BulletFly調(diào)用,子彈間的碰撞不在本函數(shù),子彈間碰撞已在BulletShoot中檢測并處理
void PrintBullet? (int x,int y,int T);? ? ? ? ?//打印子彈(人機(jī)共用)
void ClearBullet? (int x,int y,int T);? ? ? ? ?//清除子彈(人機(jī)共用)
int? BulletCheak? (int x,int y);? ? ? ? ? ? ? ?//判斷子彈前方情況(人機(jī)共用)
?
//坦克部分
void BuildAITank (int* position, Tank* AI_tank); //建立AI坦克
void BuildMyTank (Tank* my_tank);? ? ? ? ? ? ? ? //建立我的坦克
void MoveAITank? (Tank* AI_tank);? ? ? ? ? ? ? ? //AI坦克移動
void MoveMyTank? (int turn);? ? ? ? ? ? ? ? ? ? ?//我的坦克移動,只通過keyboard函數(shù)調(diào)用,既鍵盤控制
void ClearTank? ?(int x,int y);? ? ? ? ? ? ? ? ? //清除坦克(人機(jī)共用)
void PrintTank? ?(Tank tank);? ? ? ? ? ? ? ? ? ? //打印坦克(人機(jī)共用)
bool TankCheak? ?(Tank tank,int direction);? ? ? //檢測坦克dirtection方向的障礙物,返值1阻礙,0 暢通
int? AIPositionCheak (int position);? ? ? ? ? ?//檢測AI坦克建立位置是否有障礙物AIPositionCheak
?
//DWORD WINAPI InputX(LPVOID lpParameter); //聲明線程函數(shù),用于檢查X鍵輸入并設(shè)置X鍵的輸入冷卻時間
?
?
//注意map數(shù)組應(yīng)是縱坐標(biāo)在前,橫坐標(biāo)在后,既map[y][x],(∵數(shù)組行長度在前,列長度在后)
//map里的值: 個位數(shù)的值為地圖方塊部分,百位數(shù)的值為坦克,子彈在map上沒有值(子彈僅僅是一個假坐標(biāo))
//map里的值: 0為可通過陸地,1為紅磚,2黃磚,5為水,100~103為敵方坦克,200為我的坦克,
?
//全局變量
int map[41][41];? //地圖二維數(shù)組
int key_x;? ? ? ? // X鍵是否被“讀入”的變量,也是子彈是否可以發(fā)射的變,
int bul_num;? ? ? //子彈編號
int position;? ? ?//位置計(jì)數(shù),對應(yīng)AI坦克生成位置,-1為左位置,0為中間,1為右,2為我的坦克位置
int speed=7;? ? ? //游戲速度,調(diào)整用
int level=1;? ? ? //游戲關(guān)卡數(shù)
int score=0;? ? ? //游戲分?jǐn)?shù)
int remain_enemy; //剩余敵人(未出現(xiàn)的敵人)
?
char* tank_figure[4][3][4]=
{
? {
? ? {"◢┃◣", "◢━◣", "◢┳◣", "◢┳◣"},
? ? {"┣●┫", "┣●┫", "━●┃", "┃●━"},
? ? {"◥━◤", "◥┃◤", "◥┻◤", "◥┻◤"}
? },?
? {
? ? {"┏┃┓", "┏┳┓", "┏┳┓", "┏┳┓"},
? ? {"┣●|",? "┣●|",? "━●┫", "┣●━"},
? ? {"┗┻┛", "┗┃┛", "┗┻┛", "┗┻┛"}
? },?
? {
? ? {"┏┃┓", "◢━◣", "┏┳◣", "◢┳┓"},
? ? {"┣●┫", "┣●┫", "━●┃", "┃●━"},
? ? {"◥━◤", "┗┃┛", "┗┻◤", "◥┻┛"}
? },
? {
? ? {"╔┃╗", "╔╦╗", "╔╦╗", "╔╦╗"},
? ? {"╠█╣", "╠█╣", "━█╣", "╠█━"},
? ? {"╚╩╝", "╚┃╝", "╚╩╝", "╚╩╝"}
? }
};
?
?
?
int main ()? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//主函數(shù)
{
? ? int i;
? ? unsigned int interval[12]={1,1,1,1,1,1,1,1,1,1,1,1} ;? //間隔計(jì)數(shù)器數(shù)組,用于控制速度
? ? srand(time(NULL)); //設(shè)置隨機(jī)數(shù)種子(若不設(shè)置種子而調(diào)用rand會使每次運(yùn)行的隨機(jī)數(shù)序列一致)隨機(jī)數(shù)序列指:如首次調(diào)用rand得到1,第二次得2,第三次3,則此次隨機(jī)數(shù)序列為1,2,3
? ? HideCursor();? ? ? ? ? ? ? ? ? ? ? ? ?//隱藏光標(biāo)
? ? system("mode con cols=112 lines=42"); //控制窗口大小
? ? Frame ();? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//打印游戲主體框架
? ? Initialize();? ? ? ? ? ? ? ? ? ? ? ? ?//初始化,全局變量level初值便是1?
//? ? HANDLE h1 , h2 ;? ? ? ? ? ? ? ? ? ? ? //定義句柄變量
? ? for(;;)
? ? {
? ? ? ? if(interval[0]++%speed==0)? ? ? ? //速度調(diào)整用,假設(shè)interval[0]為a, 語句意為 a % 2==0,a=a+1;?
? ? ? ? {
? ? ? ? ? ? GameCheak();? ? ? ? ? ? ? ? ? //游戲勝負(fù)檢測
? ? ? ? ? ? BulletFly ( bullet );
? ? ? ? ? ? for(i=0 ; i<=3 ; i++)? ? ? ? ?//AI坦克移動循環(huán)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if(AI_tank[i].model==2 && interval[i+1]++%2==0) //四個坦克中的快速坦克單獨(dú)使用計(jì)數(shù)器1,2,3,4
? ? ? ? ? ? ? ? ? ? MoveAITank( & AI_tank[i]);
? ? ? ? ? ? ? ? if(AI_tank[i].model!=2 && interval[i+5]++%3==0) //四個坦克中的慢速坦克單獨(dú)使用計(jì)數(shù)器5,6,7,8
? ? ? ? ? ? ? ? ? ? MoveAITank( & AI_tank[i]);
? ? ? ? ? ? }
? ? ? ? ? ? for(i=0;i<=3;i++)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//建立AI坦克部分
? ? ? ? ? ? ? ? ? ? ?if(AI_tank[i].alive==0 && AI_tank[i].revive<4 && interval[9]++%90==0)? //一個敵方坦克每局只有4條命
? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//如果坦克不存活。計(jì)時,每次建立有間隔? 1750 ms
? ? ? ? ? ? ? ? ? ? ? BuildAITank( &position, & AI_tank[i] );? ? ?//建立AI坦克(復(fù)活)
? ? ? ? ? ? ? ? ? ? ? break;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //每次循環(huán)只建立一個坦克
? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? for(i=0;i<=3;i++)
? ? ? ? ? ? ? ? if(AI_tank[i].alive)
? ? ? ? ? ? ? ? ? ? BuildAIBullet(&AI_tank[i]);? ? ? ? ? ? ? ? ?//AIshoot自帶int自增計(jì)數(shù)CD,不使用main中的CD interval
? ? ? ? ? ? if(my_tank.alive && interval[10]++%2==0 )
? ? ? ? ? ? ? ? ?keyboard ();
? ? ? ? ? ? if(my_tank.alive==0 && interval[11]++%30==0 && my_tank.revive < MAX_LIFE)
? ? ? ? ? ? ? ? ?BuildMyTank( &my_tank );
? ? ? ? }
? ? ? ? Sleep(5);
? ? }
? ? return 0;
}
?
?
///這里的多線程暫時不用? ? ? ? ? ? ? ? ? ?//x鍵用于子彈發(fā)射,x鍵的冷卻時間不能和上下左右一同設(shè)置,那樣就太快了
DWORD WINAPI InputX(LPVOID lpParameter)? ? //如果不用多線程運(yùn)行,那么在x鍵冷卻時間內(nèi)程序會因Sleep將會掛起,暫停運(yùn)行
{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //因?yàn)橹挥幸粋€變量改變,而且變量改變先后順序是顯而易見的,所以不必設(shè)置緩沖區(qū)
? ? for(;;)? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? if(GetAsyncKeyState( 88 )& 0x8000) //88為x鍵鍵值,當(dāng)摁下x并且x鍵處于可輸入狀態(tài)
? ? ? ? {
? ? ? ? ? ? key_x=1;? ? ? ? ? ? ? ? ? ? ? ?// X鍵是否允許被“讀入”的變量,也是子彈是否可以發(fā)射的變量
? ? ? ? ? ??
? ? ? ? }
? ? ? ??
? ? }
? ? return 0;
}
?
?
void keyboard ()
{? ? ? ? ? ? ? ?// kbhit()? ?getch()? 用法可用但是不好用? ? ? ? ? ??
? ? int count=0;
? ? if (GetAsyncKeyState(VK_UP)& 0x8000)??
? ? ? ? MoveMyTank( UP );
? ? else if (GetAsyncKeyState(VK_DOWN)& 0x8000)??
? ? ? ? MoveMyTank( DOWN );
? ? else if (GetAsyncKeyState(VK_LEFT)& 0x8000)
? ? ? ? MoveMyTank( LEFT );
? ? else if (GetAsyncKeyState(VK_RIGHT)& 0x8000)??
? ? ? ? MoveMyTank( RIGHT );
? ? else if (GetAsyncKeyState( 0x1B )& 0x8000)? // Esc鍵
? ? ? ? exit(0);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //退出程序函數(shù)
? ? else if (GetAsyncKeyState( 0x20 )& 0x8000)? //空格
? ? ? ? Stop();
? ? else if (count++%7==0)? ? ? ? ? ? //這里添加計(jì)數(shù)器是為了防止按鍵粘連不能達(dá)到微調(diào)效果
? ? {
? ? ? ? if (speed>1 && GetAsyncKeyState( 0x6B )& 0x8000)? ?// +鍵
? ? ? ? {
? ? ? ? ? ? speed--;
? ? ? ? ? ? GoToxy(102,11);? ? ? ? ? ?//在副屏幕打印出當(dāng)前速度
? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_BLUE|FOREGROUND_RED);
? ? ? ? ? ? printf("%d ",21-speed);? ?//副屏幕顯示的速度為1~10
? ? ? ? }
? ? ? ? else if (speed<20 && GetAsyncKeyState( 0x6D )& 0x8000)? // - 鍵
? ? ? ? {
? ? ? ? ? ? speed++;
? ? ? ? ? ? GoToxy(102,11);? ? ? ? ? ?//在副屏幕打印出當(dāng)前速度
? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_BLUE|FOREGROUND_RED);
? ? ? ? ? ? printf("%d ",21-speed);? ?//副屏幕顯示的速度為1~10
? ? ? ? }
? ? }
? ? if(my_tank.CD==7)
? ? {
? ? ? ? if(GetAsyncKeyState( 88 )& 0x8000)
? ? ? ? {
? ? ? ? ? ? BuildBullet(my_tank);
? ? ? ? ? ? my_tank.CD=0;
? ? ? ? }
? ? }
? ? else
? ? ? ? my_tank.CD++;
}
?
?
?
void BuildAIBullet(Tank *tank)? ?//AI子彈發(fā)射(建立)含有對my_tank的讀取
{
? ? if(tank->CD==15)
? ? {
? ? ? ? if(!(rand()%11))? ? ?//冷卻結(jié)束后在隨后的每個游戲周期中有10分之一的可能發(fā)射子彈
? ? ? ? {
? ? ? ? ? ?BuildBullet(*tank);
? ? ? ? ? ? tank->CD=0;
? ? ? ? }
? ? }
? ? else
? ? ? ? tank->CD++;
? ? if(tank->CD >= 14)? ? ? ?//AI強(qiáng)化部分,在冷卻到達(dá)一定范圍即可使用
? ? {
? ? ? ? if(tank->y==38 )? ? ?//如果坦克在底部(這個最優(yōu)先)
? ? ? ? {
? ? ? ? ? ? if(tank->x < 20) //在老家左邊
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if(tank->direction==LEFT)? //坦克方向朝左
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? BuildBullet(*tank);? ? ?//發(fā)射子彈
? ? ? ? ? ? ? ? ? ? tank->CD=0;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? else? ? ? ? ? ? ?//在老家右邊
? ? ? ? ? ? ? ? if(tank->direction==RIGHT)? ?//坦克方向朝右
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? BuildBullet(*tank);? ? ?//發(fā)射子彈
? ? ? ? ? ? ? ? ? ? tank->CD=0;
? ? ? ? ? ? ? ? }
? ? ? ? }
? ? ? ? else if(tank->x==my_tank.x+1 || tank->x==my_tank.x || tank->x==my_tank.x-1)? //AI坦克在縱向上"炮口"對準(zhǔn)我的坦克
? ? ? ? {
? ? ? ? ? ? if(tank->direction==DOWN && my_tank.y > tank->y || tank->direction==UP && my_tank.y < tank->y)
? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//若是AI朝下并且我的坦克在AI坦克下方(數(shù)值大的在下面)或者AI朝上我的坦克在AI上方
? ? ? ? ? ? ? ? int big=my_tank.y , smal=tank->y , i;?
? ? ? ? ? ? ? ? if(my_tank.y < tank->y)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? big=tank->y;
? ? ? ? ? ? ? ? ? ? smal=my_tank.y;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? for(i=smal+2;i<=big-2;i++)? //判斷AI炮口的直線上兩坦克間有無障礙
? ? ? ? ? ? ? ? ? ? if(map[i][tank->x]!=0 || map[i][tank->x]!=5)? ? ? //若有障礙
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? if(i==big-1)? ? ? ? ? ? ? ? //若i走到big-1說明無障礙
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ?BuildBullet(*tank);? ? ?//則發(fā)射子彈
? ? ? ? ? ? ? ? ? ? tank->CD=0;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? else if(tank->y==my_tank.y+1 || tank->y==my_tank.y || tank->y==my_tank.y-1) //AI坦克在橫向上"炮口"對準(zhǔn)我的坦克
? ? ? ? {
? ? ? ? ? ? if(tank->direction==RIGHT && my_tank.x > tank->x || tank->direction==LEFT && my_tank.x < tank->x)
? ? ? ? ? ? {? ? ? ? ? ? ? ? ? //若是AI朝右并且我的坦克在AI坦克右方(數(shù)值大的在下面)或者AI朝左我的坦克在AI左方
? ? ? ? ? ? ? ? int big=my_tank.y , smal=tank->y , i;
? ? ? ? ? ? ? ? if(my_tank.x < tank->x)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? big=tank->x;
? ? ? ? ? ? ? ? ? ? smal=my_tank.x;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? for(i=smal+2;i<=big-2;i++)? //判斷AI炮口的直線上兩坦克間有無障礙
? ? ? ? ? ? ? ? ? ? if(map[tank->y][i]!=0 || map[tank->y][i]!=5)? ? ? //若有障礙
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? if(i==big-1)? ?//若i走到big-1說明無障礙
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? BuildBullet(*tank);? ? ?//則發(fā)射子彈
? ? ? ? ? ? ? ? ? ? tank->CD=0;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
?
?
?
void BuildBullet(Tank tank)? //子彈發(fā)射(建立),傳入結(jié)構(gòu)體Tank,這里包含改變了全局變量結(jié)構(gòu)體bullet
{? ? ? ? ? ? ? ? ? ? ? ? ? ? //∵實(shí)現(xiàn)方式為順序循環(huán)建立子彈,每次調(diào)用改變的bullet數(shù)組元素都不同
? ? switch(tank.direction)? ?//∴為了方便,不將bullet放入?yún)?shù),bullet作為全局變量使用
? ? {
? ? ? ? case UP? ? :
? ? ? ? ? ? ? ? bullet [bul_num].x = tank.x;
? ? ? ? ? ? ? ? bullet [bul_num].y = tank.y-2;
? ? ? ? ? ? ? ? bullet [bul_num].direction=1;
? ? ? ? ? ? ? ? break;
? ? ? ? case DOWN? :
? ? ? ? ? ? ? ? bullet [bul_num].x = tank.x;
? ? ? ? ? ? ? ? bullet [bul_num].y = tank.y+2;
? ? ? ? ? ? ? ? bullet [bul_num].direction=2;
? ? ? ? ? ? ? ? break;
? ? ? ? case LEFT? :
? ? ? ? ? ? ? ? bullet [bul_num].x = tank.x-2;
? ? ? ? ? ? ? ? bullet [bul_num].y = tank.y;
? ? ? ? ? ? ? ? bullet [bul_num].direction=3;
? ? ? ? ? ? ? ? break;
? ? ? ? case RIGHT :
? ? ? ? ? ? ? ? bullet [bul_num].x = tank.x+2;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? bullet [bul_num].y = tank.y;?
? ? ? ? ? ? ? ? bullet [bul_num].direction=4;
? ? ? ? ? ? ? ? break;?
? ? }? ? ?
? ? bullet [bul_num].exist = 1;? ? //子彈被建立,此值為1則此子彈存在
? ? bullet [bul_num].initial = 1;? //子彈處于初建立狀態(tài)
? ? bullet [bul_num].my=1;? ?//如果是我的坦克發(fā)射的子彈bullet.my=1,否則為0
? ? bul_num++;
? ? if(bul_num==BULLET_NUM)? ? ? ? //如果子彈編號增長到20號,那么重頭開始編號
? ? ? ? bul_num=0;? ? ? ? ? ? ? ? ?//考慮到地圖上不可能同時存在20顆子彈,所以數(shù)組元素設(shè)置20個
}
?
?
void BulletFly(Bullet bullet[BULLET_NUM]) //子彈移動和打擊
{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//含有全局變量Bullet的改變
? ? for(int i =0; i<BULLET_NUM;i++)
? ? {
? ? ? ? if(bullet [i].exist)? ? ? ? ? ? ? //如果子彈存在
? ? ? ? {? ?
? ? ? ? ? ? if(bullet [i].initial==0)? ? ?//如果子彈不是初建立的
? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? if(map[bullet[i].y] [bullet[i].x]==0 || map[bullet[i].y] [bullet[i].x]==5)? ?//如果子彈坐標(biāo)當(dāng)前位置無障礙
? ? ? ? ? ? ? ? ? ? ClearBullet( bullet[i].x , bullet[i].y , BulletCheak(bullet[i].x , bullet[i].y ));? ? ?//抹除子彈圖形
? ? ? ? ? ? ? ? switch(bullet [i].direction)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //然后子彈坐標(biāo)變化(子彈變到下一個坐標(biāo))
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? case UP? ? :(bullet [i].y)--;break;
? ? ? ? ? ? ? ? ? ? case DOWN? :(bullet [i].y)++;break;
? ? ? ? ? ? ? ? ? ? case LEFT? :(bullet [i].x)--;break;
? ? ? ? ? ? ? ? ? ? case RIGHT :(bullet [i].x)++;break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? int collide = BulletCheak ( bullet [i].x , bullet [i].y );? ?//判斷子彈當(dāng)前位置情況,判斷子彈是否碰撞,是否位于水面上。
? ? ? ? ? ? if( collide )? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //如果檢測到當(dāng)前子彈坐標(biāo)無障礙(無碰撞)(包括在地面上與在水面上)
? ? ? ? ? ? ? ? PrintBullet( bullet[i].x , bullet[i].y , collide);? ? ? ?//則打印子彈,若有碰撞則不打印
? ? ? ? ? ? else
? ? ? ? ? ? ? ? BulletHit( & bullet [i] );? ? ?//若有碰撞則執(zhí)行子彈碰撞函數(shù)? ? ? ? ? ? ? ? ??
? ? ? ? ? ? if(bullet [i].initial)? ? ? ? ? ? ?//若子彈初建立,則把初建立標(biāo)記去除
? ? ? ? ? ? ? ? bullet [i].initial = 0;
? ? ? ? ? ? for(int j=0; j< BULLET_NUM ; j++)? //子彈間的碰撞判斷,若是我方子彈和敵方子彈碰撞則都刪除,若為兩敵方子彈則無視
? ? ? ? ? ? ? ? if(bullet [j].exist && j!=i && (bullet[i].my || bullet[j].my) && bullet[i].x==bullet[j].x && bullet[i].y==bullet[j].y)
? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //同樣的兩顆我方子彈不可能產(chǎn)生碰撞
? ? ? ? ? ? ? ? ? ? bullet [j].exist=0;
? ? ? ? ? ? ? ? ? ? bullet [i].exist=0;
? ? ? ? ? ? ? ? ? ? ClearBullet( bullet[j].x , bullet[j].y , BulletCheak(bullet[j].x , bullet[j].y ));? //抹除j子彈圖形,子彈i圖形已被抹除
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? }
? ? }
}
?
?
void BulletHit(Bullet* bullet)? //含有Tank全局變量的修改,子彈間的碰撞不在本函數(shù),子彈間碰撞已在BulletShoot中檢測并處理
{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//∵每次打中的坦克都不一樣,不可能把所有坦克放在參數(shù)表中
? ? int x=bullet->x;? ? ? ? ? ? //∴這里的Tank使用全局變量
? ? int y=bullet->y;? ? ? ? ? ? //這里傳入的值是子彈坐標(biāo),這兩個值不需要改變
? ? int i;
? ? if(map[y][x]==1 || map[y][x]==2)? //子彈碰到磚塊
? ? {
? ? ? ? if(bullet->direction==UP || bullet->direction==DOWN)? ?//如果子彈是縱向的
? ? ? ? ? ? for(i = -1 ; i<=1 ; i++)
? ? ? ? ? ? ? ? if(map[y][x+i]==1 || map[y][x+i]==2)? //如果子彈打中磚塊兩旁為磚塊,則刪除磚,若不是(一旁為坦克或其他地形)則忽略
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? map[y][x+i]=0;? ? //磚塊碎
? ? ? ? ? ? ? ? ? ? ?GoToxy(2*x+2*i,y);
? ? ? ? ? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED); //背景黑色
? ? ? ? ? ? ? ? ? ? ?printf("? ");
? ? ? ? ? ? ? ? }
? ? ? ? if(bullet->direction==LEFT || bullet->direction==RIGHT)? ? ?//若子彈是橫向的? (與子彈縱向?qū)崿F(xiàn)同理)
? ? ? ? ? ? for(i = -1 ; i<=1 ; i++)
? ? ? ? ? ? ? ? if(map[y+i][x]==1 || map[y+i][x]==2)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? map[y+i][x]=0;
? ? ? ? ? ? ? ? ? ? ?GoToxy(2*x,y+i);
? ? ? ? ? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED); //背景黑色
? ? ? ? ? ? ? ? ? ? ?printf("? ");?
? ? ? ? ? ? ? ? }
? ? ? ? bullet->exist=0;? ? ? ? ? ?//這顆子彈已經(jīng)不存在了
? ? }
? ? else if(map[y][x]==4 || map[y][x]==6 )? //子彈碰到邊框或者不可摧毀方塊
? ? ? ? bullet->exist=0;
? ? else if(bullet->my && map[y][x]>=100 && map[y][x]<104 )? //若我的子彈碰到了敵方坦克
? ? {
? ? ? ? int num = map[y][x]%100;? ?//map[y][x]%100 等同于 tank.num ,可通過map值讀取該坦克信息
? ? ? ? if(AI_tank[num].model==3 && AI_tank[num].color==2)? ?//若為firm tank,且color==2。該坦克為綠色,表明沒有受到傷害
? ? ? ? ? ? ? ? AI_tank[num].color=3;? ? ? ? ? ? ? ? ? ? ? ? //則變成黃色,color=3為黃色
? ? ? ? else if (AI_tank[num].model==3 && AI_tank[num].color==3)
? ? ? ? ? ? ? ? AI_tank[num].color=4;? ? ? ? ? ? ? ? ? ? ? ? //4為紅色
? ? ? ? else? ? ? ? ? ? ? ? ? ? ? ?//其他類型的坦克或者firm tank為紅色的情況
? ? ? ? {
? ? ? ? ? ? AI_tank[num].alive=0;
? ? ? ? ? ? ClearTank(AI_tank[num].x , AI_tank[num].y);? ? ? //清除該坦克
? ? ? ? }
? ? ? ? bullet->exist=0;
? ? ? ? score+=100;
? ? ? ? GoToxy(102,5);? ? ? ? ? ? ?//在副屏幕上打印出分?jǐn)?shù)
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
? ? ? ? printf("%d ",score);
? ? }
? ? /*else if(map[y][x]==200 && bullet->my==0 )? ?//若敵方子彈擊中我的坦克
? ? {
? ? ? ? my_tank.alive=0;
? ? ? ? ClearTank(my_tank.x , my_tank.y);
? ? ? ? bullet->exist=0;
? ? ? ? my_tank.revive++;? ? ? //我的坦克復(fù)活次數(shù)+1(∵我的坦克復(fù)活次數(shù)與生命值有關(guān)∴放在這里自減)
? ? ? ? score-=100;? ? ? ? ? ? //分?jǐn)?shù)減少
? ? ? ? GoToxy(102,5);? ? ? ? ?//在副屏幕上打印出分?jǐn)?shù)
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
? ? ? ? printf("%d? ?",score);
? ? ? ? GoToxy(102,7);? ? ? ? ?//在副屏幕打印出我的剩余生命值
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN);
? ? ? ? printf("%d? ?", MAX_LIFE-my_tank.revive);
? ? }*/
//? ? else if(bullet->my==0 && map[y][x]>=100 && map[y][x]<104) //敵方子彈擊中敵方坦克,可以設(shè)置兩種子彈運(yùn)行方式,這種暫時不用
//? ? ? ? bullet->exist=0;
? ? else if(map[y][x]==9)? ? ? //子彈碰到家(無論是誰的子彈)
? ? {
? ? ? ? bullet->exist=0;
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN);
? ? ? ? GoToxy(38,37);? ? ?printf("軍事基地");
? ? ? ? GoToxy(38,38);? ? ?printf("◢◣? ");
? ? ? ? GoToxy(38,39);? ? ?printf("███");
? ? ? ? //GameOver(1);? ? ? ? ? ?//游戲結(jié)束,傳入1代表老家被毀
? ? }
}
?
?
int BulletCheak (int x,int y)? //判斷子彈當(dāng)前位置情況,判斷子彈是否碰撞,是否位于水面上。
{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //有障礙返回0,無障礙且子彈在地面返回1,子彈在水面上返回2
? ? if(map[y][x]==0)
? ? ? ? return 1;
? ? else if(map[y][x]==5)
? ? ? ? return 2;
? ? else
? ? ? ? return 0;
}
?
?
void PrintBullet (int x,int y,int T)? ?//當(dāng)前坐標(biāo)BulletCheak 的值做參量 T
{
? ? if(T==1)? ? ? ? ? //? T==1 表示子彈當(dāng)前坐標(biāo)在陸地上
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY);
? ? else if(T==2)? ? ?//? T==2 表示子彈當(dāng)前坐標(biāo)在水面上
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY|BACKGROUND_BLUE);
? ? GoToxy(2*x,y);
? ? printf(".");
}
?
?
void ClearBullet(int x,int y,int T)? ?//當(dāng)前坐標(biāo)BulletCheak 的值做參量 T
{
? ? GoToxy(2*x,y);
? ? if(T==2)? ? ? ? //? T==2 表示子彈當(dāng)前坐標(biāo)在水面上
? ? {
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|BACKGROUND_BLUE|FOREGROUND_BLUE|FOREGROUND_GREEN);
? ? ? ? printf("~");
? ? }
? ? else if(T==1)? ?//? T==1 表示子彈當(dāng)前坐標(biāo)在陸地上
? ? {
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_BLUE);
? ? ? ? printf("? ");
? ? }
}
?
?
//position為坦克生成位置,-1為左位置,0為中間,1為右,2為我的坦克位置
void BuildAITank(int* position, Tank* AI_tank)? ?//執(zhí)行一次該函數(shù)只建立一個坦克
{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//rand函數(shù)公式:0<=rand()%(a+1)<=a? 0+m<=rand()%(n-m+1)+m<=n??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //rand函數(shù)實(shí)現(xiàn)1到n:1<=rand()%(n)+1<=n
? ? ? ?if(AIPositionCheak(*position))? ? ? ? //若此位置無障礙,可生成。position參數(shù)詳見AIPositionCheak函數(shù)定義
? ? {
? ? ? ? AI_tank->x= 20 + 18*(*position);? //20 + 18 * position 對應(yīng)三個生成位置的x假坐標(biāo)
? ? ? ? AI_tank->y=2;
? ? ? ? if(AI_tank->revive==level_info[level-1].firm_tank_order)? //坦克出現(xiàn)(復(fù)活)次序==關(guān)卡信息(level_info)中firm tank的出現(xiàn)次序
? ? ? ? {
? ? ? ? ? ? AI_tank->model = 3;? ? ? ? ? ?//3為firm tank的模型(外觀)
? ? ? ? ? ? AI_tank->color = 2;? ? ? ? ? ?//顏色參數(shù)2為綠色,具體詳見函數(shù)ColorChoose
? ? ? ? }
? ? ? ? else if(AI_tank->revive==level_info[level-1].fast_tank_order)? //同上if,這里是fast_tank的
? ? ? ? {
? ? ? ? ? ? AI_tank->model = 2;
? ? ? ? ? ? AI_tank->color = rand()%6+1;? //若不是firm tank則隨機(jī)顏色,顏色參數(shù)為1~6,分別代表不同顏色,詳見函數(shù)ColorChoose
? ? ? ? }
? ? ? ? else? ? ? //普通坦克
? ? ? ? {
? ? ? ? ? ? AI_tank->model = 1;
? ? ? ? ? ? ? ?AI_tank->color = rand()%6+1;? //若不是firm tank則隨機(jī)顏色
? ? ? ? }
? ? ? ? AI_tank->alive = 1;? ? ? ?//坦克變?yōu)榇嬖?/p>
? ? ? ? AI_tank->direction = 2 ;? //方向朝下
? ? ? ? AI_tank->revive++;? ? ? ? //復(fù)活次數(shù)+1
? ? ? ? PrintTank(*AI_tank);
? ? ? ? (*position)++;?
? ? ? ? remain_enemy--;
? ? ? ? GoToxy(102,9);? ? ? ? ? ? //在副屏幕上打印剩余坦克數(shù)
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED);
? ? ? ? printf("%d ",remain_enemy);
? ? ? ? if(*position==2)? ? ? ? ? //position只能為0,1,-1,這里position循環(huán)重置
? ? ? ? ? ? *position = -1;
? ? ? ? ? ? ?return ;? ? ? ? ? ? ? ? ? //若生成了一輛坦克,則結(jié)束該函數(shù)
? ? }
}
?
?
int AIPositionCheak( int position )? ? //position為坦克生成位置2為我的坦克位置,其余為AI位,-1為左位,0為中間位置,1為右位
{
? ? int? ? x,y;
? ? if(position==2)? ? ? ? ? ? ? ? ? ? //2為我的坦克位置,現(xiàn)在暫時用不到
? ? ? ? x=15,y=38;
? ? else
? ? ? ? y=2 , x= 20 + 18 * position ;? //20 + 18 * position 對應(yīng)三個生成位置的x假坐標(biāo)
? ? for(int i=0;i<3;i++)
? ? ? ? for(int j=0;j<3;j++)
? ? ? ? ? ? if( map[y+j-1][x+i-1]!=0)? //如果遍歷的九宮格里有障礙物
? ? ? ? ? ? ? ? return 0;? ? ? ? ? ? ? //則返回0,表示此生成位置有阻礙
? ? return 1;? ? ? ? ? ? ? ? ? ? ? ? ? //否則生成1,表示此生成位置無阻礙
}
?
?
void MoveAITank(Tank* AI_tank) //AI專用函數(shù),該函數(shù)主要為AI加強(qiáng)
{
? ? ? ?if(AI_tank->alive)? ? ? ? ?//如果坦克活著
? ? {
? ? ? ? if(AI_tank->stop!=0)? ?//坦克是否停止運(yùn)動的判斷,若stop參數(shù)不為0
? ? ? ? {
? ? ? ? ? ? AI_tank->stop--;? ?//則此坦克本回合停止運(yùn)動
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? if( !(rand()%23) )? ? ?//22分之1的概率執(zhí)行方向重置
? ? ? ? {
? ? ? ? ? ? AI_tank->direction = rand()%4+1;
? ? ? ? ? ? if( rand()%3 )? ? ?//在方向重置后有2分之1的概率停止走動3步的時間
? ? ? ? ? ? {
? ? ? ? ? ? ? ? AI_tank->stop=2;
? ? ? ? ? ? ? ? return;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? ClearTank (AI_tank->x , AI_tank->y);
? ? ? ? if(TankCheak ( *AI_tank , AI_tank->direction))? ?//如果前方無障礙
? ? ? ? ? ? switch ( AI_tank->direction )
? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ?case UP? ?: AI_tank->y--; break;? //上前進(jìn)一格
? ? ? ? ? ? ? ? case DOWN : AI_tank->y++; break;? //下前進(jìn)一格
? ? ? ? ? ? ? ? ?case LEFT : AI_tank->x--; break;? //左前進(jìn)一格
? ? ? ? ? ? ? ? case RIGHT: AI_tank->x++; break;? //右前進(jìn)一格
? ? ? ? ? ? }
? ? ? ? else? ? ? ? ? ? ? ? ? ? ?//前方有障礙
? ? ? ? {
? ? ? ? ? ? if(!(rand()%4))? ? ? //3分之1的概率亂轉(zhuǎn)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? AI_tank->direction=rand()%4+1;
? ? ? ? ? ? ? ? AI_tank->stop=2; //亂轉(zhuǎn)之后停止走動3步的時間
? ? ? ? ? ? ? ? PrintTank(*AI_tank);
? ? ? ? ? ? ? ? return;? ? ? ? ? //∵continue會跳過下面的打印函數(shù),∴這里先打印
? ? ? ? ? ? }
? ? ? ? ? ? else? ? ? ? ? ? ? ? ?//另外3分之2的幾率選擇正確的方向
? ? ? ? ? ? {
? ? ? ? ? ? ? ? int j;
? ? ? ? ? ? ? ? for(j=1;j<=4;j++)
? ? ? ? ? ? ? ? ? ? if(TankCheak ( *AI_tank , j ))? //循環(huán)判斷坦克四周有無障礙,此函數(shù)返值1為可通過
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? if(j==5)? ? ? ? ?//j==5說明此坦克四周都有障礙物,無法通行
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? PrintTank(*AI_tank);
? ? ? ? ? ? ? ? ? ? return;? ? ? //則跳過下面的while循環(huán)以防程序卡死
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? while(TankCheak ( *AI_tank , AI_tank->direction) == 0)? //如果前方仍有障礙
? ? ? ? ? ? ? ? ? ? AI_tank->direction=(rand()%4+1);? ? ? ? ? ? ? ? ? ? //則換個隨機(jī)方向檢測
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? PrintTank(*AI_tank);? ? ?//打印AI坦克
? ? }
}
?
?
void BuildMyTank (Tank* my_tank) //建立我的坦克
{
? ? my_tank->x=15;
? ? ? ?my_tank->y=38;
? ? ? ?my_tank->stop=NULL;
? ? ? ?my_tank->direction=1;
? ? my_tank->model=0;
? ? my_tank->color=1;
? ? my_tank->alive=1;
? ? my_tank->my=1;
? ? my_tank->CD=7;
? ? PrintTank (*my_tank) ;? ?//打印我的坦克
}
?
?
void MoveMyTank(int turn )? ?//玩家專用函數(shù),turn為keyboard函數(shù)里因輸入不同方向鍵而傳入的不同的值
{
? ? ClearTank(my_tank.x , my_tank.y);? ? ? ? //map 數(shù)組中“我的坦克”參數(shù)清除工作已在此函數(shù)中完成
? ? my_tank.direction=turn;? ? ? ? ? ? ? ? ? //將鍵盤輸入的方向值傳入我的坦克方向值
? ? if(TankCheak ( my_tank , my_tank.direction ))? //若此時我的坦克當(dāng)前方向上無障礙
? ? ? ? switch (turn)
? ? ? ? {
? ? ? ? ? ? case UP? ?: my_tank.y--; break;? //上前進(jìn)一格
? ? ? ? ? ? case DOWN : my_tank.y++; break;? //下前進(jìn)一格
? ? ? ? ? ? case LEFT : my_tank.x--; break;? //左前進(jìn)一格
? ? ? ? ? ? case RIGHT: my_tank.x++; break;? //右前進(jìn)一格
? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //若坦克當(dāng)前方向上有障礙則跳過坐標(biāo)變化直接打印該轉(zhuǎn)向的坦克
? ? PrintTank (my_tank);
}
?
?
bool TankCheak(Tank tank,int direction)? //檢測坦克前方障礙函數(shù),參量為假坐標(biāo)。返值1為可通過,返值0為阻擋(人機(jī)共用)
{
? ? switch(direction)? ? ? ? ? ? ? ? ? ? //direction變量? ?1上,2下,3左,4右
? ? {
? ? ? ? case UP:
? ? ? ? ? ? if (map[tank.y-2][tank.x]==0 && map[tank.y-2][tank.x-1]==0 && map[tank.y-2][tank.x+1]==0)
? ? ? ? ? ? ? ? return 1;
? ? ? ? ? ? else
? ? ? ? ? ? ? ? return 0;
? ? ? ? case DOWN:
? ? ? ? ? ? if (map[tank.y+2][tank.x]==0 && map[tank.y+2][tank.x-1]==0 && map[tank.y+2][tank.x+1]==0)
? ? ? ? ? ? ? ? return 1;
? ? ? ? ? ? else
? ? ? ? ? ? ? ? return 0;
? ? ? ? case LEFT:
? ? ? ? ? ? if (map[tank.y][tank.x-2]==0 && map[tank.y-1][tank.x-2]==0 && map[tank.y+1][tank.x-2]==0)
? ? ? ? ? ? ? ? return 1;
? ? ? ? ? ? else
? ? ? ? ? ? ? ? return 0;
? ? ? ? case RIGHT:
? ? ? ? ? ? if (map[tank.y][tank.x+2]==0 && map[tank.y-1][tank.x+2]==0 && map[tank.y+1][tank.x+2]==0)
? ? ? ? ? ? ? ? return 1;
? ? ? ? ? ? else
? ? ? ? ? ? ? ? return 0;
? ? ? ? default:
? ? ? ? ? ? printf("錯誤!!");
? ? ? ? ? ? Sleep(5000);
? ? ? ? ? ? return 0;
? ? }
}
?
?
void ClearTank(int x,int y)? ?//清除坦克函數(shù)(人機(jī)共用)
{
? ? for(int i=0;i<3;i++)
? ? ? ? for(int j=0;j<3;j++)
? ? ? ? {? ? ? ? ? ? ? ? ? ? ?//將坦克占用的地圖上的九格去掉
? ? ? ? ? ? ?map[y+j-1][x+i-1]=0;
? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN);
? ? ? ? ? ? GoToxy(2*x+2*j-2,y+i-1);
? ? ? ? ? ? printf("? ");
? ? ? ? }
}
?
?
void PrintTank(Tank tank)? ? ?//打印坦克(人機(jī)共用) 由于讀取的Tank參數(shù)較多,故就不將參數(shù)一一傳入了
{? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// tank.color參數(shù)對應(yīng)不同的顏色,范圍 1 ~ 6
? ? ColorChoose(tank.color);? //顏色選擇函數(shù)? ?定義一個數(shù)組里裝著字符指針(既裝字符串)的數(shù)組指針(指向一維數(shù)組首地址的指針)
? ? char *(*tankF)[4] = tank_figure[tank.model];? //將二維數(shù)組首址賦初值給數(shù)組指針 model==0為我的坦克,4為電腦1坦克,8為電腦2,類推
? ? for(int i = 0; i < 3; i++)? ?
? ? {
? ? ? ? GoToxy((tank.x-1)*2 , tank.y-1+i);? ? ? ? //在坦克中心坐標(biāo)的左邊,上中下三行打印
? ? ? ? printf("%s", tankF[i][tank.direction-1]); //打印的是地址,地址既字符串
? ? ? ? ?for(int j=0;j<3;j++)
? ? ? ? ? ? if(tank.my)? ? ? ?//若為我的坦克
? ? ? ? ? ? ? ? map[tank.y+j-1][tank.x+i-1]=200;? //在map上把"坦克"九格填滿代表敵我坦克的參數(shù)。敵方此值為100~103,我方為200
? ? ? ? ? ? else
? ? ? ? ? ? ? ? map[tank.y+j-1][tank.x+i-1]=100+tank.num;? //這樣可以通過map值讀取坦克編號,讀取操作在BulletHit 函數(shù)
? ? }
}
?
?
void HideCursor()? //隱藏光標(biāo)
{? ? ? ? ? ? ? ? ? //CONSOLE_CURSOR_INFO結(jié)構(gòu)體包含控制臺光標(biāo)的信息,DWORD dwSize光標(biāo)百分比厚度(1~100)和BOOL bVisible光標(biāo)是否可見
? ? CONSOLE_CURSOR_INFO cursor_info={1,0};
? ? SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info); //SetConsoleCursorInfo用來設(shè)置指定的控制臺光標(biāo)的大小和可見性。
}
?
?
void GoToxy(int x,int y)? //光標(biāo)移動函數(shù),X表示橫坐標(biāo),Y表示縱坐標(biāo)。
{
? ? COORD? coord;? ? ? ? ?//使用頭文件自帶的坐標(biāo)結(jié)構(gòu)
? ? coord.X=x;? ? ? ? ? ? //這里將int類型值傳給short,不過程序中涉及的坐標(biāo)值均不會超過short范圍
? ? coord.Y=y;
? ? HANDLE a=GetStdHandle(STD_OUTPUT_HANDLE);? //獲得標(biāo)準(zhǔn)輸出句柄
? ? SetConsoleCursorPosition(a,coord);? ? ? ? ?//以標(biāo)準(zhǔn)輸出的句柄為參數(shù)設(shè)置控制臺光標(biāo)坐標(biāo)
}
?
?
void ColorChoose(int color)? ?//顏色選擇函數(shù)
{
? ? switch(color)
? ? {
? ? ? ? ? ?case 1:? ? ? ? ? ? ? ?//天藍(lán)色(我的坦克顏色)
? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN|FOREGROUND_BLUE);
? ? ? ? ? ? break;
? ? ? ? case 2:? ? ? ? ? ? ? ?//綠色
? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN);? ??
? ? ? ? ? ? break;
? ? ? ? case 3:? ? ? ? ? ? ? ?//黃色
? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN);
? ? ? ? ? ? break;
? ? ? ? case 4:? ? ? ? ? ? ? ?//紅色
? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED);
? ? ? ? ? ? break;
? ? ? ? case 5:? ? ? ? ? ? ? ?//紫色
? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_BLUE);
? ? ? ? ? ? break;
? ? ? ? case 6:? ? ? ? ? ? ? ?//白色
? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
? ? ? ? ? ? break;
? ? ? ? case 7:? ? ? ? ? ? ? ?//深藍(lán)色(∵顏色深難與黑色背景辨識度不高 ∴坦克顏色不選用此顏色),只用在字體顏色閃爍中
? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_BLUE);
? ? ? ? ? ? break;
? ? }
}
?
?
void Stop()? ? //暫停
{
? ? int color=1,timing=0;
? ? while(1)
? ? {
? ? ? ? if(timing++%30==0)
? ? ? ? {
? ? ? ? ? ? ColorChoose(color);? ?//顏色選擇
? ? ? ? ? ? GoToxy(100,13);? ? ? ?//副屏幕打印
? ? ? ? ? ? printf("游戲暫停");
? ? ? ? ? ? GoToxy(88,17);
? ? ? ? ? ? printf("按回車鍵回到游戲");
? ? ? ? ? ? GoToxy(88,18);
? ? ? ? ? ? printf("或按 Esc鍵退出游戲");
? ? ? ? ? ? if(++color==8)
? ? ? ? ? ? ? ? color=1;
? ? ? ? }
? ? ? ? if (GetAsyncKeyState( 0xD )& 0x8000)? ? ? //回車鍵
? ? ? ? {
? ? ? ? ? ? GoToxy(100,13);? ? ? ?//副屏幕打印
? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN|FOREGROUND_BLUE);
? ? ? ? ? ? printf("正在進(jìn)行");? ?//覆蓋掉原來的提示
? ? ? ? ? ? GoToxy(88,17);
? ? ? ? ? ? printf("? ? ? ? ? ? ? ? ? ? ?");
? ? ? ? ? ? GoToxy(88,18);
? ? ? ? ? ? printf("? ? ? ? ? ? ? ? ? ? ?");
? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? else if(GetAsyncKeyState( 0x1B )& 0x8000) //Esc鍵退出? ??
? ? ? ? ? ? exit(0);
? ? ? ? Sleep(20);
? ? }
}
?
?
void ClearMainScreen()? //主屏幕清屏函數(shù),因使用system("cls");再打印框架有一定幾率造成框架上移一行的錯誤,所以單獨(dú)編寫清屏函數(shù)
{
? ? for(int i=1;i<40;i++)
? ? {
? ? ? ? GoToxy(2,i);
? ? ? ? printf("? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ");
? ? }
}
?
?
void Frame ()? ? ?//打印游戲主體框架
{? ? ? ? ? ? ? ? ?//SetConsoleTextAttribute為設(shè)置文本顏色和文本背景顏色函數(shù)
? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY);
? ? printf("? ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁? ");
? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY|FOREGROUND_BLUE);?
? ? printf("? ▂▂▂▂▂▂▂▂▂▂▂▂▂ \n");
? ? for(int i=0;i<14;i++)
? ? {
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN|FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_INTENSITY);
? ? ? ? printf("▕? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ▏");
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY|FOREGROUND_BLUE);?
? ? ? ? printf(" |? ? ? ? ? ? ? ? ? ? ? ? ? |\n");
? ? }
? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN|FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_INTENSITY);
? ? printf("▕? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ▏");
? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY|FOREGROUND_BLUE);?
? ? printf(" |═════════════|\n");
? ? for(int i=0;i<24;i++)
? ? {
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN|FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_INTENSITY);
? ? ? ? printf("▕? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ▏");
? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY|FOREGROUND_BLUE);?
? ? ? ? printf(" |? ? ? ? ? ? ? ? ? ? ? ? ? |\n");
? ? }
? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN|FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_INTENSITY);
? ? printf("? ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔? ");
? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY| FOREGROUND_BLUE);?
? ? printf(" ﹊﹊﹊﹊﹊﹊﹊﹊﹊﹊﹊﹊﹊﹊\n");
? ? SideScreen ();? //打印副屏幕
}
?
?
void PrintMap()? ? ?// 打印地圖(地圖既地圖障礙物)
{
? ? for(int j=0;j<41;j++)
? ? ? ? for(int i=0;i<41;i++)
? ? ? ? ? ? if(map[i][j]==6)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN
? ? ? ? ? ? ? ? ? ? |FOREGROUND_RED|FOREGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_RED|BACKGROUND_BLUE);
? ? ? ? ? ? ? ? GoToxy(2*j,i);
? ? ? ? ? ? ? ? printf("■");
? ? ? ? ? ? }
? ? ? ? ? ? else if(map[i][j]==2)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN|FOREGROUND_RED|BACKGROUND_GREEN|BACKGROUND_RED);
? ? ? ? ? ? ? ? GoToxy(2*j,i);
? ? ? ? ? ? ? ? printf("▓");
? ? ? ? ? ? }
? ? ? ? ? ? else if(map[i][j]==1)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|BACKGROUND_GREEN|BACKGROUND_RED);
? ? ? ? ? ? ? ? GoToxy(2*j,i);
? ? ? ? ? ? ? ? printf("▓");
? ? ? ? ? ? }
? ? ? ? ? ? else if(map[i][j]==5)
? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|BACKGROUND_BLUE|FOREGROUND_BLUE|FOREGROUND_GREEN);
? ? ? ? ? ? ? ? GoToxy(2*j,i);
? ? ? ? ? ? ? ? printf("~");
? ? ? ? ? ? }
? ? SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN);
? ? GoToxy(38,37);? ? ?printf("◣◢");
? ? GoToxy(38,38);? ? ?printf("███");? ? //∵無論地圖怎么變,家所在位置不變,且家的字符多種,不方便用上述方式打印
? ? GoToxy(38,39);? ? ?printf("◢█◣");? ? //∴直接打印(且家的map值與符號無關(guān))
}
?
?

覺得可以的給個贊吧
也是支持原作者