Recursive method lacks recursivity

I am trying to program minesweeper, and I'm not having too much trouble except in where you try to clear all the zeroes from a section you enter the coordinates to. I had one method that almost worked, but it failed when the program went to a new line, so I tried a recursive function to search for all the zeroes connected to one zero. When I tried this, I ended up with more problems than before, so I've tried outputting what's happening and it seems that after going through two layers of recursion, the program just stops and goes back to the start without searching all possible connections. What's wrong with 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
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
void Minesweeper::zone()
{
	//declare variables
	int zone = 1;

	/*//test zoning
	showBoard();*/ //used for testing method

	//start zoning
	for(int y = 0; y < rows; y++)
	{
		for(int x = 0; x < columns; x++)
		{
			if(board[x][y][DISPLAY] == 0 && board[x][y][ZONES] == 0)
			{
				board[x][y][ZONES] = zone;
				search(x, y, zone);
				zone++;
			}//end if
		}//end for
	}//end for

	//zone non-zeroes
	for(int y = 0; y < rows; y++)
	{
		for(int x = 0; x < columns; x++)
		{
			if(board[x][y][DISPLAY] == 0 && board[x][y][ZONES] != 0)
			{
				//declare temps
				int aMin;
				int aMax;
				int bMin;
				int bMax;

				if(x == 0)
				{
					aMin = 0;
					aMax = 1;
				}
				else if(x == columns - 1)
				{
					aMin = -1;
					aMax = 0;
				}
				else
				{
					aMin = -1;
					aMax = 1;
				}//end ifs
				if(y == 0)
				{
					bMin = 0;
					bMax = 1;
				}
				else if(y == rows - 1)
				{
					bMin = -1;
					bMax = 0;
				}
				else
				{
					bMin = -1;
					bMax = 1;
				}//end ifs
				zone = board[x][y][ZONES];

				for(int b = bMin; b <= bMax; b++)
				{
					for(int a = aMin; a <= aMax; a++)
					{
						stringstream z;
						stringstream find;
						z << board[a + x][b + y][ZONES];
						find << zone;
						if(int(z.str().find(find.str(), 0)) < 0 && board[a + x][b + y][DISPLAY] != 0)
						{
							stringstream s;
							s.str(z.str() + find.str());
							stringstream(s.str()) >> board[a + x][b + y][ZONES];
						}
						else if(board[a + x][b + y][DISPLAY] != 0)
							board[a + x][b + y][ZONES] = zone;
						//end ifs
						z.str("");
						find.str("");
					}//end for
				}//end for
			}//end if
		}//end for
	}//end for
}//end zone
void Minesweeper::search(int xPos, int yPos, int z)
{
	//declare variables
	int xMin;
	int xMax;
	int yMin;
	int yMax;

	//get mins and maxes
	if(xPos == 0)
	{
		xMin = 0;
		xMax = 1;
	}
	else if(xPos == columns - 1)
	{
		xMin = -1;
		xMax = 0;
	}
	else
	{
		xMin = -1;
		xMax = 1;
	}//end ifs
	//get mins and maxes
	if(yPos == 0)
	{
		yMin = 0;
		yMax = 1;
	}
	else if(yPos == rows - 1)
	{
		yMin = -1;
		yMax = 0;
	}
	else
	{
		yMin = -1;
		yMax = 1;
	}//end ifs

	for(int y = yMin; y <= yMax; y++)
	{
		for(int x = xMin; x <= xMax; x++)
		{
			/*cout << xPos + x << "," << yPos + y << endl;
			cout << board[xPos + x][yPos + y][DISPLAY] << endl;
			cout << board[xPos + x][yPos + y][ZONES];*/ //used for checking the method
			if(board[xPos + x][yPos + y][DISPLAY] == 0 && board[xPos + x][yPos + y][ZONES] == 0)
			{
				//cout << " << " << z << endl;  used for testing method
				board[xPos + x][yPos + y][ZONES] = z;
				//system("pause");  used for testing method
				search(x, y, z);
			}//end if
			/*else
			{
				cout << endl;
				system("pause");
			}*/ used for testing method */
		}//end for
	}//end for
}//end search 
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
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//gives regions of zeroes in minesweeper zones
//so that they can be cleared all at once
void Minesweeper::zone()
{
	//declare variables
	int zone = 1;

	//start zoning
	for(int y = 0; y < rows; y++)
	{
		for(int x = 0; x < columns; x++)
		{
                        //only search neighboring cells if current cell
                        //has no zone and no neighboring bombs
			if(board[x][y][DISPLAY] == 0 && board[x][y][ZONES] == 0)
			{
                                //don't check this cell again
				board[x][y][ZONES] = zone;

                                //search all neighboring cells
				search(x, y, zone);

                                //next occurrences will have different zone
				zone++;
			}//end if
		}//end for
	}//end for

	//zone non-zeroes
	for(int y = 0; y < rows; y++)
	{
		for(int x = 0; x < columns; x++)
		{
                        //if cell has no neighboring bombs
                        //force zone upon all neighboring cells
			if(board[x][y][DISPLAY] == 0 && board[x][y][ZONES] != 0)
			{
				//declare temps
				int aMin;
				int aMax;
				int bMin;
				int bMax;

                                //get mins and maxes
                                //was originally a switch statement
                                //but rows and columns are not constants
				if(x == 0)
				{
					aMin = 0;
					aMax = 1;
				}
				else if(x == columns - 1)
				{
					aMin = -1;
					aMax = 0;
				}
				else
				{
					aMin = -1;
					aMax = 1;
				}//end ifs
				if(y == 0)
				{
					bMin = 0;
					bMax = 1;
				}
				else if(y == rows - 1)
				{
					bMin = -1;
					bMax = 0;
				}
				else
				{
					bMin = -1;
					bMax = 1;
				}//end ifs
				zone = board[x][y][ZONES];

				for(int b = bMin; b <= bMax; b++)
				{
					for(int a = aMin; a <= aMax; a++)
					{
                                                //put zones of both cells into
                                                //stringstream objects so that they
                                                //can be concatenated
						stringstream z;
						stringstream find;
						z << board[a + x][b + y][ZONES];
						find << zone;

                                                //if zone of neighbor cell does not contain
                                                //zone of initial, neighbor has a bomb as a 
                                                //neighbor, and neighbor already has a zone
						if(int(z.str().find(find.str(), 0)) < 0 && board[a + x][b + y][DISPLAY] != 0 && board[a + x][b + y][ZONES] != 0)
						{
                                                        //concatenate two zones into one
                                                        //for neighbor cell
							stringstream s;
							s.str(z.str() + find.str());
							stringstream(s.str()) >> board[a + x][b + y][ZONES];
						}
                                                //if cell has a bomb as a neighbor and
                                                //does not meet previous requirements
						else if(board[a + x][b + y][DISPLAY] != 0)
							board[a + x][b + y][ZONES] = zone;
						//end ifs

                                                //clear objects for next use
						z.str("");
						find.str("");
					}//end for
				}//end for
			}//end if
		}//end for
	}//end for
}//end zone

/*Recursive method meant to search all cells
  around a cell for zeroes to add to the region
  of the initial cell being searched around*/
/*This method calls itself once before returning to the
  calling method (not search) without reading any more
  lines of search*/
void Minesweeper::search(int xPos, int yPos, int z)
{
	//declare variables
	int xMin;
	int xMax;
	int yMin;
	int yMax;

	//get mins and maxes
        //these were originally a switch statement
        //but rows and columns are not constants
	if(xPos == 0)
	{
		xMin = 0;
		xMax = 1;
	}
	else if(xPos == columns - 1)
	{
		xMin = -1;
		xMax = 0;
	}
	else
	{
		xMin = -1;
		xMax = 1;
	}//end ifs
	//get mins and maxes
        //same as above mins and maxes
	if(yPos == 0)
	{
		yMin = 0;
		yMax = 1;
	}
	else if(yPos == rows - 1)
	{
		yMin = -1;
		yMax = 0;
	}
	else
	{
		yMin = -1;
		yMax = 1;
	}//end ifs

	for(int y = yMin; y <= yMax; y++)
	{
		for(int x = xMin; x <= xMax; x++)
		{
                        //only search all neighboring cells if this cell
                        //has no zone and zero neighboring bombs
			if(board[xPos + x][yPos + y][DISPLAY] == 0 && board[xPos + x][yPos + y][ZONES] == 0)
			{

                                //give cell a zone so that it will
                                //not be checked multiple times
				board[xPos + x][yPos + y][ZONES] = z;

                                //search all neighboring cells
				search(x, y, z);
			}//end if
		}//end for
	}//end for
}//end search  
I'd say that's way too complicated. In my book the process would be:

- Fille the board randomly with bombs (negative value?)

- for all fields:
1
2
if board[x][y] != bomb
  SetNeighbouringBombCount

- play

pseudo code:

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
RowBombCount (x, y, bool is_midst)
{
count = 0
if x > 0
  if board[x - 1][y] == bomb
    ++count;
if is_midst
  if board[x][y] == bomb
    ++count;
if x < MaxX - 1
  if board[x + 1][y] == bomb
    ++count;

return count;
}

SetNeighbouringBombCount (x, y)
{
count = RowBombCount(x, y, false)
if y > 0
    count += RowBombCount(x, y - 1, true)
if y < MaxY - 1
    count += RowBombCount(x, y + 1, true)

board[x][y] = count
}
I've already finished that part. The part I'm working on now is when there are no neighboring bombs and I want to clear a whole section of neighboring bombs. My method for counting neighboring bombs works, but my method for putting large sections with no neighboring bombs into zones so that they can all be cleared at once is not working.
I'd introduce a new 2d bool array (or an array with bitset).

To find the free cells the approach would be similar to that above:
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
bool SetFreeRow(x, y)
{
has_free = false;
if board[x][y] != bomb
  free_board[x][y] = true
  has_free = true

go_left = true
go_right = true

for i = 1 -> i < MaxX
  if go_left
    free_index_left = x - i
    go_left = free_index_left >= 0
    if go_left
      go_left = board[free_index_left][y] != bomb
    if go_left
      free_board[free_index_left][y] = true
      has_free = true

  if go_right
    free_index_right = x + i
    ...

  if not go_right and not go_left
    break

return has_free
}

SetSurroundingFree(x, y)
{
if SetFreeRow(x, y)
  for i = y - 1 -> i >= 0 --i
    if not SetFreeRow(x, i)
      break
  for i = y + 1 -> i < MaxY ++i
    if not SetFreeRow(x, i)
      break
}


The algorithm for 'go_right' is almost the same as for 'go_left'
Are you able to read that pseudo code?
Last edited on
I think I get what you're saying, but you're missing the second dimension. If it's only looking left and right, then I'm only going to be able to clear part of a line. My search method is intended to set zones for odd shapes. I think I may have just figured out how to fix my code, but it worries me that my recursive method is skipping out for no reason that I can see.
I managed to get the program working correctly. Thanks to all for your help.
Topic archived. No new replies allowed.