2022综合实验4 - 弹球模拟

一、实验目的与要求

  1. 进一步掌握数组的定义与使用;进一步掌握函数的定义和函数调用方法;
  2. 学习和掌握结构体(结构体数组)的定义和使用方法。
  3. 进一步掌握 C 语言的编程方法;学习动画程序的基本设计思想和方法。
  4. 编译并运行你的程序。调试正确后,将必要的文件如项目 project 目录压缩文件上载。
  5. 提交正式的实验报告。实验报告的文件名为“学号姓名 综 4”,如“202x280168 王 敬华 综 4.doc”

对编程的具体要求:

1) 每个弹球用一个结构体 BALL 变量描述(可参考前面的程序说明),一组弹球用结

构体数组定义;

2) 除 main()主函数外,你的程序至少还要编写 4 个以上的自定义子函数。

3) 主函数在一个单独的源文件中;其余子函数放在另外一个源文件中;必要的声明与

定义(包括结构体的定义、以及子程序的声明等)放在自定义的一个*.h 头文件中。

需要在新建的项目 project 里面这样添加多个文件实现。

4) 本程序应可以模拟 1 到 NUM 个弹球的运动,NUM 是由预处理语句定义的一个整

型常量,表示模拟中可能的最多的弹球数。

5) 模拟程序在每次运行时,弹球的实际个数由用户输入。若用户输入的弹球个数小于

1,则设置弹球数量为 1;若用户输入的弹球个数大于 NUM 时,则设置弹球个数为

NUM;若用户输入的弹球个数在 1 到 NUM 之间,则弹球个数为用户输入的个数。

6) 弹球在画面中的初始位置、运动方向(运动速度均为 1.0)、显示的颜色(不同颜色

的弹球可以用不同的字符表示)等,在程序运行开始时随机设置。

7) 弹球运动时,如果碰到墙壁则直接弹回;如果碰到地面(下墙壁),则在弹回的同

时,要求发出碰撞声,同时统计弹球撞到地面的次数。发出碰撞声可以使用下面语

句实现:putchar('\a');

8) 弹球运动过程中,如果两个弹球相撞,两个弹球的速度大小不变,但运动速度的方向都逆时针旋转 90 度,同时两个弹球的颜色都发生改变。

二、实验步骤与过程:

(给出编程思路并表示出算法,如画出流程图或伪代码表示。提供带注释的核心程序代码。要求:设计思路合理,程序运行正确、输出界面符合实验要求。)

该程序的主函数流程图如下所示

具体代码如下:

1.main.c

#include "headfile.h"

int count = 0; //弹球碰撞地面次数统计

int main(void) {

  srand((unsigned)time(NULL));

  printf("请输入弹球个数(1~10)");

  int num;

  scanf("%d",&num);

  if (num<1) num=1;

  if (num>10) num=10;

  struct BALL b[10];

  initBall(b, num);

  char cWin[HEIGHT][WIDTH];

  memset(cWin, ' ', HEIGHT*WIDTH);

  initCharPicture(cWin);

while(1)

{

system("cls"); //执行清屏命令

redrawCWin(b, num);

Sleep(200);   //0.2s的暂停  

count=moveBall(b,num);

}             

  return 0;

}

2.Function.c

#include "headfile.h"

/*

功能:将二维图像数组初始化为背景图模式。

 */

void initCharPicture(char cWin[][WIDTH])

{

        int i;

        for (i=0;i<79;i++)

        {

                 cWin[0][i]='-';

                 cWin[23][i]='=';

        }

        for (i=1;i<23;i++)

        {

                 cWin[i][0]='|';

                 cWin[i][78]='|';

        }

}

/*

功能:根据num个弹球的最新位置,在屏幕上绘制出当前弹球位置的图像。

 */

void redrawCWin(struct BALL ball[], int num)

{

        int i,j;

       char cWin[24][80];

       memset(cWin, ' ', HEIGHT*WIDTH);

        initCharPicture(cWin);

         for (i=0;i<num;i++)

         {

               cWin[ball[i].wX][ball[i].wY]= ball[i].body[ball[i].sel];

         }

         for (i=0;i<24;i++)

 {

         for (j=0;j<80;j++)

         {

                printf("%c",cWin[i][j]);

       

         }

         printf("\n");

 }

}

/*

功能:对num个弹球的数据进行初始化。

 */

void initBall(struct BALL ball[], int num)

{

        int i;

        for (i=0;i<num;i++)

        {

                 ball[i].body[0]='@';

                 ball[i].body[1]='0';

                 ball[i].sel = rand()%2;

                 ball[i].X = (1+rand()%22);

                 ball[i].Y = (1+rand()%77);

                 ball[i].wX = (int)(ball[i].X + 0.5);

                 ball[i].wY = (int)(ball[i].Y + 0.5);

                 ball[i].dX = cos((PI* (rand()%359) )/180);

                 ball[i].dY = sin((PI* (rand()%359) )/180);

        }

}

int moveBall(struct BALL ball[], int num)

 {

                int i;

                 int count=0;

       

                 for(i=0;i<num;i++)  //正常移动

        {

                ball[i].X += ball[i].dX ;

                 ball[i].Y += ball[i].dY ;

        }

       

                 for (i = 0; i < num; i++)

        {

                 int j;

                

                 if(ball[i].X>23)   //碰到地面 ,发出声音,记录次数

                 {

                         putchar('\a');

                         count++;

                 }

                 if(ball[i].X<0||ball[i].X>23)  //碰到地面和上壁

                 {

                         ball[i].dX = -ball[i].dX;

                         ball[i].X += ball[i].dX ;

                 }

                

            if(ball[i].Y<0||ball[i].Y>78) //碰到左右壁

                 {

                         ball[i].dY = -ball[i].dY;

                         ball[i].Y += ball[i].dY;

                 }

                

                 for(j=i+1;j<num;j++)   //两球相撞

                 {

                         double dist=distBetweenBalls(ball, i, j); 

                         if(dist<1)    //dist小于1相撞

                         {     

                                  double t1,t2;            //dX' = - dY dY' = dX 按原方向逆时针旋转90

                                  t1=ball[i].dX;

                                  t2=ball[j].dX;

                                  ball[i].dX=-ball[i].dY;

                                  ball[j].dX=-ball[j].dY;

                                  ball[i].dY=t1;

                                  ball[j].dY=t2;

                                 

                                  if(ball[i].sel==0) ball[i].sel=1;   //碰撞改变颜色(字符)

                                  if(ball[i].sel==1) ball[i].sel=0;

                                 

                                  if(ball[j].sel==0) ball[j].sel=1;

                if(ball[j].sel==1) ball[j].sel=0;

                         }

                                 

                 }

                        

                         ball[i].wX = (int)(ball[i].X + 0.5);  //将最终的移动距离赋给真实值

                         ball[i].wY = (int)(ball[i].Y + 0.5);

               

        }

                 return count;

}

/*

功能:计算弹球 i 和弹球 j 之间的距离的平方,用来判断是否相互碰撞。

*/

double distBetweenBalls(struct BALL ball[], int i, int j)

{

        double dist;

       dist = pow((ball[j].X - ball[i].X),2)+pow((ball[j].Y-ball[i].Y),2);

       return dist;

}

3. headfile.h

/* 各种系统库函数头文件的包含 */

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <time.h>

#include <Windows.h>

/* 各种符号常量的定义 */

#define PI 3.14159265358979324

//动画图像的维度,上下纵向HEIGHT、左右横向WIDTH

#define HEIGHT 24

#define WIDTH 80

#define NUM 10 //弹球的最大数量

/* 各种复杂数据结构类型如结构体、共用体的定义 */

struct BALL {

  char body[2];//两个不同的字符,分别代表两个不同颜色的球

  int sel;   //当前球的颜色。0表示第一种颜色,1表示第二种颜色

  int wX;    //在二维数组中,球在x方向的实际显示位置(整数)

  int wY;    //在二维数组中,球在y方向的实际显示位置(整数)

  double X;  //球在x方向的精确位置(实数)

  double Y;  //球在y方向的精确位置(实数)

  double dX; //球在x方向的速度(实数)

  double dY; //球在y方向的速度(实数)

};

/* 所有自定义函数的声明 */

void initCharPicture(char cWin[][WIDTH]);

void redrawCWin(struct BALL ball[], int num);

void initBall(struct BALL ball[], int num);

int  moveBall(struct BALL ball[], int num);

double distBetweenBalls(struct BALL ball[], int i, int j);

三、实验结果与分析:

(其中:提交程序运行情况及运行结果的截图,对实验结果与实验数据进行分析、评价,说明实验结果是否达到实验要求?同时回答“思考与上机验证问题”。)

程序最终呈现如下:

模拟了弹球碰撞,各个实验要求均有满足,本次实验成功完成!

思考题(选做):

如果考虑到重力的作用,其他条件不变,如何设计你的程序?谈谈你的设计思想。

重力的作用只有在垂直方向上体现,所以只需要在弹球X方向上添加一个g的向下的加速度,首先开始的速度dx随机,在主函数定义一个时间t,则dx=dx+g*t,下方有碰撞时,dx=-dxt=0

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值