2022综合实验4 - 弹球模拟

2023-10-25 05:59
文章标签 综合 模拟 实验 2022 弹球

本文主要是介绍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

这篇关于2022综合实验4 - 弹球模拟的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/280485

相关文章

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

hdu4431麻将模拟

给13张牌。问增加哪些牌可以胡牌。 胡牌有以下几种情况: 1、一个对子 + 4组 3个相同的牌或者顺子。 2、7个不同的对子。 3、13幺 贪心的思想: 对于某张牌>=3个,先减去3个相同,再组合顺子。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOExcepti

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

STL经典案例(四)——实验室预约综合管理系统(项目涉及知识点很全面,内容有点多,耐心看完会有收获的!)

项目干货满满,内容有点过多,看起来可能会有点卡。系统提示读完超过俩小时,建议分多篇发布,我觉得分篇就不完整了,失去了这个项目的灵魂 一、需求分析 高校实验室预约管理系统包括三种不同身份:管理员、实验室教师、学生 管理员:给学生和实验室教师创建账号并分发 实验室教师:审核学生的预约申请 学生:申请使用实验室 高校实验室包括:超景深实验室(可容纳10人)、大数据实验室(可容纳20人)、物联网实验

【算法专场】模拟(下)

目录 前言 38. 外观数列 算法分析 算法思路 算法代码 1419. 数青蛙 算法分析 算法思路 算法代码  2671. 频率跟踪器 算法分析 算法思路 算法代码 前言 在前面我们已经讲解了什么是模拟算法,这篇主要是讲解在leetcode上遇到的一些模拟题目~ 38. 外观数列 算法分析 这道题其实就是要将连续且相同的字符替换成字符重复的次数+

生信圆桌x生信分析平台:助力生物信息学研究的综合工具

介绍 少走弯路,高效分析;了解生信云,访问 【生信圆桌x生信专用云服务器】 : www.tebteb.cc 生物信息学的迅速发展催生了众多生信分析平台,这些平台通过集成各种生物信息学工具和算法,极大地简化了数据处理和分析流程,使研究人员能够更高效地从海量生物数据中提取有价值的信息。这些平台通常具备友好的用户界面和强大的计算能力,支持不同类型的生物数据分析,如基因组、转录组、蛋白质组等。