Search code examples
c++user-controls

How to make movable character in maze with C++


So I have my maze printed out once the user presses 1 in order to launch the map and other variables. I have declared the player as a smiley face or set equal to 1. However, I would like to make this character movable throughout the maze but am having trouble doing so. I have created a player move as a space in order for it to move without overwriting other code. I was thinking of using a switch statement and detecting user input and then changing the X and Y positions based on that but I dont know how to put it in my mapCreation function. I was also wondering if you guys could help me generate the variables such as treasures at random locations throughout the map and if it is a wall or '|' then dont print. My treasures spawn but at the same location. Any input on any of my questions would really help! Thank you!

** Ignore the cases as they were just being used previously but now I dont have a use for them.

**UPDATE If anyone has a link somewhere that would help that would also be helpful! Thank you!

// Header Files
#include <cstdlib>
#include <iostream>
#include <windows.h>


using namespace std; 

HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE); // For use of SetConsoleTextAttribute()


#define LEVEL_COUNT (2)
const char* maze[LEVEL_COUNT][12] = 
{
        {
            "||||||||||||\n",
            "|       |  |\n",
            "|       |  |\n",
            "|    ||||  |",
            "|          |",
            "|          |",
            "||||||     |",
            "| |        |",
            "| |    |   |",
            "|      |   |",
            "|      |   |",
            "||||||||||||",
        },
       {
            "||||||||||||",
            "|       |  |",
            "|   |||||  |",
            "|       |  |",
            "|          |",
            "|       ||||",
            "|          |",
            "|   |      |",
            "|   |      |",
            "|||||||    |",
            "|          |",
            "||||||||||||",
        }, 
};

// Function Prototypes

void titleScreen(); // Prints Title and instructions

void mapCreation( char arr[][12], int level);

void drawMap(char arr[][12]);

bool update(char arr[][12], int &level, int &lives, int &score);

void loadMap( char arr[][12], int level);

// Player Struct
struct Player{
    int x;
    int y;
    char move;
};



// Main Program
int main ()
    {
    // initialize variables
    int option;
    char baseMap[12][12];
    int level = 1;
    int lives = 3;
    int score = 0;
    bool gameOver = false;
    bool levelCompleted = false;


    SetConsoleTextAttribute(console, 240); // change background to white

    system("CLS");// clears screen in order to remove black background

    titleScreen(); // Display Title

    do // do-while loop starts
    {

    cin >> option; // take in input

        if(option == 1) // temporary option to check for next screen
            {
            //Display Maze

            system("CLS");// clears screen in order to remove black background

                 mapCreation( baseMap, 1 ); // Create map, this one is map 1

                 drawMap(baseMap); // iterate throup the map and print it out
                    //   update(baseMap, level, lives, score);



             }
          if(option == 2)
            {
            //Display Maze

            system("CLS");// clears screen in order to remove black background

                 mapCreation( baseMap, 2 ); // Create map, this one is map 1

                 drawMap(baseMap); // iterate throup the map and print it out
                    //   update(baseMap, level, lives, score);
             }

        }
    while( option !=1); // condition of do-while loop

    system("pause"); // Pause for user, only temporary

    return 0;

}








void titleScreen(){

    cout << " Welcome to Treasure Hunter!\n\n";
    cout << "In order to beat this game you must find the treasure\n";
    cout << " that is located in the maze. You can move using the \n";
    cout << " arrow keys or WASD.\n\n";
    cout << " Warning! There are traps that will take life away as\n";
    cout << " well as add life! However, they are hidden so be careful!\n ";
    cout << " Goodluck and have fun!\n\n\n\n";
    cout << " Press Ctrl+C to quit\n";


}


void mapCreation( char arr[12][12], int level )
    {
      int traps = 0;   
      int lives = 0;
      int treasure = 0;
      int x ;
      int y ;
        for(int i = 0; i < 12; i++)
            {
             for(int j = 0; j < 12; j++)
                {
                 arr[i][j] = 0;
                }

            }

        // load the map:
        loadMap(arr,level);

        switch (level)
        {
        case 1:




        break;

        case 2: // Level 2 Map

        break;
        }
    }

void drawMap(char arr[12][12])
    {
        // Declare variables to be prtined out
      Player player;
      player.x = 1;
      player.y = 1;
      player.move = ' ';
      int traps = 0;   
      int lives = 0;
      int treasure = 0;
      // Lives,Traps, and Treasure x and y positions
      int Trap_Y,Trap_X,Lives_X,Lives_Y,Traps_X,Traps_Y; 
      // Randomly place variables
      Trap_X = (rand() % 10);
      Trap_Y = (rand() % 10);  
      Lives_X = (rand() % 12);
      Lives_Y = (rand() % 12);
      Traps_X = (rand() % 12);
      Traps_Y = (rand() % 12);    

     for(int i = 0; i < 12; i++)
        {
        cout << endl; // print out new line
         for(int j = 0; j < 12; j++ )
            {
                if(player.x == i && player.y == j)
                arr[player.x][player.y] = 1;                        




                // If variables are  not equal to a wall character print it out
                 if(arr[Trap_X][Trap_Y] != '|' )                         
                arr[Trap_X][Trap_Y] = 4; // treasure is 4
                treasure++;
                if(arr[Lives_X][Lives_Y] != '|')// traps are 2
                 arr[Lives_X][Lives_Y]= 2; 
                 traps++;
                if(arr[Traps_X][Traps_Y] != '|') // lives are 3
                 arr[Traps_X][Traps_Y]= 3;
                 lives++;


                cout << arr[i][j];

            }
        }
        cout << endl;
    }

/*bool update(char arr[][12], int &level, int &lives, int &score)
    {
     bool levelCompleted = false;
     bool gameOver = false;
    }
*/


void loadMap( char arr[][12], int level)
{
     if((level < 0) || (level >= LEVEL_COUNT))
         return;

     for(int i = 0; i < 12; i++)
     {
         const char* row = maze[level][i];
         for(int j = 0; j < 12; j++)
         {
             if(row[j] == 0)
                 break; // end of string
             if(row[j] == ' ')
                 arr[i][j] = 0;  // set spaces to zero
             else
                 arr[i][j] = row[j];
         }
     }
}

Solution

  • On windows, You can use ReadConsoleInput() to navigate with a keyboard in a windows console. This solution checks for collision using the statement if (maze[player.y][player.x-1]==0) . 0 means no wall, 1 means wall has been hit.

    Here's an example of the usage of ReadConsoleInput().

    enter image description here

    #include <stdio.h>
    #include <windows.h>
    #include <iostream>
    using namespace std;
    
    #define VK_W 0x57
    #define VK_S 0x53
    #define VK_A 0x41
    #define VK_D 0x44
    
    
    struct t_player{ int x,y;};
    t_player player;
    char playersymbol=219;
    char mazewall=0;
    int mazex=31,mazey=8;
    
    int maze[16][24] =
    {{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
     { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
     { 1,0,1,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
     { 1,0,0,0,0,1,0,0,0,1,0,1,1,1,1,0,0,1,0,0,0,0,0,1},
     { 1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,0,1},
     { 1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,0,1},
     { 1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1},
     { 1,0,1,1,1,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
     { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
     { 1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1,0,0,0,0,1},
     { 1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
     { 1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1},
     { 1,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,1,0,0,0,0,0,0,1},
     { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1},
     { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
     { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
    };
    
    
    void clrscr();
    void gotoxy(int x, int y);
    void setcolor(WORD color);
    void textColor(unsigned char fColor,unsigned char bColor);
    void moveleft();
    void moveright();
    void moveup();
    void movedown();
    void drawmaze(int px,int py);
    void putmenu();
    void putplayer();
    
    int main()
    {
        DWORD        mode;          /* Preserved console mode */
        INPUT_RECORD event;         /* Input event */
        BOOL         EXITGAME = FALSE;  /* Program termination flag */
        unsigned int counter = 0;   /* The number of times 'Esc' is pressed */
    
    
        /* Get the console input handle */
        HANDLE hstdin = GetStdHandle( STD_INPUT_HANDLE );
    
        /* Preserve the original console mode */
        GetConsoleMode( hstdin, &mode );
    
        /* Set to no line-buffering, no echo, no special-key-processing */
        SetConsoleMode( hstdin, 0 );
    
    
        player.x=20;
        player.y=13;
    
        clrscr();
        setcolor(15);
    
    
        while (!EXITGAME)
        {
            if (WaitForSingleObject( hstdin, 0 ) == WAIT_OBJECT_0)  /* if kbhit */
            {
                DWORD count;  /* ignored */
    
                /* Get the input event */
                ReadConsoleInput( hstdin, &event, 1, &count );
    
                /* Only respond to key release events */
                if ((event.EventType == KEY_EVENT)
                &&  !event.Event.KeyEvent.bKeyDown)
    
                clrscr();
                putmenu();
                Sleep(100);
    
    
                    switch (event.Event.KeyEvent.wVirtualKeyCode)
                    {
                        case VK_ESCAPE:
                           EXITGAME = TRUE;
                         break;
    
                        case VK_LEFT:
                            // left key   move player left
                             moveleft();
                         break;
    
                        case VK_RIGHT:
                            // right key   move player right
                            moveright();
    
                         break;    
    
                        case VK_UP:
                            // up key   move player up
                            moveup();
    
                         break;
    
                        case VK_DOWN:
                            // down key   move player down
                             movedown();
    
                         break; 
    
                        case VK_A:
                            // left key   move player left
                            moveleft();
    
                         break; 
    
                        case VK_D:
                            // right key   move player right
    
                            moveright();
                         break; 
    
                        case VK_W:
                            // up key   move player up
    
                            moveup();
                         break; 
    
                        case VK_S:
                            // down key   move player down
                            movedown();
                         break; 
    
    
                    }//switch
    
                    putplayer();
    
    
            }
        }
    
        gotoxy(1,23);cout<<"  ";  
        SetConsoleMode( hstdin, mode );
        return 0;
    }
    
    void putplayer()
    {
        setcolor(9);
        gotoxy( player.x +mazex,    player.y  +mazey); 
        cout<<playersymbol;
        setcolor(7);
    
    }
    
    
    void putmenu()
    {
        gotoxy(1,1);cout<<"keyboard navigator ";
    
        setcolor(14);
        gotoxy(31,1);cout<<"Use keys W,S, A,D, Left,Right,Up,Down ";
    
        setcolor(7);
    
        gotoxy(31,2);cout<<"W or up key = move player up ";
        gotoxy(31,3);cout<<"S or down key = move player down ";
        gotoxy(31,4);cout<<"A or left key = move player left ";
        gotoxy(31,5);cout<<"D or right key = move player right ";
    
        setcolor(11);
    
        drawmaze(mazex,mazey);
        setcolor(7);
    
    }
    
    
    void drawmaze(int px,int py)
    {
        for(int y =0; y<16;y++)
        {
            for(int x=0; x<24; x++)
            {
               if (maze[y][x]==1) mazewall=219;
               else mazewall=32;
    
               gotoxy(x+px,y+py);
               cout<< mazewall;
            }
    
        }
    
    }
    
    void moveleft()
    {
        gotoxy(31,7); 
        cout<<"left key   move player left    \n\n";
         if (maze[player.y][player.x-1]==0)   player.x = player.x -1;
    }
    
    void moveright()
    {
        gotoxy(31,7); 
        cout<<"right key   move player right   \n\n";
         if (maze[player.y][player.x+1]==0)   player.x = player.x +1;
    }
    
    void moveup()
    {
        gotoxy(31,7); 
        cout<<"up key   move player up      \n\n";
         if (maze[player.y-1][player.x]==0)   player.y = player.y -1;
    }
    
    void movedown()
    {
        gotoxy(31,7); 
        cout<<"down key   move player down   \n\n";
         if (maze[player.y+1][player.x]==0)   player.y = player.y +1;
    
    }
    
    
    
    void gotoxy(int x, int y)
    {
        COORD coord;
        coord.X = x; coord.Y = y;
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
        return;
    }
    
    void setcolor(WORD color)
    {
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color);
        return;
    }
    
    
    
    
    void setForeGroundAndBackGroundColor(int ForeGroundColor,int BackGroundColor)
    {
       int color=16*BackGroundColor+ForeGroundColor;
       setcolor(color);
    }
    
    
    
    void clrscr()
    {
        COORD coordScreen = { 0, 0 };
        DWORD cCharsWritten;
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        DWORD dwConSize;
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    
        GetConsoleScreenBufferInfo(hConsole, &csbi);
        dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
        FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
        GetConsoleScreenBufferInfo(hConsole, &csbi);
        FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
        SetConsoleCursorPosition(hConsole, coordScreen);
        return;
    }