Introduction to Programming

Avoid!


Filename: avoid.c
Compile: gcc avoid.c -o avoid -l curses
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <curses.h>
#include <string.h>

// This function causes some small amount of time to go by.
void delay(int n)
{
    int i;
    int j;

    for (j=0; j<n; j++)
    {
        for (i=0; i<100000; i++)
        {
        }
    }
}

// Center the given string on the screen.
void center(int line, char *fmt, ...)
{
    va_list argv;
    char str[128];
    int pos;

    va_start(argv, fmt);
    vsprintf(str, fmt, argv);
    va_end(argv);

    pos = 30 - strlen(str)/2;
    move(line, pos);
    addstr(str);
}

// Make an animated explosion.
void go_boom(int x, int y)
{
    color_set(3, NULL);
    move (y, x);
    addstr("@");
    move (21, 0);
    refresh();
    delay(50);
    move (y-1, x);
    addstr("^");
    move (y, x-1);
    addstr("<@>");
    move (y+1, x);
    addstr("v");
    move (21, 0);
    refresh();
    delay(50);
    move (y-2, x);
    addstr("^");
    move (y-1, x-1);
    addstr("\\|/");
    move (y, x-2);
    addstr("<-@->");
    move (y+1, x-1);
    addstr("/|\\");
    move (y+2, x);
    addstr("v");
    move (21, 0);
    refresh();
    delay(500);
}

// This is the main program. This is where it all starts!
int main(int argc, char *argv[]) 
{ 
    float x, y, dx, dy, oldx, oldy; 
    char ch = 0;
    int die, i, n_obs, obs_x[100], obs_y[100];
    int level = 1, lives = 5;

    // Initialize curses
    initscr();
    start_color();
    init_pair(1, 2, 0);
    init_pair(2, 3, 0);
    init_pair(3, 1, 0);
    cbreak();
    noecho();
    nonl();
    intrflush(stdscr, FALSE);
    keypad(stdscr, TRUE);
    nodelay(stdscr, TRUE);

    // Random seed.
    srand(time(NULL)); 

    // Intro screen!
    color_set(3, NULL);
    center(3, "____________________________________");
    color_set(1, NULL);
    center(5, "Welcome to AVOID!");
    color_set(3, NULL);
    center(6, "by MAK");
    color_set(2, NULL);
    center(8, "Press a to go up and z to go down...");
    color_set(1, NULL);
    center(10, "Press any key to begin!");
    color_set(3, NULL);
    center(11, "____________________________________");
    move(21, 0); 
    refresh();
    ch = -1;
    while (ch < 0)
        ch = getch();

    while (ch != 'q' && lives > 0 && level <= 10)
    {
        clear();

        // Level screen
        color_set(3, NULL);
        center(3, "______________________________");
        color_set(1, NULL);
        center(5, "Level %d", level);
        color_set(2, NULL);
        if (lives == 1)
            center(8, "This is your last life!");
        else
            center(8, "You have %d lives remaining!", lives);
        color_set(3, NULL);
        center(9, "______________________________");
        move(21, 0); 
        refresh();
        delay(1000);
        clear();

        // Starting values.
        x = 0; 
        y = 10; 
        dx = 0.01; 
        dy = 0; 
        oldx = 10; 
        oldy = 10;
        die = 0;

        // Randomly place obsticles on the screen.
        n_obs = level * 10;
        for (i=0; i<n_obs; i++)
        {
            obs_x[i] = rand() % 50 + 10;
            obs_y[i] = rand() % 20;
            move(obs_y[i], obs_x[i]);
            color_set(1, NULL);
            addch('#');
        }

        // As long as the user doesn't quit, keep the loop going...
        while (x < 60 && ch != 'q' && !die) 
        { 
            // Draw over the old star.
            move((int) oldy, (int) oldx); 
            addch(' '); 
            // Draw the new star.
            move((int) y, (int) x); 
            color_set(2, NULL);
            addch('*'); 

            // Move the curser back to the bottom, refresh, and wait.
            // (If we don't wait, stuff will move *way* too fast!)
            move(21, 0); 
            refresh();
            delay(1);

            // Bounce off the top and bottom of the screen.
            if (dy < 0 && y <= 0)
                dy = -dy;
            if (dy > 0 && y >= 20)
                dy = -dy;

            // Update x and y and their old values.
            oldx = x; 
            oldy = y; 
            x += dx; 
            y += dy; 

            // See if the user has a command.
            ch = getch();

            // a goes up, z goes down.
            if (ch == 'a')
                dy = -0.005;
            if (ch == 'z')
                dy = 0.005;

            // Check for a collision with *all* the obsticles!
            for (i=0; i<n_obs; i++)
            {
                if (x >= obs_x[i] && x < obs_x[i]+1 &&
                    y >= obs_y[i] && y < obs_y[i]+1)
                {
                    go_boom(x, y);
                    die=1;
                }
            }
        }

        // If you made it to the end, the level goes up.
        if (x >= 60)
            level++;
        // If you died, your lives go down.
        if (die)
            lives--;
    }

    // Clear the screen and shut down curses.
    clear();
    endwin();

    // If you ran out of lives, game over.
    if (lives == 0)
        printf("Sorry, you died!\n");
    // If you quit, say goodbye.
    else if (ch=='q')
        printf("Thanks for playing!\n");
    // Otherwise, you must have won!
    else
        printf("You made it!!\n");

    // End of program.
    return 0; 
}

Next: The MAK Library

Previous: Speed Letters


Introduction to Programming

Home