Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- car_race_brick_game_v1.c author: Dragan Milicev
- https://www.facebook.com/dmilicev
- Program is tested on Windows 7 Ultimate.
- Car race, simplified graphics.
- Use the left and right arrows to control the car.
- Each wall passed brings 1 point.
- In the beginning you have 3 lives.
- You lose one life with every collision with the wall.
- For every 10 points you get extra life.
- The race starts slowly, at a speed of 50.
- Every 25 points the speed increases by 10.
- Press the space bar to pause.
- Press the ESCAPE key to exit the game.
- Good luck!
- Inspired from:
- https://create.arduino.cc/projecthub/Homer/arduino-web-based-car-race-brick-game-cb1b30
- Video:
- https://youtu.be/BvSdFNwcyLY
- Source code:
- https://mega.nz/file/G9RzVSKY#vgxKoEZf5EygomVuU0GJOPL2A2WPwZ8H_UbTKK299Qo
- Compiled exe file:
- https://mega.nz/file/upBHDSSD#-w-bbZ2K_i4tPrZf4hCO5FP2NlQ8Bt5mxcVSExpq7Xw
- Zipped source and exe file:
- https://mega.nz/file/mgBRiS5A#dgjXpF_TyqMJ-IT4gBQLiQdIo4raPhg25g032Zwttpw
- You can find all my C programs at Dragan Milicev's pastebin:
- https://pastebin.com/u/dmilicev
- */
- #include <stdio.h>
- #include<stdlib.h> // for rand()
- #include<time.h> // for random number generator
- #include <windows.h> // tracking cursor all the time, for cursor position functions
- // gotoxy(x,y) , wherex() , wherey(), showcursor(), hidecursor()
- #define MAX_COLUMNS 80 // of the console window
- #define MAX_ROWS 80 // of the console window
- #define UP 72 // up arrow
- #define DOWN 80 // down arrow
- #define LEFT 75 // left arrow
- #define RIGHT 77 // right arrow
- #define SPACE 32 // Space key, to pause the game
- #define ESC 27 // Escape key to quit the game
- // ----------CURSOR CONTROL FUNCTIONS------------------------------------------
- // make console cursor invisible
- void hidecursor()
- {
- HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_CURSOR_INFO info;
- info.dwSize = 20;
- info.bVisible = FALSE;
- SetConsoleCursorInfo(consoleHandle, &info);
- }
- // make console cursor invisible
- void showcursor()
- {
- HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_CURSOR_INFO info;
- info.dwSize = 20;
- info.bVisible = TRUE;
- SetConsoleCursorInfo(consoleHandle, &info);
- }
- // place cursor at position ( x, y ) = ( column, row )
- void gotoxy( int column, int row )
- {
- COORD coord;
- coord.X = column;
- coord.Y = row;
- SetConsoleCursorPosition( GetStdHandle(STD_OUTPUT_HANDLE), coord );
- }
- // return x coordinate (column) of current cursor position
- // on failure return -1
- int wherex()
- {
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- if (!GetConsoleScreenBufferInfo( GetStdHandle(STD_OUTPUT_HANDLE), &csbi ) )
- return -1;
- return csbi.dwCursorPosition.X;
- }
- // return y coordinate (row) of current cursor position
- // on failure return -1
- int wherey()
- {
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- if (!GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &csbi ) )
- return -1;
- return csbi.dwCursorPosition.Y;
- }
- // END OF-----CURSOR CONTROL FUNCTIONS------------------------------------------
- // ----------TEXT AND BACKGROUND COLOR CONTROL FUNCTIONS------------------------
- void ClearConsoleToColors(int ForgC, int BackC)
- {
- WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);
- ///Get the handle to the current output buffer...
- HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
- ///This is used to reset the carat/cursor to the top left.
- COORD coord = {0, 0};
- ///A return value... indicating how many chars were written
- /// not used but we need to capture this since it will be
- /// written anyway (passing NULL causes an access violation).
- DWORD count;
- ///This is a structure containing all of the console info
- /// it is used here to find the size of the console.
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- ///Here we will set the current color
- SetConsoleTextAttribute(hStdOut, wColor);
- if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
- {
- ///This fills the buffer with a given character (in this case 32=space).
- FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
- FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count );
- ///This will set our cursor position for the next print statement.
- SetConsoleCursorPosition(hStdOut, coord);
- }
- return;
- } //ClearConsoleToColors()
- void SetColorAndBackground(int ForgC, int BackC)
- {
- WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);;
- SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), wColor);
- return;
- } //SetColorAndBackground()
- // END OF----TEXT AND BACKGROUND COLOR CONTROL FUNCTIONS------------------------
- // wait (do nothing) for time in milliseconds
- void wait( int milliseconds )
- {
- clock_t start_time = clock(); // get start time
- // looping (do nothing) till required time is not acheived
- while ( clock() < start_time + milliseconds )
- ; // do nothing
- } // wait()
- // generate and return random integer number between lower and upper, including them.
- int get_random_integer_from_lower_to_uppper(int lower, int upper)
- {
- // generate and return random number between 0 and upper-1
- //return( rand() % upper );
- // generate and return random number between 1 and upper
- //return( rand() % upper + 1 );
- // generate and return random integer number between lower and upper
- return( (rand() % (upper - lower + 1)) + lower );
- } // get_random_integer_from_lower_to_uppper()
- // Deletes the car in place xc,yc
- void delete_car( int xc, int yc, int x, int y )
- {
- gotoxy(x+xc,yc); // delete car
- putchar(32); // space, blanko
- } // print_car()
- // Print the car in place xc,yc
- void print_car( int xc, int yc, int x, int y )
- {
- gotoxy(x+xc,yc); // print car
- putchar(219); // 219, 176, 177, 178
- } // print_car()
- // Makes an empty line, a wall without bricks.
- void make_empty_line( int BL[MAX_ROWS], int row, int column )
- {
- int i;
- for(i=0;i<column;i++){ // we reset them all to zero
- BL[i] = 0;
- }
- } // make_empty_line()
- // Makes one row (line) BL[] of Brik_Matrix BM[][]
- // with num_of_bricks randomly arranged in a line
- void make_Brik_Line( int BL[MAX_ROWS], int row, int column, int num_of_bricks )
- {
- int r, c, counter=0;
- int completed[MAX_COLUMNS];
- for(c=0;c<column;c++){ // we reset them all to zero
- BL[c] = 0;
- completed[c] = 0;
- }
- while( counter < num_of_bricks ){
- r = get_random_integer_from_lower_to_uppper(0,column-1);// a random number between 1 and column
- if( !completed[r] ){ // if that has not already been processed
- BL[r] = 1; // there is a brick
- completed[r] = 1; // that is now processed
- counter++; // we increase the counter of bricks in line
- }
- }
- } // make_Brik_Line()
- // Prints the entire matrix with bricks, BM with rows and columns
- // on place x,y
- void print_Brik_Matrix( int x, int y, int BM[MAX_ROWS][MAX_COLUMNS], int rows, int columns )
- {
- int r, c, d, j, x_mem=x, y_mem=y;
- for(r=0;r<rows;r++){
- gotoxy(x++,y);
- putchar(179); // '|'
- for(c=0;c<columns;c++){
- gotoxy(x++,y);
- if( BM[r][c] == 1 )
- putchar(177); // 176, 177, 178, 219, 254
- else
- putchar(32); // blanko space
- }
- gotoxy(x++,y);
- putchar(179); // '|'
- x = x_mem; // new line
- y++;
- }
- } // print_Brik_Matrix()
- // Determine if the last row of the matrix BM contains bricks.
- // Returns 1 if last row of matrix BM contains bricks, otherwise returns 0
- int last_row_of_the_matrix_contains_bricks( int BM[MAX_ROWS][MAX_COLUMNS], int rows, int columns )
- {
- int c, flag_contain_brick=0;
- for(c=0;c<columns;c++){
- if( BM[rows-1][c] == 1 ) {
- flag_contain_brick = 1; // one brick was found
- return 1; // exit for loop and function
- }
- }
- return 0; // last row of the matrix does not contain bricks
- }
- // Scrolls the matrix with the bricks BM down one row.
- // Adds a new row to the top of the matrix.
- void scroll_Brik_Matrix( int x, int y,
- int BM[MAX_ROWS][MAX_COLUMNS], int rows, int columns,
- int distance )
- {
- int r, c, d, j, flag_contain_brick, x_mem=x, y_mem=y;
- // determine if the last row of the matrix contains bricks
- flag_contain_brick = last_row_of_the_matrix_contains_bricks( BM, rows, columns );
- // Lower the rows of the matrix by 1 row
- for(r=rows-1;r>0;r--){
- for(c=0;c<columns;c++){
- BM[r][c] = BM[r-1][c];
- }
- }
- // make new random first line on top of matrix BM[][]
- if( flag_contain_brick )
- make_Brik_Line( BM[0], rows, columns, get_random_integer_from_lower_to_uppper(1,columns-1) );
- else
- make_empty_line( BM[0], rows, columns );
- print_Brik_Matrix( x, y, BM, rows, columns );
- } // scroll_Brik_Matrix()
- // Make a BM matrix with bricks.
- // Leaves a distance between the rows of bricks
- void make_Brik_Matrix( int BM[MAX_ROWS][MAX_COLUMNS],
- int rows, int columns,
- int num_of_bricks, int distance )
- {
- int i=0, d;
- while( i<rows ){
- // distance empty lines
- for(d=0;d<distance;d++){
- make_empty_line( BM[i++], rows, columns );
- }
- // line with bricks
- make_Brik_Line( BM[i++], rows, columns, get_random_integer_from_lower_to_uppper(1,num_of_bricks) );
- }
- } // make_Brik_Matrix()
- // ----------FUNCTIONS TO MOVE CURSOR -----------------------------------------
- // not used
- void move_up( )
- {
- }
- // not used
- void move_down( )
- {
- }
- // Move cursor left. The coordinates of the cursor are xc,yc.
- void move_left( int *xc, int *yc, int x, int y )
- {
- if( *xc > 1 ){ // if there is room to go left
- delete_car( *xc, *yc, x, y ); // delete the old position of the car
- (*xc)--; // new xc coordinate of the car position
- print_car( *xc, *yc, x, y ); // print car in a new position
- }
- }
- // Move cursor right. The coordinates of the cursor are xc,yc.
- void move_right( int *xc, int *yc, int x, int y, int columns )
- {
- if( *xc < columns ){ // if there is room to go right
- delete_car( *xc, *yc, x, y ); // delete the old position of the car
- (*xc)++; // new xc coordinate of the car position
- print_car( *xc, *yc, x, y ); // print car in a new position
- }
- }
- // END OF----FUNCTIONS TO MOVE CURSOR -----------------------------------------
- // Prints statistics of results in place with coordinates x,y
- void print_scores( int x, int y,
- int number_of_lives,
- int number_of_passages_through_walls,
- int number_of_extra_lives,
- int number_of_lost_lives,
- int delay_time )
- {
- gotoxy(x,y-9);
- printf("speed = %5d ", 250-delay_time);
- gotoxy(x,y-7);
- printf("lost lives = %5d ", number_of_lost_lives);
- gotoxy(x,y-5);
- printf("extra lives = %5d ", number_of_extra_lives);
- gotoxy(x,y-3);
- printf("number of wals = %5d ", number_of_passages_through_walls);
- gotoxy(x,y-1);
- printf("number of lives = %5d ", number_of_lives);
- }
- // Prints help screen
- void print_help()
- {
- int x=1, y=2;
- // print title
- gotoxy(x+15,y+=2);
- printf("CAR RACE BRICK GAME");
- gotoxy(x,y+=5);
- printf("Use the left and right arrows to control the car.");
- gotoxy(x,y+=2);
- printf("Each wall passed brings 1 point.");
- gotoxy(x,y+=2);
- printf("In the beginning you have 3 lives.");
- gotoxy(x,y+=2);
- printf("You lose 1 life with every collision with the wall.");
- gotoxy(x,y+=2);
- printf("For every 10 points you get extra life.");
- gotoxy(x,y+=2);
- printf("The race starts slowly, at a speed of 50.");
- gotoxy(x,y+=2);
- printf("Every 25 points the speed increases by 10.");
- gotoxy(x,y+=2);
- printf("Press the space bar to pause.");
- gotoxy(x,y+=2);
- printf("Press the ESCAPE key to exit the game.");
- gotoxy(x,y+=3);
- printf("Good luck!");
- gotoxy(x+17,y+=4);
- printf("author Dragan Milicev");
- gotoxy(x+17,y+=2);
- printf("https://www.facebook.com/dmilicev");
- gotoxy(x,y+=5);
- printf("Press any key to start race ...");
- _getch(); // pause
- system("CLS");
- }
- // ----------KEYBOARD CONTROL--------------------------------------------------
- /*
- Keyboard control:
- UP up arrow
- DOWN down arrow
- LEFT left arrow
- RIGHT right arrow
- Key Space, SPACE (32) for pause.
- Key Escape, ESC (27) for quit.
- */
- int keyboard_control( int x, int y,
- int BM[MAX_ROWS][MAX_COLUMNS], int rows, int columns,
- int distance )
- {
- int xc, yc; // car coordinates
- int choice; // for pressed key
- int delay_time=200; // delay time for speed
- int number_of_lives=3;
- int number_of_passages_through_walls=0;
- int number_of_extra_lives=0;
- int number_of_lost_lives=0;
- int tens=10;
- int twenty_fives=25;
- xc = columns/2+1; // car coordinates
- yc = rows-1;
- // print title
- gotoxy(7,rows-27);
- printf("CAR RACE BRICK GAME");
- gotoxy(7,rows-23);
- printf("author Dragan Milicev");
- while( 1 ) { // an infinite loop that exits with choice Ecsape, ESC (27)
- while( !_kbhit() ){ // until a key is pressed
- wait(delay_time); // delay time for speed
- scroll_Brik_Matrix( x, y, BM, rows, columns, distance );
- // determine if the last row of the matrix contains bricks
- if( last_row_of_the_matrix_contains_bricks( BM, rows, columns ) )
- number_of_passages_through_walls++; // count number_of_passages_through_walls
- if( number_of_passages_through_walls == tens ){
- number_of_extra_lives++;
- number_of_lives++;
- tens += 10;
- }
- if( number_of_passages_through_walls == twenty_fives ){
- delay_time -= 10;
- twenty_fives += 25;
- }
- // collision calculation, if the car is in the same place where the brick is in the last row
- if( BM[rows-1][xc-1] == 1 ){
- gotoxy(x+xc,yc);
- putchar('X'); // replace car with X
- number_of_lives--;
- number_of_lost_lives++;
- print_scores( 6, rows,
- number_of_lives,
- number_of_passages_through_walls,
- number_of_extra_lives,
- number_of_lost_lives,
- delay_time );
- if ( number_of_lives == 0 )
- return( choice ); // end of game
- _getch(); // pause
- }
- else
- print_car(xc,yc,x,y);
- print_scores( 6, rows,
- number_of_lives,
- number_of_passages_through_walls,
- number_of_extra_lives,
- number_of_lost_lives,
- delay_time );
- } // while( !_kbhit() )
- choice = _getch(); // read the keyboard
- if( choice == 0 || choice == 224 ) // if is pressed function key with leading 0 or 224
- {
- choice = _getch(); // let's empty that 0 or 224
- if( choice == UP ) // if pressed up arrow
- {
- // not used
- }
- if( choice == DOWN ) // if pressed down arrow
- {
- // not used
- }
- if( choice == LEFT ) // if pressed left arrow
- {
- move_left( &xc, &yc, x, y );
- }
- if( choice == RIGHT ) // if pressed right arrow
- {
- move_right( &xc, &yc, x, y, columns );
- }
- } // end of: if is pressed function key with leading 0 or 224
- else // if pressed ordinary keys
- {
- if( choice == SPACE ) // if is pressed SPACE
- {
- _getch(); // pause the game
- }
- if( choice == ESC ) // if is pressed ESC
- {
- return( choice ); // end of game
- }
- } // end of: if pressed ordinary keys
- } // end of: while( 1 )
- return( choice ); // have to return something
- }
- // END OF----KEYBOARD CONTROL--------------------------------------------------
- int main(void)
- {
- int i, x=30, y=0, lines=6, columns=5, num_of_bricks=columns-1, distance=columns;
- int BM[MAX_ROWS][MAX_COLUMNS]; // matrix, BM stands for Brik Matrix
- time_t t; // for random number generator
- srand((unsigned) time(&t)); // Intializes random number generator, should only be called once.
- system("MODE CON: COLS=53 LINES=43"); // select MODE (size) of Console Window
- hidecursor();
- print_help();
- make_Brik_Matrix( BM, lines*distance+lines, columns, num_of_bricks, distance );
- print_Brik_Matrix( x, y, BM, lines*distance+lines, columns );
- keyboard_control( x, y, BM, lines*distance+lines, columns, distance );
- gotoxy(x-2,lines*distance+lines+1);
- printf(" GAME OVER \n");
- showcursor();
- return 0;
- } // main()
Add Comment
Please, Sign In to add comment