Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

C Program Help/suggestions

Status
Not open for further replies.

RussOSU

Technical User
Apr 16, 2001
93
US
I am trying to create a program for my C programming class that does a crude animation. I am given a .txt file in which I have to read the following characters which are in a 3x3 array.
o
-|-
/ I then have to display him, pause, erase him and draw him in a new position. I have to do this in a two-dimensional world. I have to do this while moving him in random amounts in a -1...+1 range vertically and -3...+3 horizontally. The whole thing should be random. I also have added a break if the figure moves outside of the default 76x24 screen size. I have a very crude random function set up and would like some help simplifying the function. [6*round(((double)rand()/(double)RAND_MAX)-3]and the y which is right below it in the code under animation. I am also having a problem with the colors. There is a 5x5 box around the center of the screen (35,10) beyond that box I have the screen broken up into 4 quads (UR, LR, LL, UL) each quad has a different color. My problem is that the character is staying the original white and I am not sure why. Any help would be great. The full code is below.

Russ

#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>

#define NUMROWS 3
#define NUMCOLS 4

#define BLACK 0
#define DARKBLUE 1
#define DARKGREEN 2
#define DARKCYAN 3
#define DARKRED 4
#define DARKMAGENTA 5
#define DARKYELLOW 6
#define DARKWHITE 7
#define GREY 8
#define BLUE 9
#define GREEN 10
#define CYAN 11
#define RED 12
#define MAGENTA 13
#define YELLOW 14
#define WHITE 15


/********** Define Prototypes **********/
void readData(char drawVals[NUMROWS][NUMCOLS]);
void drawFigure(int x,int y, char drawVals[NUMROWS][NUMCOLS]);
void pause(int pauseTime);
void animate(char drawVals[NUMROWS][NUMCOLS], char blankVals[NUMROWS][NUMCOLS]);

/********** Defining readData Function **********/

void readData(char drawVals[NUMROWS][NUMCOLS])
{
char *filename;
int i;
int j;

FILE *fp;

filename = &quot;data6engr.txt&quot;;

if((fp = fopen(filename, &quot;r&quot;)) == NULL)
{
printf(&quot;can't open file %s\n&quot;, filename);
}

for(i=0; i<NUMROWS; i++)
{
for(j=0; j<NUMCOLS; j++)
{
drawVals[j] = fgetc(fp);
}
}

fclose(fp);
}

/********** Defining drawFigure Function **********/

void drawFigure(int x,int y, char drawVals[NUMROWS][NUMCOLS])
{
int i;
int j;

for(i=0; i<NUMROWS; i++)
{
for(j=0; j<NUMCOLS; j++)
{
_gotoxy(x+j,y+i);
printf(&quot;%c&quot;,drawVals[j]);
}
}

fflush(stdout);
}

/********** Defining Pause Function **********/

void pause(int pauseTime)
{
int pause;

pause = clock() + pauseTime;

while(clock() < pause)
{
}

return;
}

/********** Defining Animate Function **********/

void animate(char drawVals[NUMROWS][NUMCOLS], char blankVals[NUMROWS][NUMCOLS])
{
int i;
int x;
int xLow;
int xHigh;
int y;
int yLow;
int yHigh;
int pauseTime;

i = 0;
pauseTime = 30;
x = 35;
y = 10;
xLow = x - 5;
xHigh = x + 5;
yLow = y - 5;
yHigh = y + 5;

while(i < 150)
{
drawFigure(x,y,drawVals);

pause(pauseTime);

drawFigure(x,y,blankVals);

x += 6*round((double)rand() / (double)RAND_MAX) - 3;
y += 3*round((double)rand() / (double)RAND_MAX) - 1;


srand(0);

if(x > xHigh && y < yLow)
_textcolor(BLUE);
if(x > xHigh && y > yHigh)
_textcolor(RED);
if(x < xLow && y > yHigh)
_textcolor(CYAN);
if(x < xLow && y < yLow)
_textcolor(GREEN);

if(x > 76 || x <= 0)
break;
if(y > 23 || y <= 0)
break;

++i;
}

fflush(stdout);
return;
}

int main(void)
{
char drawVals[NUMROWS][NUMCOLS],blankVals[NUMROWS][NUMCOLS] = {' '};
readData(drawVals);
animate(drawVals,blankVals);

return 0;
}
 
> srand(0);
Do this ONCE at the start of the program - all you're doing is resetting the seed back to the same constant value each time around the loop

> 6*round(((double)rand()/(double)RAND_MAX)-3
See You could just make a function out of it - since you repeat the same code twice (almost).

> My problem is that the character is staying the original white and I am not sure why
>
Code:
printf(&quot;%c&quot;,drawVals[i][j]);
Try
Code:
_cprintf(&quot;%c&quot;,drawVals[i][j]);

This should be as for printf, but paying attention to the _textcolor() settings
 
you might try this variation of this function. It might hanadle the error for the file access better. If the file is not available you should only display the error message.
if the file was not able to be opened there aint nothing to close ();

void readData(char drawVals[NUMROWS][NUMCOLS])
{
char *filename;
int i;
int j;

FILE *fp;

filename = &quot;data6engr.txt&quot;;

if ((file = fopen(Logfile, &quot;r&quot;)) != NULL)
{
if((fp = fopen(filename, &quot;r&quot;)) != NULL)
{
for(i=0; i<NUMROWS; i++)
{
for(j=0; j<NUMCOLS; j++)
{
drawVals[j] = fgetc(fp);
}
}
}

fclose(fp);
}
else
{
printf(&quot;can't open file %s\n&quot;, filename);
}
}


tomcruz.net
 
I would also add a return value and check it so you dont do anthing in the main if the function has an error.

if (readData(drawVals))
animate(drawVals,blankVals);

tomcruz.net

 
There's still quite a lot of educational milage in nice little animations like this.

In drawing the figure, I would be quite inclined to write each line of the figure as a single string, rather than a set of characters drawn by a loop. i.e. your figure drawing function becomes a single loop rather than two nested. The reason is that I'd strongly expect the C compiler's code for writing a string to the screen to be much more efficient than a high-level implementation of it (which is basically what your inner loop is). Not very important in this case, but in a more complex animation might help efficiency....

This suggestion won't help you much because your figure moves up to 3 spaces sideways, but in figures that move smaller distances, a good way to handle rubbing out is to keep a figure one space bigger than the real text bit on all sides. i.e. surround your little man with a border of spaces. Then if you write this, without worrying about deleting the old little man, provided the new man is within one position of the old, the border will handle the erasing for you.
This technique is only useful if the perimeter of the figure is much larger than its area, so the bigger your animation, the more it's worth considering. At best it saves you a lot of drawing and a function call.

At risk of telling you the obvious, if you were animating a man with a bit more direction about him, you might like to set two variables dx and dy, which you add to the position each loop, and then change dx and dy randomly every n loops.

Pauses: the elegant way to do this on a PC (we get platform dependant here) is to wait for the return of the screen's electron beam. This is the same speed (depending on text mode) on all PCs, from a lowly 1MHz 8086 to a super-pentium, so your program will become suitable for every PC in the world! Also it prevents nasty visual effects where your animation happens at precisely the moment the electron beam is whizzing past. More details on request, but I'm strictly in DOS world about this....
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top