话不多说,放代码
#include<stdio.h>
#include<math.h>
#include<Windows.h>
#include<time.h>
#include<stdlib.h>
//界面的长和宽
#define HIGN 27
#define WIDTH 60
//暂定球与球之间的距离≤1时视为碰撞
#define REACH 1
#define PI 3.14159//圆周率
#define NUM 10 //球的最大数量
int COUNT = 0;
struct BALL {
char body;//单个字符,表示球在dos控制台应有的形态
int sel; //当前球的颜色。0表示第一种颜色,1表示第二种颜色
int wX; //在二维数组中,球在x方向的实际显示位置(整数)
int wY; //在二维数组中,球在y方向的实际显示位置(整数)
double X; //球在x方向的精确位置(实数)
double Y; //球在y方向的精确位置(实数)
double dX; //球在x方向的速度(实数)
double dY; //球在y方向的速度(实数)
};
void Manage(struct BALL*, int);//每一个周期进行的一次处理
void print_pos(struct BALL*, int);//一组球的输出函数
void swap(double*, double*);//double类型的交换函数
void color(const unsigned short);//设定颜色的函数
int main() {
srand(time(NULL));
printf("请输入球的个数:");
int num;//球的个数
scanf("%d", &num);
if (num > NUM)num = NUM;
struct BALL* ball = (struct BALL*)malloc(sizeof(struct BALL) * num);
for (int i = 0; i < num; i++) {
(ball + i)->sel = rand() % 15 + 1; //颜色
(ball + i)->X = rand() % WIDTH + 1; //x精确坐标
(ball + i)->Y = rand() % HIGN + 1; //y精确坐标
if ((ball + i)->X < 1) //边界情况
(ball + i)->wX = 1;
else if ((ball + i)->X >WIDTH) //边界情况
(ball + i)->wX = WIDTH;
else
(ball + i)->wX = (int)((ball + i)->X+0.5); //四舍五入
if ((ball + i)->Y < 1) //边界情况
(ball + i)->wY = 1;
else if ((ball + i)->Y > HIGN) //边界情况
(ball + i)->wY = HIGN;
else
(ball + i)->wY = (int)((ball + i)->Y+0.5); //四舍五入
(ball + i)->body = 'o';//球是圆的,所以直接全部设为小写字母o
double xita = rand() % 360;
(ball + i)->dX = cos(PI * xita / 180);
(ball + i)->dY = sin(PI * xita / 180);
}
while (TRUE)
{
HANDLE hOut;
COORD pos={0,0};
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,pos);//重设打印起点
CONSOLE_CURSOR_INFO cci;
GetConsoleCursorInfo(hOut, &cci);
cci.bVisible = FALSE;
SetConsoleCursorInfo(hOut, &cci);
print_pos(ball, num);
Manage(ball, num);
Sleep(25);//休眠25毫秒
}
free(ball); //其实这条是多余的
return 1;
}
//显示操作台和某球的实际位置
void print_pos(struct BALL* p, int num) {
//上边界
for (int i = 0; i < WIDTH + 2; i++)
putchar('*');
putchar('\n');
//中间部分
for (int i = 1; i <= HIGN; i++) {
putchar('|');
for (int j = 1; j <= WIDTH; j++) {
short flag = 1;
for (int k = 0; k < num; k++) {
if ((p + k)->wX == j && (p + k)->wY == i) {
color((p + k)->sel);
putchar((p + k)->body);
color(7);
flag = 0;
break;
}
}
if (flag)
putchar(' ');
}
putchar('|');
putchar('\n');
}
//下边界
for (int i = 0; i < WIDTH + 2; i++)
putchar('*');
putchar('\n');
}
void Manage(struct BALL* p, int num) {
for (int i = 1; i < num; i++)
for(int j=0;j<num-i;j++)
if (pow((p + i)->X - (p + j)->X, 2) + pow((p + i)->Y - (p + j)->Y, 2) <= pow(REACH,2))
{
swap(&(p + i)->dX, &(p + j)->dX);
swap(&(p + i)->dY, &(p + j)->dY);
}
for (int i = 0; i < num; i++){
if ((p + i)->X <= 1 || (p + i)->X >= WIDTH) {
(p + i)->dX = -(p + i)->dX;
}
if ((p + i)->Y <= 1) {
(p + i)->dY = -(p + i)->dY;
}
if ((p + i)->Y >= HIGN) {
(p + i)->dY = -(p + i)->dY;
}
(p + i)->X += (p + i)->dX;
(p + i)->Y += (p + i)->dY;
if ((p + i)->X < 1)
(p + i)->wX = 1;
else if ((p + i)->X > WIDTH)
(p + i)->wX = WIDTH;
else
(p + i)->wX = (int)((p + i)->X + 0.5);
if ((p + i)->Y < 1)
(p + i)->wY = 1;
else if ((p + i)->Y > HIGN)
(p + i)->wY = HIGN;
else
(p + i)->wY = (int)((p + i)->Y + 0.5);
}
}
void swap(double* x, double* y) {
double temp = *x;
*x = *y;
*y = temp;
}
void color(const unsigned short color1)
{
if (color1 >= 0 && color1 <= 15)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color1);
else
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}
效果