Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ///////////////////////////////////////////////////////////////////////////////
- // Grid Game
- ///////////////////////////////////////////////////////////////////////////////
- // Grid game board program that lets users move a cursor around on a board
- ///////////////////////////////////////////////////////////////////////////////
- // Small define for if project were in multiple files
- //#define USE_SEPARATE_FILES
- #ifndef USE_SEPARATE_FILES
- #include <stdio.h> // For I/O
- #include <stdlib.h> // For rand
- #include <time.h> // For seeding Rand
- #include <string> // For memset
- #endif
- // Need to include windows so that we can capture key presses properly
- #if defined _WIN32 || defined __CYGWIN__
- #include <windows.h>
- #endif
- #ifdef USE_SEPARATE_FILES
- #include "RenderContext.h"
- #include "I_Drawable.h"
- #include "GameBoard.h"
- #ifdef WIN32
- #include "CmdPromptHelper.h"
- #endif
- #else
- // RenderContext
- #ifndef USE_SEPARATE_FILES
- // Class that acts a canvas for things to draw to
- class RenderContext {
- private:
- int m_width, m_height; // Width and Height of this canvas
- char* m_renderBuffer; // Array to hold "pixels" of canvas
- char m_clearChar; // What to clear the array to
- public:
- // Empty Constructor
- RenderContext() : m_width(50), m_height(20), m_clearChar(' ') {
- m_renderBuffer = new char[m_width * m_height];
- }
- // Construct to specify width and height of canvas
- RenderContext(int width, int height) : m_width(width), m_height(height), m_clearChar(' ') {
- m_renderBuffer = new char[m_width * m_height];
- }
- // Destructor
- ~RenderContext() {
- if (m_renderBuffer) {
- delete m_renderBuffer;
- }
- }
- // Get a specific "pixel" on a canvas
- char getContentAt(int x, int y) {
- if (((0 <= x) && (x < m_width)) && ((0 <= y) && (y < m_height))) {
- return m_renderBuffer[(x + (y * m_width))];
- }
- }
- // Fill a specific "pixel" on the canvas
- void setContentAt(int x, int y, char val) {
- if (((0 <= x) && (x < m_width)) && ((0 <= y) && (y < m_height))) {
- m_renderBuffer[(x + (y * m_width))] = val;
- }
- }
- // Change what this canvas is flooded with when cleared
- void setClearChar(char clearChar) {
- m_clearChar = clearChar;
- }
- // Paint the canvas to the shell
- void render() {
- int row, column;
- for (row = 0; row < m_height; row++) {
- for (column = 0; column < m_width; column++) {
- printf("%c", getContentAt(column, row));
- }
- printf("\n");
- }
- }
- // Clear the canvas
- void clear() {
- memset(m_renderBuffer, m_clearChar, m_width * m_height);
- }
- };
- #endif
- // I_Drawable
- #ifndef USE_SEPARATE_FILES
- // Interface that allows objects to draw to the canvas
- class I_Drawable {
- public:
- // Virtual function that draws to the canvas
- virtual void draw(RenderContext&) = 0;
- };
- #endif
- // Marker
- #ifndef USE_SEPARATE_FILES
- // Class representing the cursor that selects objects on a game board
- class Marker : public I_Drawable {
- private:
- int m_xPos, m_yPos; // Position of cursor
- public:
- // Empty constructor
- Marker() : m_xPos(0), m_yPos(0) {
- }
- // Parameterized constructor allowing for setting of initial position
- Marker(int xPos, int yPos) : m_xPos(xPos), m_yPos(yPos) {
- }
- // Draw the cursor to the canvas
- void draw(RenderContext& renderTarget) {
- // Adjust marker by board spacing
- // (This is kind of a hack and should be changed)
- int tmpX, tmpY;
- tmpX = ((m_xPos * 5) + 1);
- tmpY = ((m_yPos * 3) + 1);
- // Set surrounding elements
- renderTarget.setContentAt(tmpX - 0, tmpY - 1, '-');
- renderTarget.setContentAt(tmpX - 1, tmpY - 0, '|');
- renderTarget.setContentAt(tmpX - 0, tmpY + 1, '-');
- renderTarget.setContentAt(tmpX + 1, tmpY - 0, '|');
- }
- // Get x position
- int getXPos() {
- return m_xPos;
- }
- // Get y position
- int getYPos() {
- return m_yPos;
- }
- // Set x position
- void setXPos(int xPos) {
- m_xPos = xPos;
- }
- // Set y position
- void setYPos(int yPos) {
- m_yPos = yPos;
- }
- };
- #endif
- // MoveDirection
- #ifndef USE_SEPARATE_FILES
- // Enumeration to hold directions a cursor can move
- typedef enum {
- MD_UP,
- MD_DOWN,
- MD_LEFT,
- MD_RIGHT
- } MoveDirection;
- #endif
- // GameBoard
- #ifndef USE_SEPARATE_FILES
- // Class to represent the board of a game being played
- class GameBoard : public I_Drawable {
- private:
- int m_width, m_height; // Width and height of the board
- int m_verticalSpacing, m_horizontalSpacing; // Spaces between each element on the board
- Marker m_marker; // The cursor that will draw on this board
- int* m_board; // Array of elements on this board
- // Set a value at a spot on this board
- // (There is no actual padding on the board, so do not include vertical/horizontal spacing)
- void setAtPos(int x, int y, int val) {
- if (((0 <= x) && (x < m_width)) && ((0 <= y) && (x < m_height))) {
- m_board[(x + (y * m_width))] = val;
- }
- }
- // Actually create the board
- void generateBoard() {
- int row, column, randomNumber, valToLeft, valToTop;
- // Iterate over all rows and columns
- for (row = 0; row < m_height; row++) {
- for (column = 0; column < m_width; column++) {
- // Get the previous elements
- valToLeft = getAtPos(column - 1, row);
- valToTop = getAtPos(column, row - 1);
- // Generate random numbers until we have one
- // that is not the same as an adjacent element
- do {
- randomNumber = (2 + (rand() % 7));
- } while ((valToLeft == randomNumber) || (valToTop == randomNumber));
- setAtPos(column, row, randomNumber);
- }
- }
- }
- public:
- // Empty Constructor
- GameBoard() : m_width(10), m_height(10), m_verticalSpacing(5), m_horizontalSpacing(3), m_marker(Marker()) {
- m_board = new int[m_width * m_height];
- generateBoard();
- }
- // Constructor that takes a width and height of a board
- GameBoard(int width, int height) : m_width(width), m_height(height), m_verticalSpacing(5), m_horizontalSpacing(3), m_marker(Marker()) {
- m_board = new int[m_width * m_height];
- generateBoard();
- }
- // Destructor
- ~GameBoard() {
- if (m_board) {
- delete m_board;
- }
- }
- // Function to get an element on the board
- // I would say overload operator() but it's often overkill
- // and can lead to hard to find bugs
- int getAtPos(int x, int y) {
- if (((0 <= x) && (x < m_width)) && ((0 <= y) && (x < m_height))) {
- return m_board[(x + (y * m_width))];
- }
- }
- // Function to draw to the canvas
- void draw(RenderContext& renderTarget) {
- int row, column;
- char buffer[8];
- // Iterate over every element
- for (row = 0; row < m_height; row++) {
- for (column = 0; column < m_width; column++) {
- // Convert the integer to a char
- sprintf(buffer, "%d", getAtPos(column, row));
- // Set the canvas "pixel" to the char at the
- // desired position including the padding
- renderTarget.setContentAt(
- ((column * m_verticalSpacing) + 1),
- ((row * m_horizontalSpacing) + 1),
- buffer[0]);
- }
- }
- // Draw the marker
- m_marker.draw(renderTarget);
- }
- // Function to move the cursor around depending on input
- // (Does not allow the cursor to move off of the board)
- void handleInput(MoveDirection moveDirection) {
- switch (moveDirection) {
- case MD_UP:
- if (m_marker.getYPos() > 0) {
- m_marker.setYPos(m_marker.getYPos() - 1);
- }
- break;
- case MD_DOWN:
- if (m_marker.getYPos() < m_height - 1) {
- m_marker.setYPos(m_marker.getYPos() + 1);
- }
- break;
- case MD_LEFT:
- if (m_marker.getXPos() > 0) {
- m_marker.setXPos(m_marker.getXPos() - 1);
- }
- break;
- case MD_RIGHT:
- if (m_marker.getXPos() < m_width - 1) {
- m_marker.setXPos(m_marker.getXPos() + 1);
- }
- break;
- }
- }
- // Get the width of the board
- int getWidth() {
- return m_width;
- }
- // Get the height of the board
- int getHeight() {
- return m_height;
- }
- };
- #endif
- // CmdPromptHelper
- #ifndef USE_SEPARATE_FILES
- // This class is only useful if we are building on windows
- #ifdef WIN32
- // Class to help with drawing on the windows command prompt
- class CmdPromptHelper {
- private:
- DWORD inMode; // Attributes of std::in before we change them
- DWORD outMode; // Attributes of std::out before we change them
- HANDLE hstdin; // Handle to std::in
- HANDLE hstdout; // Handle to std::out
- public:
- // Empty constructor
- CmdPromptHelper() {
- // Get a handle to input of prompt
- hstdin = GetStdHandle(STD_INPUT_HANDLE);
- if ((hstdin == INVALID_HANDLE_VALUE)
- || !GetConsoleMode(hstdin, &inMode)
- || !SetConsoleMode(hstdin, 0)) {
- return;
- }
- // Get handle for output of prompt
- hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
- if ((hstdout == INVALID_HANDLE_VALUE)
- || !GetConsoleMode(hstdout, &outMode)) {
- return;
- }
- }
- // Revert the console
- void reset() {
- SetConsoleMode(hstdin, inMode);
- }
- // See what key is pressed by the user and return it
- WORD getKeyPress() {
- if (hstdin != INVALID_HANDLE_VALUE) {
- DWORD count;
- INPUT_RECORD inrec;
- // Get Key Press
- ReadConsoleInput(hstdin, &inrec, 1, &count);
- // Return key only if it is key down
- if (inrec.Event.KeyEvent.bKeyDown) {
- return inrec.Event.KeyEvent.wVirtualKeyCode;
- }
- else{
- return 0;
- }
- // Flush input
- FlushConsoleInputBuffer(hstdin);
- } else {
- return 0;
- }
- }
- // Flood the console with empty space so that we can
- // simulate single buffering (I have no idea how to double buffer this)
- void clearScreen() {
- if (hstdout != INVALID_HANDLE_VALUE) {
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- DWORD cellCount; // How many cells to paint
- DWORD count; // How many we painted
- COORD homeCoord = {0, 0}; // Where to put the cursor when we're done
- // Get console info
- if (!GetConsoleScreenBufferInfo(hstdout, &csbi)) {
- return;
- }
- // Get cell count
- cellCount = csbi.dwSize.X * csbi.dwSize.Y;
- // Fill the screen with spaces
- FillConsoleOutputCharacter(
- hstdout,
- (TCHAR) ' ',
- cellCount,
- homeCoord,
- &count
- );
- // Set cursor position
- SetConsoleCursorPosition(hstdout, homeCoord);
- }
- }
- };
- #endif
- #endif
- #endif
- // Entry point of program
- int main() {
- // Create a game board
- GameBoard gb(5, 5);
- // Create something to render to
- RenderContext rc(25, 15);
- rc.setClearChar('.');
- rc.clear();
- // If on windows, we can animate
- #ifdef WIN32
- // Make a helper
- CmdPromptHelper cph;
- // Variable to hold key presses
- WORD key;
- // Play Game
- do {
- // Draw the board to the render object
- gb.draw(rc);
- // Draw the render object
- rc.render();
- // Get Key Press
- key = cph.getKeyPress();
- // Handle the key press
- switch (key) {
- case VK_UP:
- gb.handleInput(MD_UP);
- break;
- case VK_DOWN:
- gb.handleInput(MD_DOWN);
- break;
- case VK_LEFT:
- gb.handleInput(MD_LEFT);
- break;
- case VK_RIGHT:
- gb.handleInput(MD_RIGHT);
- break;
- }
- // Clear Screen
- rc.clear();
- cph.clearScreen();
- } while (key != VK_ESCAPE);
- // Reset console
- cph.reset();
- // If we aren't on windows, we can't animate and have
- // to write OS specific code to handle key presses
- #else
- // Variable to hold key presses
- char key;
- // Play Game
- do {
- // Draw the board to the render object
- gb.draw(rc);
- // Draw the render object
- rc.render();
- // Get Key Press
- key = getchar();
- } while (key != 0);
- #endif
- }
- // EoF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement