Multiple Bouncing Balls Program in C (Please Help)

Pages: 12
I am trying to make a program in C with multiple bouncing balls. I know it is a very known program and I have already searched the internet and seen different versions of it. However, because I am new in programming, I didn’t manage to understand them and answer my questions. The problem is that I have created a code, but my program doesn’t run properly. To be more exact, I think the part where it reads the data is fine, but then there is a problem in the code of the graphics.h library. I cannot understand where the problem is, as it is the first time I use this library. Please help me and be as lenient as possible.

Thank you in advamce.

Here is my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  #include <stdio.h>
#include <graphics.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

int main()
{
    FILE *input;
    int n, *num, i, total, j;
    if((input=fopen("data.txt", "r"))!=NULL)
    {
        fscanf(input, "%d", &n);
        total=n*7;
        num=(int *) malloc(total*sizeof(int));
        if(num!=NULL)
        {
           for(i=0; i<total; i++)
           {
               fscanf(input, "%d", &num[i]);
           }
           fclose(input);
           clock_t start,finish, previous;
           double step;
           int gdriver = DETECT, gmode, errorcode;
           initgraph(&gdriver, &gmode, "");
           errorcode = graphresult();
           if (errorcode != grOk) 
           { 
               printf("Graphics error: %s\n", grapherrormsg(errorcode));
               system ("pause");
               exit(1);               
           }
           start=clock();
           previous=start;
           j=0;               
           do
           {
               for(i=0; i<=n; i++)
               {
                   finish = clock();
                   step = (finish-previous)*1.0/CLOCKS_PER_SEC;
                   if (step >= 0.03)
                   {
                    previous = finish;
                    setfillstyle(SOLID_FILL,BLACK);
                    setcolor(BLACK);
                    fillellipse(num[j],num[j+1],num[j+4],num[j+4]);
                    num[j]+= num[j+5]*step;
                    num[j+1]+= num[j+6]*step;
                    if (num[j]+num[j+4]>=getmaxx() || num[j]-num[j+4]<=0)
                    num[j+5] *= -1;
                    if (num[j+1]+num[j+4]>=getmaxy() || num[j+1]-num[j+4]<=0)
                    num[j+6] *= -1;
                    setfillstyle(SOLID_FILL,RED);
                    setcolor(RED);
                    fillellipse(num[j],num[j+1],num[j+4],num[j+4]);
                   }
               }
         }
     while (!kbhit());
     closegraph();
    }
   } 
  }
    else
    {
        printf("Could not allocate memory\n\n");
    }
}
else
{
    printf("Could not open file\n\n");
}
system("pause");
return 0;
}
Last edited on
Looks like you're programming in C, not C# (or C++). Is that what you meant to do?

graphics.h is not a standard C++ library. It did used to be commonly bundled with some very old compilers, about 25 years ago. About 15 years ago, there was a library made to replicate it (WinBGIm). Where did you get it?
Last edited on
Yes I am programming in C. Not in C#. My mistake.

Well, I downloaded the WinBGIm library and I inserted it to my compiler (CodeBlocks), but then I saw on the internet that most people used graphics.h to make a program like that. I have read in a forum that you should create a C++ project in order to use graphics.h. So, I created a C++ project and programmed in C. The problem is that this is the first time I use this library and I don't know many things. However, I know that there is not any problem in the syntax, as the program begins to run and then crushes. I think the problem is with the functions of it.
How does your input file look like ?
It looks like this:

2
100 150 4 350 20 50 80
200 250 7 950 40 -50 20
Very strange.
When I ran it inside VS 2015 several times it crashed only occasionally.
The problem was inside kbhit() so it's more a problem inside the library - not in your code.
The only problem in your code I can see is that the ball gets stuck at the top-left corner.
So, what can I do to fix these problems?
One option is not to use kbhit() - just close the window with the mouse.
Use for(;;) instead of the do while loop
It crushes again.
I can imagine that it crashes because you draw permanently the same without pause. That's not good. Better draw once and then when things change.
How can I do that? I thought this way because I want multiple balls to interact with each other.
Last edited on
Take a look at this:

https://www.cs.colorado.edu/~main/bgi/doc/
https://www.cs.colorado.edu/~main/bgi/doc/delay.html

The delay depends on how fast the balls should move. Maybe try a delay of 100ms or more. The delay would replace lines 41 to 45. You current calculated delay is 30ms.

Also consider using a std::vector for num.

Notice that n is actually useless (so is malloc(...)) because you use j which doesn't change instead of i.
With a for(;;) loop it works fine in VS.
Maybe the problem is your MinGW compiler that comes with Code::Blocks.
I use j because at the input file there are n balls and every seven numbers are about each ball. However, there was indeed a mistake and I think I have fixed it. But, it still crushes even with a delay of 300ms. By the way, the program is written in C. I don't know C++. The only reason I created a C++ file is to be able to use the graphics.h library.

Check out my corrections:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
do
           {
               j=0;
               for(i=0; i<=n; i++)
               {
                   finish = clock();
                   step = (finish-previous)*1.0/CLOCKS_PER_SEC;
                   if (step >= 0.03)
                   {
                       previous = finish;
                       setfillstyle(SOLID_FILL,BLACK);
                       setcolor(BLACK);
                       fillellipse(num[j],num[j+1],num[j+4],num[j+4]);
                       num[j]+= num[j+5]*step;
                       num[j+1]+= num[j+6]*step;
                       if (num[j]+num[j+4]>=getmaxx() || num[j]-num[j+4]<=0)
                       {
                           num[j+5] *= -1;
                       }
                       if (num[j+1]+num[j+4]>=getmaxy() || num[j+1]-num[j+4]<=0)
                       {
                           num[j+6] *= -1;
                       }
                       setfillstyle(SOLID_FILL,RED);
                       setcolor(RED);
                       fillellipse(num[j],num[j+1],num[j+4],num[j+4]);
                       j=j+7;
                   }
               }
         }
Last edited on
I see only a black screen.
step is always < 0 in step = (finish-previous)*1.0/CLOCKS_PER_SEC;
Before you make more experiments I would suggest to bring a bit of structure into your code with some functions.
1
2
3
4
5
6
7
8
9
10
11
typedef struct TBall
{
  int X;
  int Y;
  int Xvel; // horizontal velocity
  int Yvel; // vertical velocity
}Ball;

void UpdateBall(Ball *ball);
void HideBall(const Ball *ball);
void DrawBall(const Ball *ball);

A very simple demo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "winbgim.h"

typedef struct TBall
{
  int X;
  int Y;
  int Xvel; // horizontal velocity
  int Yvel; // vertical velocity
  int radius;
  int COLOR;
}Ball;

void UpdateBall(Ball *ball);
void HideBall(const Ball *ball);
void DrawBall(const Ball *ball);

int main()
{
  Ball ball = {10,10, 3, 3, 15, RED};
  int gdriver = DETECT, gmode, errorcode;
  initgraph(&gdriver, &gmode, "");
  errorcode = graphresult();

  if (errorcode != grOk)
  {
    printf("Graphics error: %s\n", grapherrormsg(errorcode));
    system("pause");
    exit(1);
  }

  while (!kbhit())
  {
    HideBall(&ball);
    UpdateBall(&ball);
    DrawBall(&ball);
    Sleep(50);
  }

  closegraph();

}

void UpdateBall(Ball *ball)
{
  ball->X += ball->Xvel;
  ball->Y += ball->Yvel;

  // TO DO
  // check collisions and reverse speed if necessary
}
void HideBall(const Ball *ball)
{
  setfillstyle(SOLID_FILL, BLACK);
  setcolor(BLACK);
  fillellipse(ball->X, ball->Y, ball->radius, ball->radius);
}
void DrawBall(const Ball *ball)
{
  setfillstyle(SOLID_FILL, ball->COLOR);
  setcolor(ball->COLOR);
  fillellipse(ball->X, ball->Y, ball->radius, ball->radius);
}
I don't know what's wrong with my compiler. Your demo code doesn't run too. It crushes again.
Try without kbhit()
1
2
3
4
5
6
7
while (true)
  {
    HideBall(&ball);
    UpdateBall(&ball);
    DrawBall(&ball);
    Sleep(50);
  }

Why don't you use Visual Studio instead?
Again. It doesn't work. The reason I use CodeBlocks is because this project is for the university and our tutor user the same program. So, if it doesn't work at me, it won't work for him too. He also gave us some instructions on how to do it. That's why I cannot change my code too much.
If you run the code under a debugger, it will tell you which line causes the crash and you can fix it.
Pages: 12