本文主要是介绍2022综合实验4 - 弹球模拟,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、实验目的与要求:
- 进一步掌握数组的定义与使用;进一步掌握函数的定义和函数调用方法;
- 学习和掌握结构体(结构体数组)的定义和使用方法。
- 进一步掌握 C 语言的编程方法;学习动画程序的基本设计思想和方法。
- 编译并运行你的程序。调试正确后,将必要的文件如项目 project 目录压缩文件上载。
- 提交正式的实验报告。实验报告的文件名为“学号姓名 综 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=-dx,t=0
这篇关于2022综合实验4 - 弹球模拟的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!