multidimensional array game map help please

Im trying to create a small game using a multidimensional array but i cant seem to figure it out, i know its not a good idea to do it, but i wanted to try it.

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
#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
    int map[2][5] = {{0,0,0,0,0}, {0,0,0,0,0}};
    char player = '*';

    while(true)
    {
        int direction = 0;

        player = map[0][0];


        for(int x = 0; x < 2; x++)
        {
            for(int y = 0; y < 5; y++)
            {
                cout << map[x][y];
            }

            cout << endl;
        }

        cin.get();
        
        cin >> direction;

        if(direction == 1)
        {
            
        }
    }
}
You set player to map[0][0], so now player is 0, whereas map is unchanged. Also, you should make map an array of char, not an array of int.
ok i changed the int array to char but how do i make the player move on the map?

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
#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
    char map[2][5] = {{0,0,0,0,0}, {0,0,0,0,0}};
    char player = '*';

    char up = 'W';
    char down = 'S';
    char left = 'A';
    char right = 'D';

    int x = 0;
    int y = 0;

    up = GetAsyncKeyState(0x57);
    down = GetAsyncKeyState(0x53);
    left = GetAsyncKeyState(0x41);
    right = GetAsyncKeyState(0x52);


    while(true)
    {
        int direction = 0;

        map[0][0] = player;


        for(x; x < 2; x++)
        {
            for(y; y < 5; y++)
            {
                cout << map[x][y];
            }

            cout << endl;
        }

        cin.get();

        cin >> direction;

        while(up)
        {

        }
    }
}
First put the GetAsyncKeyState inside the while loop.
Second increment/decrement x/y according to the result of GetAsyncKeyState

like so:
1
2
3
4
5
6
GetAsyncKeyState(0x57)
...
if(up)
  --x;
...
map[x][y] = player;


See:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646293%28v=vs.85%29.aspx

how GetAsyncKeyState works
I still cant get it to work i dont knwo what im doing wrong, I got the player to appear on the grid but he wont move

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
#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
    char map[5][5] = {{'#','#','#','#','#'}, {'#','#','#','#','#'},
                      {'#','#','#','#','#'}, {'#','#','#','#','#'},
                      {'#','#','#','#','#'}};
    char player = '*';

    char up = 'W';
    char down = 'S';
    char left = 'A';
    char right = 'D';

    int x = 0;
    int y = 0;


    while(true)
    {
        up = GetAsyncKeyState(0x57);
        down = GetAsyncKeyState(0x53);
        left = GetAsyncKeyState(0x41);
        right = GetAsyncKeyState(0x52);

        system("cls");

        map[x][y] = player;

        for(x = 0; x < 5; x++)
        {
            for(y = 0; y < 5; y++)
            {
                cout << map[x][y];
            }

            cout << endl;
        }

        if(up)
        {
            ++y;
        }
        else if(down)
        {
            --y;
        }
        else if(left)
        {
            ++x;
        }
        else if(right)
        {
            --x;
        }
    }
}
Last edited on
Every iteration of the loop, when you draw the map you reset x and y to the same value - (5,5) which is outside the map. Don't use x and y in the for loops.

Additionally, the outer loop for loop should be for the y value, inner for the x. Pay attention to warnings from your compiler. char is not an appropriate type for up, down, left and right. What you're doing with the x and y coordinates when moving in a particular direction is wrong for movement in both directions.

Going over the documentation for GetAsyncKeyState is recommended.
Last edited on
Ok i went over GAKS and i still cant figure this out, it has to be something simple but idk

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
#include <iostream>
#include <windows.h>

#define VK_UP 0x57
#define VK_DOWN 0x53
#define VK_LEFT 0x41
#define VK_RIGHT 0x52

using namespace std;

int main()
{
    char map[5][5] = {{'#','#','#','#','#'}, {'#','#','#','#','#'},
                      {'#','#','#','#','#'}, {'#','#','#','#','#'},
                      {'#','#','#','#','#'}};
    char player = '*';

    int up = 0;
    int down = 0;
    int left = 0;
    int right = 0;

    int x = 2;
    int y = 3;

    while(true)
    {
        system("cls");

        map[x][y] = player;

        for(y = 0; y < 5; y++)
        {
            for(x = 0; x < 5; x++)
            {
                cout << map[x][y];
            }

            cout << endl;
        }

        if(GetAsyncKeyState(0x57) == VK_UP)
        {
            y++;
        }
        else if(GetAsyncKeyState(0x53) == VK_DOWN)
        {
            y--;
        }
        else if(GetAsyncKeyState(0x41) == VK_LEFT)
        {
            x++;
        }
        else if(GetAsyncKeyState(0x52) == VK_RIGHT)
        {
            x--;
        }
    }
}
Last edited on
You're still using the x and y that designate your player position to control the for loops that draw the entire map, which still sets them to a position outside of the map every iteration of the loop.

Make them different variables. You can keep the same name if you desire; the scopes shouldn't be a problem.

1
2
3
4
5
6
7
8
9
        for(int y = 0; y < 5; y++)
        {
            for(int x = 0; x < 5; x++)
            {
                cout << map[x][y];
            }

            cout << endl;
        }

Last edited on
Like this?

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
#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
    char map[5][5] = {{'#','#','#','#','#'}, {'#','#','#','#','#'},
                      {'#','#','#','#','#'}, {'#','#','#','#','#'},
                      {'#','#','#','#','#'}};
    char player = '*';

    int up = 0;
    int down = 0;
    int left = 0;
    int right = 0;

    int x = 2;
    int y = 3;

    up = GetAsyncKeyState(0x57);
    down = GetAsyncKeyState(0x53);
    left = GetAsyncKeyState(0x41);
    right = GetAsyncKeyState(0x52);

    while(true)
    {
        system("cls");

        map[x][y] = player;

        for(int y = 0; y < 5; y++)
        {
            for(int x = 0; x < 5; x++)
            {
                cout << map[x][y];
            }

            cout << endl;
        }

        if(up)
        {
            y++;
        }
        else if(down)
        {
            y--;
        }
        else if(left)
        {
            x++;
        }
        else if(right)
        {
            x--;
        }
    }
}
Yep, like that.

Now move line 21 to 24 back inside the while loop.
Last edited on
Ok it moves but its really odd im not sure how to explain it, if you test it out youll seed its slow and stuff and it doesnt move sometimes and it doesnt move in the direction i want

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
#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
    char map[5][5] = {{'#','#','#','#','#'}, {'#','#','#','#','#'},
                      {'#','#','#','#','#'}, {'#','#','#','#','#'},
                      {'#','#','#','#','#'}};
    char player = '*';

    int up = 0;
    int down = 0;
    int left = 0;
    int right = 0;

    int x = 2;
    int y = 3;

    while(true)
    {
        up = GetAsyncKeyState(0x57);
        down = GetAsyncKeyState(0x53);
        left = GetAsyncKeyState(0x41);
        right = GetAsyncKeyState(0x52);

        map[x][y] = player;

        for(int y = 0; y < 5; y++)
        {
            for(int x = 0; x < 5; x++)
            {
                cout << map[x][y];
            }

            cout << endl;
        }

        if(up)
        {
            y++;
        }
        else if(down)
        {
            y--;
        }
        else if(left)
        {
            x++;
        }
        else if(right)
        {
            x--;
        }
    }
}
Last edited on
It's actually not slow at all. It's rather ridiculously fast, which is part of the problem. It's easy to go off the map and start obliterating memory that shouldn't be touched.

Try the following.

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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <iostream>
#include <windows.h>

using namespace std;

void cls( HANDLE hConsole ) ;
 
int main()
{
    char map[5][5] = {{'#','#','#','#','#'}, {'#','#','#','#','#'},
                      {'#','#','#','#','#'}, {'#','#','#','#','#'},
                      {'#','#','#','#','#'}};
    char player = '*';

    int up = 0;
    int down = 0;
    int left = 0;
    int right = 0;

    HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE) ;

    int x = 2;
    int y = 3;


    while(true)
    {
        Sleep(100) ;  // slow things down a bit.

        cls(console) ;

        up =    GetAsyncKeyState(0x57) & 0x8000 ;
        down =  GetAsyncKeyState(0x53) & 0x8000 ;
        left =  GetAsyncKeyState(0x41) & 0x8000 ;
        right = GetAsyncKeyState(0x44) & 0x8000 ;

        map[x][y] = player;

        for(int y = 0; y < 5; y++)
        {
            for(int x = 0; x < 5; x++)
            {
                cout << map[x][y];
            }

            cout << endl;
        }

        map[x][y] = '#' ;

        if(up)
        {
            y--;
        }
        else if(down)
        {
            y++;
        }
        else if(left)
        {
            x--;
        }
        else if(right)
        {
            x++;
        }

        if ( x == 5 )
            x = 4 ;
        else if ( x < 0 )
            x = 0 ;

        if ( y == 5 )
            y = 4 ;
        else if ( y < 0 )
            y = 0 ;
    }
}

// lifted nearly verbatim from http://support.microsoft.com/kb/99261
// changed the PERR macro to avoid the need to include cstdio

/* Standard error macro for reporting API errors */ 
 #define PERR(bSuccess, api){if(!(bSuccess)) \
    std::cout << __FILE__ << ":Error " << GetLastError() \
        << " from " << api " on line " << __LINE__ << '\n';}

 void cls( HANDLE hConsole )
 {
    COORD coordScreen = { 0, 0 };    /* here's where we'll home the
                                        cursor */ 
    BOOL bSuccess;
    DWORD cCharsWritten;
    CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ 
    DWORD dwConSize;                 /* number of character cells in
                                        the current buffer */ 

    bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
    PERR( bSuccess, "GetConsoleScreenBufferInfo" );
    dwConSize = csbi.dwSize.X * csbi.dwSize.Y;

    bSuccess = FillConsoleOutputCharacter( hConsole, (TCHAR) ' ',
       dwConSize, coordScreen, &cCharsWritten );
    PERR( bSuccess, "FillConsoleOutputCharacter" );

    bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
    PERR( bSuccess, "ConsoleScreenBufferInfo" );

    bSuccess = FillConsoleOutputAttribute( hConsole, csbi.wAttributes,
       dwConSize, coordScreen, &cCharsWritten );
    PERR( bSuccess, "FillConsoleOutputAttribute" );

    bSuccess = SetConsoleCursorPosition( hConsole, coordScreen );
    PERR( bSuccess, "SetConsoleCursorPosition" );
 }


[Edit: Oops. Removed an errant code tag from the PERROR macro.]
Last edited on
Is there anything that doesnt use Win API? i found this example

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
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
char map[17][21] = {{'+','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','+'},
                    {'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
                    {'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
                    {'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
                    {'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
                    {'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
                    {'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
                    {'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
                    {'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
                    {'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
                    {'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
                    {'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
                    {'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
                    {'+','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','+'}};
int main() {
    char kbinput;
    int x=3;
    int y=3;
    int col, row;
    while (true) {
        system("cls");
        for(row = 0; row <= 16; row++) {
            for (col = 0; col <= 20; col++)
                cout << map[row][col];
            cout << endl;
        }
        kbinput = _getch();
        switch(kbinput) {
            case 'e':
                char myi;
                cout << "Input char:";
                cin >> myi;
                map[y][x] = myi;
                y = 2;
                x = 2;
                break;
            case 'd':
                if(map[y][x+1]== '|') break;
                map[y][x]=' ';
                x += 1;
                map[y][x] = '+';
                break;
            case 'a':
                if(map[y][x-1]== '|') break;
                map[y][x]=' ';
                x -= 1;
                map[y][x] = '+';
                break;
            case 'w':
                if(map[y-1][x]== '-') break;
                map[y][x]=' ';
                y -= 1;
                map[y][x]='+';
                break;
            case 's':
                if(map[y+1][x]== '-') break;
                map[y][x]=' ';
                y += 1;
                map[y][x] = '+';
                break;
        }
    }
}


This code works like i want my game to work but i dont want to just copy someone elses code from a site, i want to actually build it myself. in this i can use the WASD keys to move around but i dont understand how he's doing that without using and WinApi Code?
He uses another non-portable library. If you want to deal with stuff like this, it is going to be OS specific, or else you need to use a library that does the OS specific stuff for you.
Yeah OS specific is fine, i dont plan on making programs for any other OS but windows anyhow.
Ok, so I was kind of making this sort of thing yesterday, so I mocked up a program for moving a player for you.

I've split the code in to functions, but they are all on the same page:
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
// Main entry point for console application.

#include <Windows.h>
#include <conio.h>
#include <iostream>

enum direction
{
	UP,
	DOWN,
	LEFT,
	RIGHT
};

// Function prototypes.
void kbHit( char &key );
void movePlayer( direction d );
void drawBoard();

#define playerChar ' '
COORD playerPosition;

const char mapArea = 22;
char map[ mapArea ][ mapArea ];

int main()
{
	for( int i = 0; i < mapArea; ++i )
		for( int j = 0; j < mapArea; ++j )
			map[ i ][ j ] = '#';

	char key = ' ';

	playerPosition.X = 0;
	playerPosition.Y = 0;

	drawBoard();

	while( key != 13 )
	{
		kbHit( key );
	}

	return 0;
}


Line 39 of the following 'kbHit' function is the limit in milliseconds of the repeat of a key held down. Like said before in this thread, it was way too fast. With line 39, the key will press 5 times a second( roughly ).
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
struct key
{
	key( const bool &b, const double &d ) : previousState( b ), currentState( b ), keyReset( d ) {}

	bool previousState;
	bool currentState;

	double keyReset;
	double upTime;

	key &operator= ( const bool & b )
	{
		previousState = b;
		currentState = b;

		return *this;
	}

	key &operator= ( const double &d )
	{
		upTime = d;

		return *this;
	}
};

void kbHit( char &k )
{
	static key up( false, GetTickCount() );
	static key down( false, GetTickCount() );
	static key right( false, GetTickCount() );
	static key left( false, GetTickCount() );

	up = ( GetTickCount() - up.keyReset );
	down = GetTickCount() - down.keyReset;
	right = GetTickCount() - right.keyReset;
	left = GetTickCount() - left.keyReset;

	const int update = 200;


	if( ( up.upTime > update ) && ( GetAsyncKeyState( VK_UP ) ) )
	{
		up.previousState = false;

		up.keyReset = GetTickCount();
	}

	if( ( down.upTime > update ) && ( GetAsyncKeyState( VK_DOWN ) ) )
	{
		down.previousState = false;

		down.keyReset = GetTickCount();
	}

	if( ( right.upTime > update ) && ( GetAsyncKeyState( VK_RIGHT ) ) )
	{
		right.previousState = false;

		right.keyReset = GetTickCount();
	}

	if( ( left.upTime > update ) && ( GetAsyncKeyState( VK_LEFT ) ) )
	{
		left.previousState = false;

		left.keyReset = GetTickCount();
	}

	if( GetAsyncKeyState( VK_UP ) )
		up.currentState = true;
	else
		up.currentState = false;

	if( GetAsyncKeyState( VK_DOWN ) )
		down.currentState = true;
	else
		down.currentState = false;

	if( GetAsyncKeyState( VK_LEFT ) )
		left.currentState = true;
	else
		left.currentState = false;
		
	if( GetAsyncKeyState( VK_RIGHT ) )
		right.currentState = true;
	else
		right.currentState = false;


	if( up.currentState != up.previousState )
	{
		if( up.currentState ) //Key pressed.
			movePlayer( UP );

		up.previousState = up.currentState;
	}

	if( down.currentState != down.previousState )
	{
		if( down.currentState ) //Key pressed.
			movePlayer( DOWN );

		down.previousState = down.currentState;
	}

	if( left.currentState != left.previousState )
	{
		if( left.currentState ) //Key pressed.
			movePlayer( LEFT );

		left.previousState = left.currentState;
	}

	if( right.currentState != right.previousState )
	{
		if( right.currentState ) //Key pressed.
			movePlayer( RIGHT );

		right.previousState = right.currentState;
	}

	k= _getch();
}


Always remember to 'erase'/reset the current position, before moving the player. Or you'll be left with a trail.
Edit:
Added the if-statements to make sure the player doesn't go off the map.
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
void movePlayer( direction d )
{
	//Erase the player before moving the player!
	map[ playerPosition.X ][ playerPosition.Y ] = '#';

	switch( d )
	{
		case UP:

			if( playerPosition.Y == 0 )
				return;

			--playerPosition.Y;
			break;

		case DOWN:

			if( playerPosition.Y == mapArea - 1 )
				return;

			++playerPosition.Y;
			break;

		case RIGHT:

			if( playerPosition.X == mapArea - 1 )
				return;

			++playerPosition.X;
			break;

		case LEFT:

			if( playerPosition.X == 0 )
				return;

			--playerPosition.X;
			break;
	}

	//Now redraw the player after the move.
	map[ playerPosition.X ][ playerPosition.Y ] = playerChar;

	drawBoard();
}


I don't currently have a clearScreen function in my code, so I'm just reposting the board each time.
1
2
3
4
5
6
7
8
9
10
11
12
13
void drawBoard()
{
	std::cout << "======================================================\n";
	for( int column = 0; column < mapArea; ++column )
	{
		for( int row = 0; row < mapArea; ++row )
		{
			std::cout << map[ row ][ column ];
		}

		std::cout << '\n';
	}
}


Hope this helps you! (:
Last edited on
Topic archived. No new replies allowed.