C++ Maze program, like a mud

I just finished my first c++ class and not taking another this semester but still want to keep tinkering around with it. My wife and I play a mud and she thought it would be cool to make a maze game sorta like a mud, but with just one player for now. I was just wondering if there was an easier way that a bunch of if/else statements. Would like to have about 100 rooms for the maze. She also took a class and mentioned possibly using an array but not sure if that would work. I'll try the if/else over the next week or so when I have time an submit the code I will have up to that point. Thanks in advance for any info you provide.
Hello! I am doing a similar thing right now. How I have done it is that it loads the map in from a custom file structure into an array, after which the program calculates and tell the user what is happening/what they can do (by using a switch statement to figure out what to do based on what is at the position of the player). For example, if they are in a space represented by the number one in the array, the computer works out which directions (north, east, south, west) the player can move (to an adjacent tile not marked with '0' (as this is a tile that can not be stepped on)) and prints to the screen something like "You can move: north, east and south." If you are going to use an array, and are loading the map from a file, do make sure that it is dynamically allocated array or a vector. It is also possible to save individual saves for different people (it takes in their name at the beginning and saves as this). Once I have finished (in about 2-4 days, though can't be definite), shall I upload the code for you?

Oh yes... as you mention that you have only took one class, I am assuming that you haven't covered many topics. This is a good website: http://thenewboston.org/list.php?cat=16
It unfortunately doesn't cover dynamically allocated arrays or vectors, but make sure to study one of them (if you haven't already, unless you know the exact dimensions of each map).

Good luck and have fun!
Last edited on
@ Exispistis- Hmm, I know a little about arrays but we really didn't get too much into them. That's the next block of the section next semester I can take it. But yea seems like you are doing the same thing almost. We really didn't get into using custom files or anything like that, but I'll watch all those videos on thenewboston.com so thanks for the link. And we didn't cover dynamically allocated arrays or vectors yet but I'll try to find some info on the internet.

Thanks and good luck to you too!

@ retardedwhale- right now I've been working on console window.
Ok, just read this post http://cplusplus.com/forum/articles/28558/ about SFML and how the console is not really intended to do what I want it to do. So I think I'm going adapt to my needs and switch away from the console app and try to work with SFML to create my maze game. After install and messing around with it for a couple of days I'll come back with some more questions once I finish other half of Buckys videos and the tutorials on the SFML site if I do need anymore help. Which I probably will with the rooms I want to make. But, till then thanks.
Heres a program i made thats a simple tactical console game using 2d arrays and map files. you can take apart this code and use some functions from it.

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <cstdlib>
#include <string>
#include <fstream>
#include <windows.h>
#include "Map.h"
#include "Player.h"
#include "concol.h"
bool Game = true;
bool pOneTurn = true;
bool pTwoTurn = false;
int main()
{

    Map mObj(2);
    mObj.createmap();
    mObj.SSP();
    mObj.RefreshScreen();
    while(Game){ //while the game is running
        while(pOneTurn){ //player ones turn
            int moves = 0;
            while(moves <3){
                setcolor(red,backcolor());
                std::cout  << "PLAYER ONE w(UP) s(DOWN) a(LEFT) d(RIGHT) g(SHOOT)"; //display controls and stats
                std::cout  << "\n --- MOVES LEFT --- " << 3 - moves << std::endl;
                setcolor(white,backcolor());
                mObj.InputChoice(1); //run input function to see where to move
                mObj.RefreshScreen(); //rewrite the array
                moves++;
            }
            mObj.RefreshScreen();
            pTwoTurn = true; //set player twos turn to true
            pOneTurn = false; //set player ones turn to false
        }
        while(pTwoTurn){
            int moves=0;
            while(moves < 3){
                setcolor(green,backcolor());
                std::cout << "PLAYER TWO w(UP) s(DOWN) a(LEFT) d(RIGHT) g(SHOOT)";
                std::cout << "\n --- MOVES LEFT --- " << 3-moves << std::endl;
                setcolor(yellow,backcolor());
                mObj.InputChoice(2);
                setcolor(white,backcolor());
                mObj.RefreshScreen();
                moves++;
            }
            mObj.RefreshScreen();
            pOneTurn = true;
            pTwoTurn = false;
        }
    }
}


Player.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef PLAYER_H
#define PLAYER_H
#include "Map.h"
#include <iostream>
class Map;
class Player //not much in this class, work in progress
{
    public:
        int getx(){return xp;};
        int gety(){return yp;};
        inline void delay( unsigned long ms );
        Player(int x, int y); //takes the players coords as parameters
        void InputChoice(Map& screen,char c,char map[][20], char bgmap[][20], int pN); //uses the current map to move across
        void SetStartPos(char c,char map[][20]); //set positions at the start so they are visible
        void FireG(int pN,Map& screen,char map[][20], char bgmap[][20], int xcord, int ycord); //fires an X horizontally across the map, uses the map and current player
        //i used the adress of the object so it would effect the current object(correct me if im wrong), i want the current xcord and ycord
        //(should those be byref? or am i just on the wrong track?)
    private:
    int xp;
    int yp;
};
#endif 


Player.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <iostream>
#include <cstdlib>
#include <string>
#include <fstream>
#include <windows.h>
#include "Map.h"
#include "Player.h"
#include <time.h>
Player::Player(int x, int y):
xp(x),
yp(y)
{
}
void Player::InputChoice(Map& screen,char c,char map[][20], char bgmap[][20], int pN)
{

        char x;
        std::cin >> x;
         switch(x){
                case 'w' :        //moves 'x' up one and replaces the coord before with what it originally had
                    if(yp <= 0){
                        yp = 0;
                    }else{yp-=1;}
                        map[yp + 1][xp] = bgmap[yp + 1][xp]; //replace last coord with the background map, which stays constant.
                    break;
                case 's':
                    if(yp >= 19){
                        yp = 19;
                    }else{yp+=1;}
                        map[yp - 1][xp] = bgmap[yp - 1][xp];
                    break;
                case 'a':
                    if(xp <= 0){
                        xp = 0;
                    }else{xp -=1;}
                        map[yp][xp + 1] = bgmap[yp][xp + 1];
                    break;
                case 'd':
                    if(xp >= 19){
                        xp = 19;
                    }else{xp +=1;}
                        map[yp][xp - 1] = bgmap[yp][xp - 1];
                    break;
                case 'g':
                    screen.callFire(pN);
            }
            map[yp][xp] = c; //set current position to 'x', later in this project i will be using a varible when i ask how to put in multiple players
            // and study vectors a little more(lots of learning to do!).
}
void Player::SetStartPos(char c,char map[][20])
{
    map[xp][yp] = c;
}
void Player::FireG(int pN,Map& screen,char map[][20], char bgmap[][20], int xcord, int ycord) //FIRE function
{
    int Path = 1;
    if(pN==2){
        while(map[ycord][xcord - Path] != 'G'){
            xcord -= Path;
            map[ycord][xcord] = 'H'; //this is the "Object" the player fires
            delay(100); //wait 3 seconds before refreshing the screen, this function is not completely
            //finished yet, still working on deleting the H's on the map now.
             if(map[ycord][xcord - Path] == '#')
            {
                map[ycord][xcord - Path] = '^';
                break;
            }
            screen.cls();
            screen.RefreshScreen();
        }
    }else{
        while(map[ycord][xcord + Path] != 'G' && map[ycord][xcord - Path] != '#'){

            xcord += Path;
            map[ycord][xcord] = 'H'; //this is the "Object" the player fires
            delay(100); //wait 3 seconds before refreshing the screen, this function is not completely
            //finished yet, still working on deleting the H's on the map now.
            if(map[ycord][xcord + Path] == '#')
                        {
                            map[ycord][xcord + Path] = '^';
                            break;
                        }
            screen.cls();
            screen.RefreshScreen();

        }
    }
}
  inline void Player::delay( unsigned long ms )
    {
    Sleep( ms );
    }


Map.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef MAP_H
#define MAP_H
#include <string>
#include "Map.h"
#include "Player.h"
#include <vector>
class Map
{
    public:
        void createmap() ;
        void InputChoice(int pN); //pN(Player Number)
        Map(int noP); //number of PLAYERS
        void SSP(); //SET START POSITION
        void RefreshScreen(); //reprint array
        void cls();
        void callFire(int pN); //call the fire function using map
    private:
        static const int nrows = 20; //array bounds
        static const int ncols = 20;
        char map[nrows][ncols];
        char bgmap[nrows][ncols];
        Player pObj; //a map HAS a player, a player is NOT a map(thanks you guys for that logic, helped A LOT)
        Player ptObj;
};
#endif // MAP_H 


Map.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "Map.h"
#include "Player.h"
#include <iostream>
#include <cstdlib>
#include <string>
#include <fstream>
#include <windows.h>
Map::Map(int pN):
pObj(5,5),
ptObj(15,15) //player TWO object
{
}
void Map::SSP() //calls player function
{
            pObj.SetStartPos('B',map);
            ptObj.SetStartPos('O',map);
}
void Map::InputChoice(int pN) //player NUMBER
{
    /* i didnt know how to access the player class outside without making another object to player, so i just made a function that
    calls the object, i need this seperate because i need to call input, THEN cls(), then refresh, in that specific order. Comment if you think i should
    move the refresh function into map aswell to make some giant function that handles it. Problem is i feel like im stuffing to much stuff into Map.h and
    .cpp */
    switch(pN){
        case 1:
            pObj.InputChoice(*this,'B',map,bgmap,1); //calls player functions
            break;
        case 2:
            ptObj.InputChoice(*this,'O',map,bgmap,2);
            break;
    }
}
void Map::RefreshScreen() //reprint array
{
    cls();
    for( int nrow = 0; nrow < nrows; nrow++){
            for(int ncol = 0; ncol < ncols;ncol++)
                std::cout << map[nrow][ncol] << " ";
            std::cout << std::endl;
            }
}
void Map::cls() //windows h function to replace screen with nulls
{
  DWORD n;
  DWORD size;
  COORD coord = {0};
  CONSOLE_SCREEN_BUFFER_INFO csbi;
  HANDLE h = GetStdHandle ( STD_OUTPUT_HANDLE );
  GetConsoleScreenBufferInfo ( h, &csbi );
  size = csbi.dwSize.X * csbi.dwSize.Y;
  FillConsoleOutputCharacter ( h, TEXT ( ' ' ), size, coord, &n );
  GetConsoleScreenBufferInfo ( h, &csbi );
  FillConsoleOutputAttribute ( h, csbi.wAttributes, size, coord, &n );
  SetConsoleCursorPosition ( h, coord );
}
void Map::callFire(int pN)
{
    switch(pN){
        case 1:
        //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
            pObj.FireG(1,*this, map, bgmap, pObj.getx(), pObj.gety()); //ERRORS HERE!
        //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
            break;
        case 2:
        //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
            ptObj.FireG(2,*this, map, bgmap,ptObj.getx(),ptObj.gety()); //ERRORS HERE!
        //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
            break;
    }
}
void Map::createmap() { //read map in from "Map.txt" file
    using namespace std;
    ifstream MapStruct("Map.txt");
    while(!MapStruct.eof()){
        for( int nrow = 0; nrow < nrows; nrow++){
            for(int ncol = 0; ncol < ncols;ncol++){
                    MapStruct >> map[nrow][ncol];
                    bgmap[nrow][ncol] = map[nrow][ncol];
                }
            }
        }
MapStruct.close(); //close file to prevent leaks
}

concol.h(header used for color, not mine)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#ifndef _EKU_CONCOL
#define _EKU_CONCOL

#ifndef _INC_WINDOWS
#include<windows.h>
#endif /*_INC_WINDOWS*/

bool textcolorprotect=true;
/*doesn't let textcolor be the same as backgroung color if true*/

enum concol
{
	black=0,
	dark_blue=1,
	dark_green=2,
	dark_aqua,dark_cyan=3,
	dark_red=4,
	dark_purple=5,dark_pink=5,dark_magenta=5,
	dark_yellow=6,
	dark_white=7,
	gray=8,
	blue=9,
	green=10,
	aqua=11,cyan=11,
	red=12,
	purple=13,pink=13,magenta=13,
	yellow=14,
	white=15
};

inline void setcolor(concol textcolor,concol backcolor);
inline void setcolor(int textcolor,int backcolor);
int textcolor();/*returns current text color*/
int backcolor();/*returns current background color*/

#define std_con_out GetStdHandle(STD_OUTPUT_HANDLE)

//-----------------------------------------------------------------------------

int textcolor()
{
	CONSOLE_SCREEN_BUFFER_INFO csbi;
	GetConsoleScreenBufferInfo(std_con_out,&csbi);
	int a=csbi.wAttributes;
	return a%16;
}

int backcolor()
{
	CONSOLE_SCREEN_BUFFER_INFO csbi;
	GetConsoleScreenBufferInfo(std_con_out,&csbi);
	int a=csbi.wAttributes;
	return (a/16)%16;
}

inline void setcolor(concol textcol,concol backcol)
{setcolor(int(textcol),int(backcol));}

inline void setcolor(int textcol,int backcol)
{
	if(textcolorprotect)
	{if((textcol%16)==(backcol%16))textcol++;}
	textcol%=16;backcol%=16;
	unsigned short wAttributes= ((unsigned)backcol<<4)|(unsigned)textcol;
	SetConsoleTextAttribute(std_con_out, wAttributes);
}

#if defined(_INC_OSTREAM)||defined(_IOSTREAM_)
ostream& operator<<(ostream& os,concol c)
{os.flush();setcolor(c,backcolor());return os;}
#endif /*_INC_OSTREAM*/

#if defined(_INC_ISTREAM)||defined(_IOSTREAM_)
istream& operator>>(istream& is,concol c)
{cout.flush();setcolor(c,backcolor());return is;}
#endif /*_INC_ISTREAM*/

#endif /*_EKU_CONCOL*/



Map.txt
G G G G G G G G G G G G G G G G G G G G
G I I I I I I I # I I I I I I I I I I G
G I I I I I I I # I I I I I I I I I I G
G I I I # I I I # I I I I I I I I I I G
G I I I # I I I # I I I I I # I I I I G
G I I # I I I I # I I I I I # I I I I G
G I I I I I I I # I I I I I I I I I I G
G I I I I I I I # # I I I I I I I I I G
G I I I I I I I # I I I I I I # I I I G
G I I I # I I I # # I I I I I I I I I G
G I I I # I I I # I I I I I I I I I I G
G I I I # I I I # I I I I I I # I I I G
G I I I # I I I # I I I I I I I I I I G
G I I I I I I I # I I # I I I I I I I G
G I I I I I I I # I I # I I I I I I I G
G I I I I I I I # I I # I I I I I I I G
G I I I I I I I # I I I I I I I I I I G
G I I I I I I I # I I I I I I I I I I G
G I I I I I I I # I I I I I I I I I I G
G G G G G G G G G G G G G G G G G G G G
Last edited on
Wow you just blew me away there...lol

The map part does seem like that's sorta the route I'm going, with each room possible have a short description and the four directions to go. Still trying to figure out the SFML stuff right now but might put that on hold and stay with the console app since I'm already familiar with it more so than the other. I'll take a look at how you did your maps and see if I can make that work for me, thanks :-)

-edit-

Just saw something that put what I want to do a good way. It's pretty much like a mud without being online nor multi-user right now. So pretty much a book that you read yet make choices that affect the outcome from different scenarios. I think that's the best way to describe what I'm trying to do.
Last edited on
Large amounts of code can get really complicated... i tried to comment as much as i could when programming that to help the reader understand.

SFML is pretty simple to learn, i've been learning it a little each day for a couple weeks now and ive got the core functions and routines down. If you decide to use sfml make sure you learn a little about the stringstream, it can come in handy a lot.

About your edit: so do you mean literally as a book? e.g.

press 1 to release the bats onto harry, or 2 to release the bats onto jim
2
Jim falls into a hole and dies! now what does harry do?


and so on? You mentioned using maps, which confuses me. Maybe a little example using the program output tags? thanks
well in a way yea like that. Have you played a mud? Check out http://www.dsl-mud.org/playdsl/playdsl.asp this site, something like this just not as big or intricate. Going to install SFML tomorrow and try getting it working cause I think I'll need to use something like that instead.
Topic archived. No new replies allowed.