Moving in two dimensional vector

Hello,
I'm having one problem. Imagine you are having two dimensional vector in which you want move generated number and you will get this:
0 0 0 0
0 2 0 0
0 0 0 0
0 0 0 0
Result:
0 2 0 0
0 0 0 0
0 0 0 0
0 0 0 0

But when I generate another number as you can see below,it's become a problem:
0 2 0 0
0 2 0 0
0 0 0 0
0 0 0 0
Result:
0 2 0 0
0 0 0 0
0 0 0 0
0 0 0 0

I understand what's the problem is but don't know how to write condition. I have only one solution and it is to create border around but I can't do that because it would require a lot of changes.
1 1 1 1 1 1
1 0 0 0 0 1
1 0 0 0 0 1
1 0 0 0 0 1 --> This would simplify condition but as I said, I couldn't do it
1 0 0 0 0 1
1 1 1 1 1 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
vector< vector<int> > board{ { 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 } };
const int bs = 4; 
  void move_up() {
	int pom = -1;
	for (int i = 0; i < bs; ++i) {
		for (int j = 0; j < bs; ++j) {
			if (board[i][j] != 0 && i != 0) {
				int previous = i - 1;
				pom = board[i][j];
				board[i][j] = 0;
				while (board[previous][j] == 0 && previous != 0)
					--previous;
				board[previous][j] = pom;
			}
		}
	}
}
Last edited on
logically, is it correct to say that you want to 1) locate 2 positions in the structures and 2) swap the values in them?

Or is this just an indexing thing, IE:

structure[currentlocaction] = (no longer here value? zero?)
currentlocation = newlocation;
structure[currentlocation] = (here now value, 2?)

Last edited on
Sorry, quite sloppy asked question. What I want to achieve is that '2' is moving while there is 0 before it. So from this
0 2 0 0
0 0 0 0
0 2 0 0
0 0 0 0

I would want to achieve
0 2 0 0
0 2 0 0
0 0 0 0
0 0 0 0

rather that this
0 2 0 0
0 0 0 0
0 0 0 0
0 0 0 0
The problems are line 8/12. You set previous without checking if it is acutally valid.

I suggest following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
				int previous = i;
				for(int prev = i - 1; prev != 0; --prev)
				{
					if(board[prev][j] == 0) // EDIT: prev instead of previous!
					  previous = prev;
					else
					  break;
				}
				if(previous != i)
				{
					pom = board[i][j];
					board[i][j] = 0;
					board[previous][j] = pom;
				}
move_up() will proceed until the border or a value != 0 is reached. Is that intended?

[EDIT]
Changed line 4
Last edited on
Yes, thats intended but unfortunately it's still isn't working. I'm getting some sort of error, some problem with a vector. I'm trying to figure out, what's the problem is.
This doesn't make sesnse to me:
1
2
3
4
int previous = i;
for (int prev = i - 1; prev != 0; --prev){
				if (board[previous][j] == 0)                     
					previous = prev;


because if we have it like this:
0 0 0 0
0 0 0 0
0 2 0 0
0 0 0 0
then our previous==2 and in if statement we are asking whether board[previous][j] is equal to zero but in fact we have '2' in there.
Last edited on
meh just check if the line it is going to has 2 or not
this is something similiar
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 <vector>
#include <string>
#include <conio.h>
#include <windows.h>

int main()
{
    std::vector<std::string> output;
    int p_x = 1;
    int p_y = 1;
    for (int y = 0; y < 5; ++y)
    {
        std::string inner;
        for (int x = 0; x < 5; ++x)
        {
            inner.push_back('X');
        }
        output.push_back(inner);
    }
    for (int y = 1; y < 4; ++y)
    {
        for (int x = 1; x < 4; ++x)
        {
            output.at(y).at(x) = ' ';
        }
    }
    while (1)
    {
        if (kbhit())
        {
            char key = getch();
            switch (key)
            {
            case 'w' :
                if (output.at(p_y - 1).at(p_x) != ' ') break;
                output.at(p_y--).at(p_x) = ' ';
                output.at(p_y).at(p_x) = '@';
                break;
            case 's' :
                if (output.at(p_y + 1).at(p_x) != ' ') break;
                output.at(p_y++).at(p_x) = ' ';
                output.at(p_y).at(p_x) = '@';
            case 'a' :
                if (output.at(p_y).at(p_x - 1) != ' ') break;
                output.at(p_y).at(p_x--) = ' ';
                output.at(p_y).at(p_x) = '@';
            case 'd' :
                if (output.at(p_y).at(p_x + 1) != ' ') break;
                output.at(p_y).at(p_x++) = ' ';
                output.at(p_y).at(p_x) = '@';
            }
        }
        for (auto& a : output)
        {
            std::cout << a << std::endl;
        }
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), COORD{0, 0});
    }
}


I simply check if the line it is going into is empty or not
Last edited on
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 <limits>
#include <vector>


std::vector<std::vector<int>>& move_up(std::vector<std::vector<int>>& board);
void waitForEnter();


int main()
{
    std::vector<std::vector<int>> board { { 0, 0, 3, 0 }, 
                                          { 0, 2, 0, 4 },
                                          { 0, 0, 3, 0 }, 
                                          { 0, 0, 0, 4 } };
    for(const auto& v : board) {
        for(const auto& i : v) {
            std::cout << i << ' ';
        }
        std::cout << '\n';
    }
    std::cout << '\n';
    move_up(board);
    for(const auto& v : board) {
        for(const auto& i : v) {
            std::cout << i << ' ';
        }
        std::cout << '\n';
    }
    std::cout << '\n';
    waitForEnter();
    return 0;
}


std::vector<std::vector<int>>& move_up(std::vector<std::vector<int>>& board)
{
    for (size_t i = 1; i < board.size(); ++i) { // let's skip first row
        for (size_t j = 0; j < board.size(); ++j) {
            if(board.at(i).at(j) != 0) {
                size_t lifter {i};
                while(lifter > 0 && board.at(lifter-1).at(j) == 0) {
                    lifter--;
                }
                if(lifter < i) {
                    board.at(lifter).at(j) = board.at(i).at(j);
                    board.at(i).at(j) = 0;
                }
            }
        }
    }
    return board;
}


void waitForEnter()
{
    std::cout << "\nPress ENTER to continue...\n";
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

using std::stable_partition on the columns of the board vector:
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
# include <iostream>
# include <vector>
# include <utility>
# include <algorithm>

constexpr auto ROW = 4;
constexpr auto COL = 4;

using vec2D = std::vector<std::vector<int>>;

vec2D transpose2D(vec2D& board)
{
    vec2D transposeBoard{};
    for (auto i = 0; i < COL; ++i)
    {
        size_t j{};
        std::vector<int> inner{};
        while (j < ROW)
        {
            inner.push_back(std::move(board[j][i]));
            ++j;
        }
        transposeBoard.push_back(std::move(inner));
        inner.clear();
    }
    return transposeBoard;
}

int main()
{
    std::vector<std::vector<int>> board { { 0, 0, 3, 0 }, { 0, 0, 0, 4 }, { 0, 3, 3, 0 }, { 0, 0, 0, 4 }};

    auto firstTranspose = transpose2D(board);
    for (auto & elem : firstTranspose)
    {
        std::stable_partition(elem.begin(), elem.end(), [](int i){return i != 0;});
    }
    auto transposeBack = transpose2D(firstTranspose);
}
Just in case someone would struggle with the similar problem in the future, this is my solution:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void move_up() {
	for (int i = 0; i < bs; ++i) {
		for (int j = 0; j < bs; ++j) {
			if (board[i][j] != 0 && i != 0) {
				int pom = board[i][j];
				board[i][j] = 0;
				int prev = i;
				while (board[prev][j] == 0) {
					if (prev == 0) {
						prev = -1;
						break;
					}
					else
						--prev;
				}
				board[prev + 1][j] = pom;
			}
		}
	}
}
Topic archived. No new replies allowed.