Help me identify the bug

Hey guys, I'm creating a BattleShip game and for some reason I'm having trouble with ship placements. Basically, I don't want the ships to overlap one another nor the grid (which is a 2d 10x10 array).

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
if (direction == horizontal)
    {
        int i = 0, currentXcoordinate = x;
        while (i < shipSize)
        {
            for (int k = 0; k < shipSize; ++k)
            {
                if ( (gameBoard[y][x + k] == occupied) || (currentXcoordinate + shipSize) > 10) )
                {
                    cout << "Ships may not overlap, enter another position: \n";
                    isPlacementLegal = false;
                    
                    if (!isPlacementLegal)
                    {
                        break;
                    }
                }
            }
            
            if (!isPlacementLegal)
            {
                isPlacementLegal = true;
                goto SHIP_PLACEMENT; //To place the 2nd ship (total of 5 ships)
            }
            else
            {
                gameBoard[y][x++] = occupied;
            }
            ++i;
        }
    }
    else if (direction == vertical)
    {
        int i = 0, currentYcoordinate = y;
        while (i < shipSize)
        {
            for (int k = 0; k < shipSize; ++k)
            {
                if ((gameBoard[y + l][x] == occupied) || (currentYcoordinate + shipSize > 10))
                {
                    cout << "Ships may not overlap, enter another position: \n";
                    isPlacementLegal = false;
                    
                    if (!isPlacementLegal)
                    {
                        break;
                    }
                }
            }
            if (!isPlacementLegal)
            {
                isPlacementLegal = true;
                goto SHIP_PLACEMENT;
            }
            else
            {
                gameBoard[y++][x] = occupied;
            }
            ++i;
        }
    }

I guess the part that's really confusing me is why when I enter the coordinate say (a, 5) for a ship of size 5 and then (a, 0) for a ship of size 4 is telling me that they're overlapping even though there's 2 empty spaces in between.
Last edited on
Line 39: You wrote gameBoard[y + l] (lowercase L) instead of gameBoard[y + k] which is what I think you meant.
Lines 8 and 39: The > 10 is incorrect. It should be >= 10.

This is not related to your bug, but you don't need two nested loops to place a ship.
1
2
3
4
5
6
7
8
9
10
11
12
13
bool place_horizontal_ship(const int size, const int x, const int y, bool board[10][10]){
    if (x < 0 || x + size >= 10 || y < 0 || y >= 10)
        return false;

    for (int i = x; i < x + size; i++)
        if (board[y][i])
            return false;

    for (int i = x; i < x + size; i++)
        board[y][i] = true;

    return true;
}
Hello again helios,

Thank you for helping me identify the bug. The ships are no longer overlapping in the horizontal nor the vertical axes. However, they are overlapping when they both have different directions. For example, if I place a ship horizontally, I can place a ship vertically that goes through it and that's not what I want. Anyway around that problem?
If you first try to place a horizontal ship on the second row, and then a vertical ship on the second column, do you get something like this,
1
2
3
4
5
 *
*****
 *
 *
 *
or like this?
1
2
3
4
5
 *
*****


At first it was giving me like the first one, but now after attempting to fix it it's giving me the 2nd one. At least they're no longer crossing so that's a step forward I guess :/
Though they are still overlapping.

EDIT: Here's my attempt:

1
2
3
4
5
6
7
8
9
for (int c = 0; c < 2; c++)
			{
				if (!isPlacementLegal || gameBoard[y][x + c] != WATER)
				{
					isPlacementLegal = true;
					goto SHIP_PLACEMENT;
				}
			}	
			gameBoard[y][x++] = occupied;	


This fixes the problem if the user tries to place a horizontal ship exactly one spot beside a vertical ship. However, if the user attempts to place the horizontal ship two spots away the vertical ship, it will leave an annoying '*' behind.

Like this:
1
2
3
4
5
      
   *
*  *
   *
   *


Notice there's a space between the two stars in Line 3
Last edited on
It's because you're placing the ship before knowing if every cell it will occupy is available. Look at my code. I checked every cell before changing anything.
Last edited on
Ahh I see! Thanks for pointing that out for me, I implemented your logic and it worked.
Just when I thought I was FINALLY done with the placement phase I am now facing yet another bug.

So I am placing a ship vertically, for instance, assume it's (a, 5). And then I place a ship horizontally, say, (a, 4). The program will notify the player that they made a mistake and will ask for another position. Which is good. BUT, if the user chooses 'a' again for their Y coordinate and then maybe 0 for their x coordinate, the program for some reason still display the error message even though the ships would not intersect.

Any way around that?

EDIT: Oh and also it leaves a star or two behind when the player enters a Y coordinate other than 'a'.
Last edited on
It doesn't need to be so complicated:

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
#include <iostream>

int main() {

	const double pi = 3.14159265;

	struct Ship {
		int x, y;
		int size;
		int rot;//rotation in degrees, ex: 0, 90, 180, 270
	};

	const int num_ships = 2;
	const int dimension = 10;
	enum Field { Empty = 0, Occupied, Size };
	const char field_symbol[Field::Size] = { '.', 'O' };

	Ship ships[num_ships] = { {3, 5, 2, 0}, {0, 1, 2, 0} };
	Field fields[dimension][dimension] = { Empty };

	//check if a ship is not within the board dimensions
	for (int index = 0; index < num_ships; ++index) {
		int global_x = (::cos(ships[index].rot * pi / 180.0) * ships[index].size) + ships[index].x;
		int global_y = (::sin(ships[index].rot * pi / 180.0) * ships[index].size) + ships[index].y;

		bool valid = (global_x >= 0 && global_x < dimension) && (global_y >= 0 && global_y < dimension);
		if (!valid) {
			std::cout << "A ship is not within the board dimensions." << std::endl;
			return 1;
		}
	}

	//check if a ship is colliding with another ship
	for (int index = 0; index < num_ships; ++index) {
		for (int segment = 0; segment < ships[index].size; ++segment) {
			int current_x = (::cos(ships[index].rot * pi / 180.0) * segment) + ships[index].x;
			int current_y = (::sin(ships[index].rot * pi / 180.0) * segment) + ships[index].y;

			if (fields[current_x][current_y] == Empty) {
				fields[current_x][current_y] = Occupied;
			}
			else {
				std::cout << "A ship is colliding with another ship." << std::endl;
				return 1;
			}
		}
	}

	//print the board
	for (int y = 0; y < dimension; ++y) {
		for (int x = 0; x < dimension; ++x) {
			std::cout << field_symbol[fields[x][y]] << " ";
		}
		std::cout << "\n";
	}

	return 0;
}


Post the code you currently have and I can help nudge you in the right direction.
Last edited on
Topic archived. No new replies allowed.