先上效果图
然后是完整代码
1 #include<stdio.h> 2 #include<conio.h> 3 #include<stdlib.h> 4 #include<time.h> 5 6 //打印飞机上下边框,长度为112,实际长度为110 7 void border(){ 8 int i; 9 for (i = 112; i > 0 ; --i){ 10 printf("*"); 11 } 12 printf(" "); 13 } 14 15 //产生80以内的靶子 16 int target(int judge){ 17 int i; 18 static int s; 19 if(!judge){ 20 srand((int)time(0)); 21 s=rand()%80; 22 } 23 printf("*"); 24 for(i=109;i>s;--i){ 25 printf(" "); 26 } 27 printf("*"); 28 for(;i>0;--i){ 29 printf(" "); 30 } 31 printf("* "); 32 return s; 33 } 34 35 //打印含有飞机主体的6行 36 int air(int x, int a,int d){ 37 int i,sum; 38 char t1[15]=" * ",t2[15]=" * * * ", 39 t3[15]=" * * * ",t4[15]=" * ", 40 t5[15]=" * * ",t6[15]=" * *"; 41 for(i=1;i<=6;++i){ 42 printf("*"); 43 //放缩 44 for(sum = 0; sum <= d-a-x;sum++){ 45 printf(" "); 46 } 47 //打印飞机主体 48 switch(i){ 49 case 1 :printf("%s",t1);break; 50 case 2 :printf("%s",t2);break; 51 case 3 :printf("%s",t3);break; 52 case 4 :printf("%s",t4);break; 53 case 5 :printf("%s",t5);break; 54 case 6 :printf("%s",t6);break; 55 } 56 //打印机体后部分空白 57 for(;100-sum>=0;sum++){ 58 printf(" "); 59 } 60 //结尾 61 printf("* "); 62 } 63 return d-a-x; 64 } 65 66 //打印子弹 67 void air1(int x, int a,int d,int i){ 68 int sum; 69 for(;i>0;--i){ 70 printf("*"); 71 //放缩 72 for(sum = 0; sum <= d-a-x+4;sum++){ 73 printf(" "); 74 } 75 printf("|"); 76 //打印机体后部分空白 77 for(;108-sum>=0;sum++){ 78 printf(" "); 79 } 80 //结尾 81 printf("* "); 82 } 83 } 84 //打印上半部分左右边框 85 void bordery1(int w, int s,int i){ 86 int a, b; 87 for(;i>w-s;--i){ 88 printf("*"); 89 for(b=110;b>0;--b){ 90 printf(" "); 91 } 92 printf("* "); 93 } 94 95 } 96 97 //打印下半部分左右边框 98 void bordery2(int w, int s){ 99 int i, b; 100 for(i=w-s;i>0;--i){ 101 printf("*"); 102 for(b=110;b>0;--b){ 103 printf(" "); 104 } 105 printf("* "); 106 } 107 } 108 int main(){ 109 int x=0,a=0,d=0,w=0,s=0,judge=0,i=20,z,b,y,grade=0; 110 int control; 111 while(1){ 112 control = getch(); 113 switch(control){ 114 case 'a':++a;break; 115 case 'd':++d;break; 116 case 'w':++w;break; 117 case 's':++s;break; 118 } 119 if(w-s <0){ 120 --s; 121 } 122 if(w-s>2){ 123 ++s; 124 } 125 if(d-a-x <-1){ 126 --a; 127 } 128 if(d-a-x>100){ 129 ++a; 130 } 131 system("cls"); 132 border(); 133 judge=target(judge); 134 bordery1(w,s,i); 135 air(x,a,d); 136 bordery2(w,s); 137 border(); 138 if(control==' '){ 139 b=19; 140 for(z=20;z>0;--z){ 141 system("cls"); 142 border(); 143 judge=target(judge); 144 bordery1(w,s,z); 145 --b; 146 air1(x,a,d,3); 147 bordery1(w,s,17-z); 148 air(x,a,d); 149 bordery2(w,s); 150 border(); 151 } 152 printf("s=%d 机头=%d ",104-judge,d-a); 153 if(104-judge==d-a){ 154 ++grade; 155 printf("得分:%d ",grade); 156 judge=0; 157 } 158 } 159 } 160 161 }
算法:1.将整个图案分为边框、飞机图案、靶图案、火线几个部分。其中飞机、靶、火线和边框结合为下:
2.通过d-a-x计算飞机位置(按头部算),然后用这个数值循环画出火线图案。
3.火线移动是改变火线在整个程序的纵向位置实现的(减少上半部分边框数量,等数量增加下半部分边框数量)。
未解决问题:屏幕闪烁、随机靶位置可能过界、子弹发射不稳定
2018/3/13
部分库函数:
l system("cls"); // 清屏 头文件#include <stdlib.h> 缺点屏幕闪烁计算时间长
l rand();// 产生随机数 头文件#include<stdlib.h>因为rand()函数是按指定的顺序来产生整数,因此每次执行上面的语句都打印相同的两个值,所以说C语言的随机并不是真正意义上的随机,有时候也叫伪随机数。
l srand(void srand(unsigned seed))//生成随机种子 头文件#include<stdlib.h> 是随机数发生器的初始化函数。
产生随机靶子模块解释:
int target(int judge){ int i; static int s; if(!judge){ srand((int)time(0)); s=rand()%70; } printf("*"); for(i=109;i>s;--i){ printf(" "); } printf("*"); for(;i>0;--i){ printf(" "); } printf("* "); return s; }
judge=target(judge);
首次执行函数会产生随机靶子,judge用于接收产生的随机数值,并且在第二次调用函数时判断是否需要再次生成随机靶子(如果靶子被击中则让judge=0(Flase) ,!Judge(Ture)执行rand函数再次生成随机数)
添加功能:操作指引和温馨提醒
int control,control2; //向用户介绍,和温馨提示 printf(" 玩家您好: 欢迎试玩飞机打靶游戏 "); printf(" 按WASD控制飞机方向,空格发射子弹 "); printf("温馨提示! 由于屏幕闪烁严重,不要在夜间或暗处使用"); printf(" 输入后等待程序响应再输入"); printf(" 请确认输入方式为英文 (按任意键两次确认)"); control2 = getch(); while(control2){
效果图:
2018/3/24 补充
更新--解决屏幕闪烁、靶子不稳定、子弹不真实问题
#include<stdlib.h> #include <stdio.h> #include <windows.h> #include <conio.h> #include "stdafx.h" #include <time.h> // 全局变量 int width, hight; int borderWidth,borderHight; int positionX, positionY; int target; int score; //移动光标 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); /* HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_CURSOR_INFO CursorInfo; GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息 CursorInfo.bVisible = false; //隐藏控制台光标 SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态 */ } void borderUD() { int i; for (i = borderWidth; i > 0; --i) { printf("*"); } printf(" "); } void borderLR() { int a, b; for (a = hight; a > 0; --a) { printf("*"); for (b = width; b > 0; --b) { printf(" "); } printf("* "); } } // 生成新靶 void aim1() { srand((int)time(0)); target = 2 + rand() % (width-3) ; if (target > width) aim1(); } //打印靶子 void aim() { aim1(); if (target > width) aim1(); int i; printf("1"); for (i = width; i > target+1; --i) printf(" "); printf("3"); for (; i > 1; --i) printf(" "); printf("1 "); } //打印飞机 void air() { int i,a,b; a = width - 3; for (i = 0; i < 2; ++i) { printf("*"); for (b = a; b > positionX;--b) printf(" "); switch (i) { case 0 :printf(" 0 "); break; case 1 :printf("000"); break; } for (; b > 0; --b) printf(" "); printf("* "); } } void fire() { int a, b,i; a = positionX - 1, b = hight + 1; printf("a"); for (i = hight; i > 0; --i) { gotoxy(a, b); printf("2"); Sleep(50); gotoxy(a, b); printf(" "); --b; } if (positionX == width - target + 1) { printf("a"); gotoxy(width - target , 1); printf(" "); aim1(); ++score; Sleep(100); gotoxy(width - target , 1); printf("3"); } } //改变飞机位置 void updateWithoutInput() { if (_kbhit()) { gotoxy(positionX - 2, hight + 2); printf(" "); gotoxy(positionX - 2, hight + 3); printf(" "); int a; a = _getch(); if (a == 'a' || a == 'A') --positionX; if (a == 'd' || a == 'D') ++positionX; if (positionX <= 3) positionX = 3; if (positionX >= width - 1) positionX = width - 1; gotoxy(positionX-2, hight + 2); printf(" 0 "); gotoxy(positionX-2, hight + 3); printf("000"); if (a == ' ') fire(); //printf("%d %d ", positionX, width - target + 1); gotoxy(0, hight + 4); printf(" 得分:%d", score); } } //数据初始化 void startup() { width = 50; hight = 20; borderWidth = width + 2; borderHight = hight + 2; target = 0; positionY = hight + 1; positionX = width / 2; HideCursor(); score = 0; } //画面显示 void show() { startup(); borderUD(); aim(); borderLR(); air(); borderUD(); getchar(); } int main() { startup(); show(); while (1) { updateWithoutInput(); } return 0; }
屏幕闪烁解决方法:
飞机、子弹、靶子:利用循环画出最初的游戏画面,然后利用光标移动函数,打印空格覆盖原有图案实现消失。
再次利用光标移动函数,将光标移动到下次需要打印的地方,打印需要图案实现出现。
反复消失、出现、消失、出现。就实现了动画移动效果。
2018/4/6 完善