Bouncy Ball with Ncurses

So a while ago now I had an assignment in school to write a program for algorithm design. The basis of the program was to have an O go across the screen leaving a trail of Xs for each spot that it occupied. The original program I wrote was in MS Visual Studio using C++ .net functionality and was fairly fast but not that fast in terms of running speed. That was the one I submitted though as it was part of the requirements. But I couldn't leave it at that and went back and converted it over to be a straight unix program and used ncurses to draw. As it turned out the ncurses version was insanely faster than the C++ .net version even though the code wasn't a whole lot different. Major difference was the adding of the ncurses stuff. The other reason whey I wrote this was so that I could learn ncurses a bit before the Maze program was written as it was written with parts in assembly and such.
So this is the entry point of the program, I always have tried to make the entrypoint nice and tidy while doing all the work else where.

#include <iostream>
#include <ncurses.h>
#include "MainImp.h"
using namespace std;

int main() {
        MainImp MI;
        MI.initialstate();
        return 0;
}

This next part is the header for the MainImp class. Really the only thing here is I hard coded dimensions to make this easier for myself since it really isn't that big of a thing here. Most terminals when you first open them are 80x23 anyways, unless you specify it to be different, which this should still operate just might look a little funny.

#ifndef MAINIMP_H_
#define MAINIMP_H_

class MainImp
{
public:
        MainImp();
        virtual ~MainImp();
        void printcurrentstate();
        bool mainstate();
        void initialstate();
        void moveupperleft();
        void movelowerleft();
        void moveupperright();
        void movelowerright();
        void exitstate();
        bool askq();

private:
        int uniquespotcount;
        int startaddressx;
        int startaddressy;
        int currentaddressx;
        int currentaddressy;
        int currentdirection; //1-4 1=upperleft, 2=upperright, 3=lowerleft, 4=lowerright
        bool ballarena[23][80]; //Hard Coded Dimensions are bad but who cares right?
};



#endif /*MAINIMP_H_*/

When testing code or bits of code sometimes it is easier to hard code user variables to take the guess work out of the code as it is. Plus it makes prototyping or checking functionality with a specific part of the code easier. So here is the meat of the program so to speak where all the work is being done.

#include <ncurses.h>
#include "MainImp.h"


MainImp::MainImp()
{
        //Ncurses Init
        initscr();
        raw();
        keypad(stdscr, TRUE);
        noecho();
       
        //Main Variable Init
        int x,y;
                for(y=0;y<23;y++)
                {
                        for(x=0;x<80;x++)
                        {
                                ballarena[y][x] = false;
                        }
                }
                uniquespotcount =0;
                startaddressx = 0; //hard coded start points to test with or to act as defaults
                startaddressy = 0; //another hard coded start point
                currentaddressx = 0;
                currentaddressy = 0;
                currentdirection = 4; //hard coded direction to get started with
}

MainImp::~MainImp()
{
}

//Work out the very initial part of the board, position and such then start
//the main loop
void MainImp::initialstate(){
        currentaddressx = startaddressx;
                currentaddressy = startaddressy;
                ballarena[currentaddressy][currentaddressx] = true;
                uniquespotcount++;
                printcurrentstate();

                while(mainstate());
                exitstate();
}

//MainState loop, figure out where we are going based on the direction
//and check if we have been there before.
bool MainImp::mainstate(){
        switch(currentdirection)
                {
                        case 1:
                                moveupperleft();
                                break;
                        case 2:
                                moveupperright();
                                break;
                        case 3:
                                movelowerleft();
                                break;
                        case 4:
                                movelowerright();
                                break;
                }
                printcurrentstate();

                if((currentaddressx == startaddressx)&&(currentaddressy == startaddressy))
                        return false;
                else
                        return true;
}

//this needs to be rewritten for ncurses.
void MainImp::printcurrentstate(){
        int x,y;
        mvprintw(currentaddressy, currentaddressx, "O"); //print current loc as an O
       
        for(y=0;y<23;y++)
                {
                        for(x=0;x<80;x++)
                        {
                                if(ballarena[y][x])
                                        mvprintw(y,x,"X");
                                //else
                                        //mvprintw(y,x," ");
                        }
                }
        refresh(); //Draw the whole thing at once
}

//Direction = 1
void MainImp::moveupperleft(){
        int nextaddressx = currentaddressx-1;
                int nextaddressy = currentaddressy-1;

                if((nextaddressx < 0) && !(nextaddressy < 0))
                {
                        currentdirection = 2;
                        moveupperright();
                        return;
                }

                if((nextaddressx < 0) && (nextaddressy < 0))
                {
                        currentdirection = 4;
                        movelowerright();
                        return;
                }

                if (nextaddressy < 0)
                {
                        currentdirection = 3;
                        movelowerleft();
                        return;
                }

                if(!ballarena[nextaddressy][nextaddressx])
                        uniquespotcount++;

                currentaddressx = nextaddressx;
                currentaddressy = nextaddressy;
                ballarena[currentaddressy][currentaddressx] = true;
}

//Direction = 3
void MainImp::movelowerleft(){
        int nextaddressx = currentaddressx-1;
                int nextaddressy = currentaddressy+1;

                if((nextaddressx < 0) && (nextaddressy != 23))
                {
                        currentdirection = 4;
                        movelowerright();
                        return;
                }
               
                if((nextaddressx < 0) && (nextaddressy == 23))
                {
                        currentdirection = 2;
                        moveupperright();
                        return;
                }

                if(nextaddressy == 23)
                {
                        currentdirection = 1;
                        moveupperleft();
                        return;
                }

                if(!ballarena[nextaddressy][nextaddressx])
                        uniquespotcount++;

                currentaddressx = nextaddressx;
                currentaddressy = nextaddressy;
                ballarena[currentaddressy][currentaddressx] = true;
}

//Direction = 2
void MainImp::moveupperright(){
        int nextaddressx = currentaddressx+1;
                int nextaddressy = currentaddressy-1;

                if((nextaddressx == 80) && !(nextaddressy < 0))
                {
                        currentdirection = 1;
                        moveupperleft();
                        return;
                }
               
                if((nextaddressx == 80) && (nextaddressy < 0))
                {
                        currentdirection = 3;
                        movelowerleft();
                        return;
                }
               
                if (nextaddressy < 0)
                {
                        currentdirection = 4;
                        movelowerright();
                        return;
                }

                if(!ballarena[nextaddressy][nextaddressx])
                        uniquespotcount++;

                currentaddressx = nextaddressx;
                currentaddressy = nextaddressy;
                ballarena[currentaddressy][currentaddressx] = true;
}

void MainImp::movelowerright(){
        int nextaddressx = currentaddressx+1;
                int nextaddressy = currentaddressy+1;

                if((nextaddressx == 80) && (nextaddressy != 23))
                {
                        currentdirection = 3;
                        movelowerleft();
                        return;
                }
               
                if((nextaddressx == 80) && (nextaddressy == 23))
                {
                        currentdirection = 1;
                        moveupperleft();
                        return;
                }

                if (nextaddressy == 23)
                {
                        currentdirection = 2;
                        moveupperright();
                        return;
                }
                if(!ballarena[nextaddressy][nextaddressx])
                        uniquespotcount++;

                currentaddressx = nextaddressx;
                currentaddressy = nextaddressy;
                ballarena[currentaddressy][currentaddressx] = true;
}

//Ncurses needs to be Written
void MainImp::exitstate(){
       
}

Not too bad for drawing an O with a trail of Xs on the screen where ever the O goes. Except this ncurses version runs so fast you hardly see the O and the Xs just sort of appear. But it was fun either way and got to see how ncurses worked on a surface level. Took ncurses even farther though with Maze.