飞机打靶-C语言实践笔记

先上效果图

然后是完整代码

  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("\n");
 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("*\n");
 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("*\n");     
 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("*\n");     
 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("*\n");
 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("*\n");
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\n",104-judge,d-a);
153         if(104-judge==d-a){
154             ++grade;
155             printf("得分:%d\n",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 srandvoid 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("*\n");
    return s;
}

 

judge=target(judge);

首次执行函数会产生随机靶子,judge用于接收产生的随机数值,并且在第二次调用函数时判断是否需要再次生成随机靶子(如果靶子被击中则让judge=0(Flase)  ,!Judge(Ture)执行rand函数再次生成随机数)

 

添加功能:操作指引和温馨提醒

    int control,control2;
    //向用户介绍,和温馨提示
        printf("\n\n\n\n玩家您好:\n  欢迎试玩飞机打靶游戏\n");
        printf("  按WASD控制飞机方向,空格发射子弹\n\n\n"); 
        printf("温馨提示!\n  由于屏幕闪烁严重,不要在夜间或暗处使用");
        printf("\n  输入后等待程序响应再输入");
        printf("\n\n\n\n请确认输入方式为英文        (按任意键两次确认)");
        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("\n");
}

void borderLR() {
    int a, b;
    for (a = hight; a > 0; --a) {
        printf("*");
        for (b = width; b > 0; --b) {
            printf(" ");
        }
        printf("*\n");
    }
}

// 生成新靶
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\n");
}

//打印飞机
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("*\n");
    }
}

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("\n\n得分:%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    完善

 

 

 

 

 

                                                                                           

 

转载于:https://www.cnblogs.com/xiaoxu-xmy/p/8554914.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值