Klasa Runner — pierwsza, koślawa implementacja

Pierwsza, trywialna implementacja klasy Runner. Bez hermetyzacji, konstruktora, rozmiary ekranu zaszyte w kodzie w postaci literałów całkowitoliczbowych. Program stanowi uzupełnienie wykładu z programowania w językach C/C++. Koncepcja klasy Runner została omówiona we wprowadzeniu do programowania obiektowego (pdf).

Do pobrania wersja źródłowa pliku (main01.cpp).

Uwaga! Implementacja tylko dla Windows, obsługa konsoli realizowana za pośrednictwem WinApi. Najlepiej kompilować używając MinGW (środowiska Code::Blocka, DevC++) lub kompilatorów w środowisku C++ Builder. Proszę unikać środowisk VisualC++, CLion, QT, będą stwarzać problemy.

// Runner, wersja 01

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <conio.h>

#if defined(__MINGW32__) || defined(_MSC_VER)
#include <windows.h>
#endif

// Kody klawiszy sterujących kursorem i klawiszy specjalnych
enum KEY_CODES
{
#ifdef __BORLANDC__
	KEY_BLANK = 0x0000,
#elif (defined(__GNUC__) && defined(__MINGW32__)) || defined(_MSC_VER)
	KEY_BLANK = 0x00e0,
#endif
	KEY_UP = 0x4800,
	KEY_DOWN = 0x5000,
	KEY_LEFT = 0x4b00,
	KEY_RIGHT = 0x4d00,
	KEY_ESC = 0x001b
};

// Prototypy funkcji obsługi konsoli
int getKey();
void clearScreen();
void writeCharXY(int x, int y, char c);
void writeStrXY(int x, int y, char s[]);
void writeIntXY(int x, int y, int i);
void writeDoubleXY(int x, int y, double d);
void cursorOff();
void cursorOn();

class Runner
{
  public :
    int  x, y;
    char shape;

    void show();
    void hide();

    void moveUp();
    void moveDown();
    void moveLeft();
    void moveRight();
};

void Runner::show()
{
  writeCharXY( x, y, shape );
}

void Runner::hide()
{
  writeCharXY( x, y, ' ' );
}

void Runner::moveUp()
{
  hide();
  if( y > 1 )
    --y;
  show();
}

void Runner::moveDown()
{
  hide();
  if( y < 24 )
    ++y;
  show();
}

void Runner::moveLeft()
{
  hide();
  if( x > 1 )
    --x;
  show();
}

void Runner::moveRight()
{
  hide();
  if( x < 80 )
    ++x;
  show();
}

int main()
{
  int  key;
  Runner R;

  R.x = 40;
  R.y = 12;
  R.shape = '*';

  clearScreen();
  cursorOff();
  R.show();

  do
  {
    key = getKey();
    switch( key )
    {
      case KEY_UP    : R.moveUp();
                       break;
      case KEY_DOWN  : R.moveDown();
                       break;
      case KEY_LEFT  : R.moveLeft();
                       break;
      case KEY_RIGHT : R.moveRight();
                     break;
    }//switch
  }
  while( key != KEY_ESC );

  clearScreen();
  cursorOn();

  return EXIT_SUCCESS;
}

// Funkcje obsługi konsoli, sprawa techniczna, w sensie merytorycznym nieistotna
int getKey()
{
	int key = _getch();
	return (key == KEY_BLANK) ? _getch() << 8 : key;
}

void clearScreen()
{
#ifdef __BORLANDC__
	clrscr();
#elif (defined(__GNUC__) && defined(__MINGW32__)) || defined(_MSC_VER)
	COORD leftTop = { 0, 0 };
	CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
	int numOfCells = 80 * 25;
	DWORD writtenItems;
	HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
	if (GetConsoleScreenBufferInfo(consoleHandle, &consoleInfo))
		numOfCells = consoleInfo.dwSize.X * consoleInfo.dwSize.Y;

	FillConsoleOutputAttribute(consoleHandle, 0xf,
		numOfCells, leftTop, &writtenItems);
	FillConsoleOutputCharacter(consoleHandle, ' ',
		numOfCells, leftTop, &writtenItems);
#else
#error "Nieobslugiwana platforma"
#endif
}

void writeCharXY(int x, int y, char c) {
#ifdef __BORLANDC__
	gotoxy(x, y);
	putch(c);
#elif (defined(__GNUC__) && defined(__MINGW32__)) || defined(_MSC_VER)
	COORD cursorPos;
	DWORD written;

	cursorPos.X = x - 1;
	cursorPos.Y = y - 1;

	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cursorPos);
	WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), &c, 1, &written, 0);
#else
#error "Nieobslugiwana platforma"
#endif
}

void writeStrXY(int x, int y, char s[])
{
#ifdef __BORLANDC__
	gotoxy(x, y);
	cputs(s);
#elif (defined(__GNUC__) && defined(__MINGW32__)) || defined(_MSC_VER)
	COORD cursorPos;
	DWORD written;

	cursorPos.X = x - 1;
	cursorPos.Y = y - 1;

	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cursorPos);
	WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), s, strlen(s), &written, 0);
#else
#error "Nieobslugiwana platforma"
#endif
}

void writeIntXY(int x, int y, int i)
{
	char s[80];
#if defined(_MSC_VER)
	sprintf_s(s, 80, "%d", i);
#else
	sprintf(s, "%d", i);
#endif
	writeStrXY(x, y, s);
}

void writeDoubleXY(int x, int y, double d)
{
	char s[80];
#if defined(_MSC_VER)
	sprintf_s(s, 80, "%g", d);
#else
	sprintf(s, "%g", d);
#endif
	writeStrXY(x, y, s);
}

void cursorOff()
{
#ifdef __BORLANDC__
	_setcursortype(_NOCURSOR);
#elif (defined(__GNUC__) && defined(__MINGW32__)) || defined(_MSC_VER)
	CONSOLE_CURSOR_INFO cursorInfo;
	HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
	GetConsoleCursorInfo(consoleHandle, &cursorInfo);
	cursorInfo.bVisible = false;
	SetConsoleCursorInfo(consoleHandle, &cursorInfo);
#else
#error "Nieobslugiwana platforma"
#endif
}

void cursorOn()
{
#ifdef __BORLANDC__
	_setcursortype(_NORMALCURSOR);
#elif (defined(__GNUC__) && defined(__MINGW32__)) || defined(_MSC_VER)
	CONSOLE_CURSOR_INFO cursorInfo;
	HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
	GetConsoleCursorInfo(consoleHandle, &cursorInfo);
	cursorInfo.bVisible = true;
	SetConsoleCursorInfo(consoleHandle, &cursorInfo);
#else
#error "Nieobslugiwana platforma"
#endif
}