C语言实现坦克大战~
新人投稿~
很快啊!大一上学期就过去了。
作为新时代的大学生,C语言大作业怎么能应付呢!!
所以,放弃高数放弃英语的我(咳,没捡起来过)好不容易写了一个自己的东西——坦克大战😁
虽然还是有很多地方借鉴,比如隐藏光标函数啊,不闪瞎眼的函清屏数啊,
:_ :附良心课程链接:
链接: 做游戏,学编程(C语言).
但是!真真的用心写了!
那个AI坦克我实在是没啥想法,只能用概率让他多向基地走走攻击攻击——来自郭老师😛的提议。大佬有想法的可以评论区告诉我,感激不尽!
对对对!还有一个没实现(迫于时间紧迫🤐)坦克子弹不能连发,要是连发。。可能有点鬼畜😭。
废话就真么多~
下面是代码~(写给自己看所以没有很多注释😶)
/**************************
作者:wckkkkk
时间:11.12
项目名称:坦克大战
**************************/
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
#include <time.h>
//系统参数
/** 画布 */
int high;
int width;
/**操作*/
char op[8] ="wsadsdsd";
/**结束*/
int over = 0;
//不一样的数字代表不一样的墙
/** map */
int map[12][22] = //画地图
{
{-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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1},
{-1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,-1},
{-1,0,0,1,0,0,3,0,1,1,1,1,1,1,1,0,0,0,1,0,0,-1},
{-1,0,0,1,1,0,3,0,0,0,0,0,0,0,0,0,0,0,1,0,0,-1},
{-1,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,3,0,-1},
{-1,0,0,-1,-1,-1,-1,0,1,0,1,0,1,0,1,0,3,0,3,-1,0,-1},
{-1,0,0,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0,0,3,-1,-1,0,-1},
{-1,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,3,-1,-1,0,0,-1},
{-1,0,1,1,1,1,0,0,0,1,1,2,1,1,0,3,-1,-1,0,1,0,-1},
{-1,0,0,0,0,1,0,0,0,1,2,2,2,1,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}
};
/**over map*/
int overmap[4][12][22] =
{
{
//win
{-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1},
{-1,0,1,0,0,0,0,0,1,0,1,1,1,0,1,1,0,0,0,1,0,-1},
{-1,0,1,0,0,0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,-1},
{-1,0,0,1,0,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,0,-1},
{-1,0,0,1,0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,1,0,-1},
{-1,0,0,1,0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,1,0,-1},
{-1,0,0,0,1,1,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,-1},
{-1,0,0,0,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,1,0,-1},
{-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1},
{-1,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}
},
{
//lose
{-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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1},
{-1,0,1,0,0,0,0,1,1,1,0,0,0,1,1,0,0,1,1,1,1,-1},
{-1,0,1,0,0,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,0,-1},
{-1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,1,0,0,0,-1},
{-1,0,1,0,0,0,1,0,0,0,1,0,1,1,0,0,0,1,1,1,0,-1},
{-1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,1,0,0,0,-1},
{-1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,0,-1},
{-1,0,1,0,0,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,0,-1},
{-1,0,1,1,1,0,0,1,1,1,0,0,0,1,1,0,0,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,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}
},
{
//draw
{-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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1},
{-1,0,1,1,0,0,0,1,1,1,1,0,0,1,0,0,1,0,0,0,1,-1},
{-1,0,1,0,1,0,0,1,0,0,1,0,1,1,1,0,1,0,0,0,1,-1},
{-1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,0,1,-1},
{-1,0,1,0,0,1,0,1,1,1,1,0,1,0,1,0,1,0,1,0,1,-1},
{-1,0,1,0,0,1,0,1,1,0,0,0,1,1,1,0,1,0,1,0,1,-1},
{-1,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,-1},
{-1,0,1,1,0,0,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,-1},
{-1,0,1,0,0,0,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,-1},
{-1,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}
},
{
//game over
{-1,0,1,1,1,0,0,0,1,0,0,0,0,1,0,1,0,0,1,1,1,-1},
{-1,1,0,0,0,0,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,-1},
{-1,1,0,0,1,1,0,1,1,1,0,0,1,0,1,0,1,0,1,1,0,-1},
{-1,1,0,0,0,1,0,1,0,1,0,0,1,0,0,0,1,0,1,0,0,-1},
{-1,0,1,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,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,-1},
{-1,0,0,1,1,0,0,1,0,1,0,0,0,1,1,1,0,0,1,1,1,-1},
{-1,0,1,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,1,0,1,-1},
{-1,0,1,0,0,1,0,1,0,1,0,0,0,1,1,0,0,0,1,1,1,-1},
{-1,0,1,0,0,1,0,1,1,1,0,0,0,1,0,0,0,0,1,1,0,-1},
{-1,0,0,1,1,0,0,0,1,0,0,0,0,1,1,1,0,0,1,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}
}
};
//对象们
/**子弹*/
typedef struct
{
//坐标
int x;
int y;
int velocity;//速度
int form;//方向
char kind;//形式
} BUL;
/** tank */
typedef struct
{
/** 坦克坐标 */
int x;
int y;
/** 坦克方向*/
int direction;//0 up ; 1 down;2 left;3 right
/**坦克形态*/
char form[5] ;
/**子弹*/
BUL bul;
/**敌坦克cd*/
long long CD;
} TANK;
TANK tank;
TANK emery;
//主体函数
void menu();//开始菜单
void start();//初始化
void show();//显示画面
void print(int o,int h,int w);//打印地图
void update_un();//与用户输入输入无关的更新
void update_ne();//与用户输入有关的更新
void Overmenu(int result);//结束
void color(short x) ;//颜色
void gotoxy(int x,int y);//清屏函数
void HideCursor();//隐藏光标
/**坦克函数*/
void MoveTank(char input,TANK * tk);//坦克移动
void AIemery();//自动化敌坦克
/**子弹函数*/
//子弹发射
void bulfire(TANK *tk);
//子弹移动
void updatebul(TANK *tk);
//子弹打墙
void collition_bull_wall(TANK *tk);
//子弹打坦克
void collition_bull_TANK() ;
/***************************************************************************************
主函数
***************************************************************************************/
int main()
{
menu();
start();
while(!over)
{
update_ne();
update_un();
show();
}
system("cls");
Overmenu(over);//结束
return 0;
}
/***********************************************************************************
************************************************************************************/
void menu()//开始菜单
{
printf("*********************************************\n");
color(13);
printf(" 欢迎来到坦克大战 \n");
color(16);
printf("*********************************************\n");
color(4);
printf("几点说明:\n");
printf(" 1.坦克形态为:A V < > ,代表四个方向,\n 由wasd控制,子弹按下空格发射。\n\n");
printf(" 2.我方坦克为红色,敌方为黄色。\n\n");
printf(" 3.务必将输入法改成英文!!!!!\n\n");
printf(" 4.子弹连发未实现>﹏<\n");
color(16);
printf("*********************************************\n");
printf("按任意键进入进入...");
getch();
system("cls");
}
void start()//初始化
{
high = 12;
width = 22;
tank.x = 10;
tank.y = 8;
tank.form[0] = 'A';
tank.form[1] = 'V';
tank.form[2] = '<';
tank.form[3] = '>';
tank.direction = 0;
tank.bul.kind = '*';
tank.bul.x = 0;
tank.bul.y = 0;
tank.bul.velocity = 0;
emery.x = 1;
emery.y = 1;
emery.form[0] = 'A';
emery.form[1] = 'V';
emery.form[2] = '<';
emery.form[3] = '>';
emery.direction = 1;
emery.bul.kind = '*';
emery.bul.x = 0;
emery.bul.y = 0;
emery.bul.velocity = 0;
emery.CD = 10;
HideCursor();//隐藏光标
srand((unsigned)time(NULL));//随机数
}
void show()//显示画面
{
gotoxy(0,0);//清屏
for(int i = 0; i < high; i++) /**显示界面*/
{
for(int j = 0; j < width; j++)
{
if(map[i][j] == -1)
{
color(3);
printf("■");
color(16);
}
else if(map[i][j] == 1)
{
color(12);
printf("□");
color(16);
}
else if(map[i][j] == 2)
{
color(6);
printf("▲");
color(16);
}
else if(map[i][j] == 3)
{
color(2);
printf("■");
color(16);
}
else if(i == tank.x &&j == tank.y)
{
color(4);
printf("%c ",tank.form[tank.direction]);
color(16);
}
else if(i == emery.x &&j == emery.y)
{
color(6);
printf("%c ",emery.form[emery.direction]);
color(16);
}
else if(i == tank.bul.x && j == tank.bul.y)
{
color(4);
printf("%c ",tank.bul.kind);
color(16);
}
else if(i == emery.bul.x && j == emery.bul.y)
{
color(6);
printf("%c ",emery.bul.kind);
color(16);
}
else printf(" ");
}
printf("\n");
}
}
void update_un()//与用户输入输入无关的更新
{
AIemery();
updatebul(&tank);
updatebul(&emery);
collition_bull_wall(&tank);
collition_bull_wall(&emery);
collition_bull_TANK();
}
void update_ne()//与用户输入有关的更新
{
char input;
if(kbhit())
{
input = getch();
if(input == ' ')
bulfire(&tank);
else
MoveTank(input,&tank);//坦克移动
}
}
void bulfire(TANK *tk)
{
//根据坦克方向定位子弹
switch(tk->direction)
{
case 0:
tk->bul.x =tk->x - 1;
tk->bul.y = tk->y;
break;
case 1:
tk->bul.x =tk->x + 1;
tk->bul.y = tk->y;
break;
case 2:
tk->bul.x =tk->x ;
tk->bul.y = tk->y - 1;
break;
case 3:
tk->bul.x =tk->x ;
tk->bul.y = tk->y + 1;
break;
}
tk->bul.form = tk->direction;
}
void updatebul(TANK *tk)
{
if(tk->bul.x > 0)
tk->bul.velocity++;
if(tk->bul.velocity == 20)
{
switch(tk->bul.form)
{
case 0:
tk->bul.x --;
break;
case 1:
tk->bul.x ++;
break;
case 2:
tk->bul.y--;
break;
case 3:
tk->bul.y++;
break;
}
tk->bul.velocity = 0;
}
}
void collition_bull_wall(TANK *tk)
{
if(map[tk->bul.x][tk->bul.y] == 1)
{
map[tk->bul.x][tk->bul.y] = 0;
tk->bul.x =0;
tk->bul.y = 0;
tk->bul.form = tk->direction;
}
if(map[tk->bul.x][tk->bul.y] == -1)
{
tk->bul.x =0;
tk->bul.y = 0;
tk->bul.form = tk->direction;
}
}
void collition_bull_TANK()
{
if(tank.bul.x == emery.x && tank.bul.y == emery.y)
{
emery.x = 0;
emery.y = 0;
over = 1;
}
if(emery.bul.x == tank.x && emery.bul.y == tank.y)
{
tank.x = 0;
tank.y = 0;
over = 2;
}
if(emery.x == tank.x&&emery.y == tank.y )
{
tank.x = 0;
tank.y = 0;
emery.x = 0;
emery.y = 0;
over = 3;
}
if(emery.bul.x == tank.bul.x && emery.bul.y == tank.bul.y)
{
tank.bul.x = 0;
tank.bul.y = 0;
emery.bul.x = 0;
emery.bul.y = 0;
}
if(map[emery.bul.x][emery.bul.y] == 2||map[tank.bul.x][tank.bul.y] == 2)
over = 2;
}
void AIemery()//自动化敌坦克
{
emery.CD ++;
if(emery.CD == 150)
{
int temp = rand()%4;
if(emery.x >= 9)//横坐标等于基地
temp = 5;
else if(emery.y >=10 && emery.y <=12)//纵坐标=基地
temp = 6;
else if(emery.x == tank.x && map[tank.x][tank.y] != 3)//横坐标=我方坦克
temp = 7;
else if(emery.y == tank.y&& map[tank.x][tank.y] != 3)//纵坐标=我方坦克
temp = 8;
switch(temp)
{
case 0://打子弹+坦克移动
temp = rand()%4;
bulfire(&emery) ;
MoveTank(op[temp+rand()%4],&emery);
break;
case 1://改方向+坦克移动
temp = rand() % 4;
emery.direction = temp;
MoveTank(op[temp+rand()%4],&emery);
break;
case 3://坦克移动+打子弹
temp = rand() % 4;
MoveTank(op[temp+rand()%4],&emery);
bulfire(&emery) ;
break;
case 4://坦克移动+打子弹
temp = rand() % 4;
MoveTank(op[temp+rand()%4],&emery);
bulfire(&emery) ;
break;
case 5://横坐标=基地
if(emery.y > width/2)
{
MoveTank('a',&emery);
bulfire(&emery) ;
}
else
{
MoveTank('d',&emery);
bulfire(&emery) ;
}
break;
case 6://纵坐标=基地
MoveTank('s',&emery);
bulfire(&emery) ;
break;
case 7://横坐标=我方
if(emery.y > tank.y)
{
MoveTank('a',&emery);
bulfire(&emery) ;
}
else
{
MoveTank('d',&emery);
bulfire(&emery) ;
}
break;
case 8://纵坐标=我方
if(emery.x >tank.x)
{
MoveTank('w',&emery);
bulfire(&emery) ;
}
else
{
MoveTank('s',&emery);
bulfire(&emery) ;
}
break;
}
emery.CD = 0;
}
}
void MoveTank(char input,TANK * tk)//坦克移动
{
switch(input)
{
/**控制坦克*/
case 'w'://方向一致且不撞地图
if(tk->direction == 0 && map[tk->x-1] [tk->y]!= -1&& map[tk->x-1] [tk->y]!= 1&& map[tk->x-1] [tk->y]!= 2)
tk->x--;
else
tk->direction = 0;
break;
case 's':
if(tk->direction == 1 && map[tk->x+1] [tk->y] != -1&&map[tk->x+1] [tk->y] != 1&&map[tk->x+1] [tk->y] != 2)
tk->x++;
else
tk->direction = 1;
break;
case 'a':
if(tk->direction == 2 && map [tk->x][tk->y-1] != -1 && map [tk->x][tk->y-1] != 1 && map [tk->x][tk->y-1] != 2)
tk->y--;
else
tk->direction = 2;
break;
case 'd':
if(tk->direction == 3 && map[tk->x][tk->y+1] != -1&& map[tk->x][tk->y+1] != 1&& map[tk->x][tk->y+1] != 2)
tk->y++;
else
tk->direction = 3;
break;
}
}
void Overmenu(int result)//结束
{
print(result-1,high,width);
printf("*********************************************\n");
printf("按任意键进入退出...");
getch();
system("cls");
print(3,high,width);
Sleep(1000);
}
void print(int o,int h,int w)//打印地图
{
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
switch(overmap[o][i][j])
{
case -1:
color(3);
printf("■");
color(16);
break;
case 0:
printf(" ");
break;
case 1:
color(12);
printf("□");
color(16);
break;
}
}
printf("\n");
}
}
void gotoxy(int x,int y)//清屏函数
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle,pos);
}
void HideCursor()//隐藏光标
{
CONSOLE_CURSOR_INFO cursor_info = {1,0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
}
void color(short x) //自定义函根据参数改变颜色
{
if(x>=0 && x<=15)//参数在0-15的范围颜色
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x); //只有一个参数,改变字体颜色
else//默认的颜色白色
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}