Submarine

How would I edit my code so that a board is printed after each coordinate is guessed, that doesn't show the position of the ships, but shows where the user enter his guess with an S.

0123456789
0.......... 0
1...5...... 1
21..4..#... 2
3S..#...... 3
4.......... 4
5.S........ 5
6......S... 6
7.......... 7
8.......... 8
9.......... 9
0123456789
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
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
const int FLEET_SIZE=5; // number of battleships
const int FIELD_SIZE=10;  // the field (ocean) is FIELD_SIZExFIELD_SIZE

// coordinates (location) of the ship and shots
struct location{
    int x;  // 1 through FIELD_SIZE
    char y; // 'a' through FIELD_SIZE
};

// contains ship's coordinates (location) and whether is was sunk
struct ship{
    location loc;
    bool sunk;
};

//
// initialization functions
//
void initialize(ship[]); // places all ships in -1 X location to signify
// that the ship is not deployed
location pick(void); // generates a random location
bool match(ship, location); // returns true if this location matches
// the location of the ship
// returns false otherwise
int check(const ship[], location); // returns the index of the element
// of the ship[] array that matches
// location. Returns -1 if none match
// uses match()
void deploy(ship[]); // places an array of battleships in
// random locations in the ocean

//
// display functions
//
void printShip(ship); // prints the location and status (sunk or not)
// of a single ship
void printFleet(const ship[]); // prints the locations of all the ships and
// whether they are sunk


//
// battle functions
//
bool operational(const ship[]);  // returns true if at least one ship in the array
// is not sunk
location fire(void);       // asks the user to input the coordinates of the next
// shot
// note that check() is also used in the battle

void sink(ship&);
int main(){
    
    srand(((unsigned)time(0)));
    ship s[FLEET_SIZE]; // enemy ship structure with 5 elements
    initialize(s); // run initialize function with structure s
    deploy(s); // run deploy function with structure s
    char shipLoc; // user input for ship status display
    ship user; // users fire guess
    cout << "WELCOME TO BATTLESHIP\n"
    << "_____________________\n\n"
    << " -Sink enemy ships-\n\n\n";
    cout << "You have the option to view the status of the ships or go straight to the game.\n\n";
    
    while(operational(s)){ // run this while there is at least one standing ship
        cout << "Enter the r and c coordinates (separated by a space) to hit: ";
  
            user.loc=fire();
            int c = check(s, user.loc);
            if (c!=-1){
                sink(s[c]);
                cout << "HIT! Ship sunk.\n\n";
            }
            else
                cout << "Sorry you missed, try again.\n\n";
        }
        
    
    cout << "\nCongratulations! You have sunk all enemy ships.\n\n";
}

void initialize(ship s[]){ // sets all ships in -1 to show it is not deployed
    for(int i=0; i<FLEET_SIZE; i++)
        s[i].loc.x = -1;
}

void deploy(ship s[]){
    int i=0; // Number of ships so far
    
    while (i<FLEET_SIZE){
        location temp = pick(); // sets random location in temp variable
        int e = check(s, temp); // -1 if there is a match, otherwise holds the element of the ship
        if (e==-1){
            s[i].loc = temp; // gives random location to the ship
            s[i].sunk=false; // makes the ship up
            i++;
        }
    }
    
}

location pick(void){ // picks a random location
    location loc;
    loc.x=rand()%FIELD_SIZE;
    loc.y=rand()%FIELD_SIZE;
   
    return loc;
}

int check(const ship s[], location loc)
{
    for(int i=0; i<FLEET_SIZE; i++)
        if (match(s[i], loc)) // if true, return the index, if not return -1
            return i;
    return -1;
}

bool match(ship s, location l)
{
    if ((s.loc.x == l.x) && (s.loc.y == l.y)) // if both member variables match, return true
        return true;
    else
        return false;
}

bool operational(const ship s[]){
    for(int i=0; i<FLEET_SIZE; i++)
        if (s[i].sunk == false) // if there is at least one operational ship, return true
            return true;
    return false;
    
}

void printShip(ship s){
    cout << s.loc.y << s.loc.x << ' ';
    if(s.sunk == true)
        cout << "sunk  ";
    else if (s.sunk == false)
        cout << "up  ";
}

void printFleet(const ship s[]){
    for(int i=0; i<FLEET_SIZE; i++){
        printShip(s[i]);
    }
    cout << endl;
}

location fire(void){
    location temp; // temp variable for users guess
    cout << "\nWhere would you like to fire a shot?\n"
    << "Y-Coordinate <0-9>: ";
    cin >> temp.y;
    cout << "X-Coordinate <0-9>: ";
    cin >> temp.x;
    cout << endl;
    return temp; // returns temps locations
}

void sink(ship& s){
    s.sunk=true; // sinks the ship
}
Last edited on
I suggest to make two arrays. One with the ships and the other for the user.
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
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
187
188
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <limits>
#include <vector>

// coordinates (location) of the ship and shots
struct location {
    int x;                          // 1 through FIELD_SIZE
    int y;                         // 'a' through FIELD_SIZE
    location(int x_arg = -1, int y_arg = -1) : x { x_arg }, y { y_arg } {}
};

// contains ship's coordinates (location) and whether is was sunk
struct ship {
    location loc;
    bool sunk;
};

struct Board {
    std::vector<std::vector<int>> board;
    int sinked { '#' },
        guess  { 'S' };
    explicit Board(int val);
    friend std::ostream& operator<<(std::ostream& os, const Board& myb)
    {
        os << "  0 1 2 3 4 5 6 7 8 9\n";
        int seq {};
        for(const auto& a : myb.board) {
            os << seq++;
            for(const auto i : a) { os << ' ' << static_cast<char>(i); }
            os << '\n';
        }
        return os;
    }
};

Board::Board(int val)
{
    board.resize(val, std::vector<int>(val, ' '));
}


// initialization functions
void initialise(ship[], const int);
location pick(const int);
bool match(const ship&, const location&);
int check(const ship[], const int, const location&);
void deploy(ship[], const int, const int);

// display functions
void printShip(ship);
void printFleet(const ship[], const int);

// battle functions
bool operational(const ship[], const int);
location fire(int);
void sink(ship&);

void waitForEnter();

int main()
{
    std::srand(((unsigned)time(0)));
    constexpr int FLEET_SIZE =  5;      // number of battleships
    constexpr int FIELD_SIZE = 10;      // the field (ocean) is FIELD_SIZE x FIELD_SIZE
    ship s[FLEET_SIZE];                 // enemy ship structure with 5 elements
    initialise(s, FLEET_SIZE);
    deploy(s, FLEET_SIZE, FIELD_SIZE);
    ship user;                      // users fire guess
    Board myb(FIELD_SIZE);
    std::cout << "WELCOME TO BATTLESHIP\n"
                 "_____________________\n\n"
                 " -Sink enemy ships-\n\n\n"
                 "You have the option to view the status of the ships or go "
                 "straight to the game.\n\n";

    // run this while there is at least one standing ship
    while(operational(s, FLEET_SIZE)) {
        user.loc = fire(FIELD_SIZE);
        int c = check(s, FLEET_SIZE, user.loc);
        if (c != -1) {
            sink(s[c]);
            std::cout << "HIT! Ship sunk.\n\n";
            myb.board.at(user.loc.y).at(user.loc.x) = myb.sinked;
        } else {
            std::cout << "Sorry you missed, try again.\n\n";
            myb.board.at(user.loc.y).at(user.loc.x) = myb.guess;
        }
        std::cout << myb << '\n';
    }

    std::cout << "\nCongratulations! You have sunk all enemy ships.\n\n";
    waitForEnter();
}

// places all ships in -1 X location to signify that the ship is not deployed
void initialise(ship s[], const int size)
{
    for(int i=0; i<size; i++) { s[i].loc.x = -1; }
}

// places an array of battleships in random locations in the ocean
void deploy(ship s[], const int fsize, const int osize)
{
    for(int i = 0; i<fsize; ++i) {
        location temp = pick(osize);
        int e = check(s, fsize, temp);
        if (e == -1) {
            s[i].loc = temp;
            s[i].sunk = false;
        }
    }
}

// generates a random location
location pick(int size) { return { rand() % size, rand() % size }; }

// returns the index of the element of the ship[] array that matches location.
// Returns -1 if none match
int check(const ship s[], const int size, const location& loc)
{
    // if true, return the index, if not return -1
    for(int i=0; i < size; ++i) {
        if (match(s[i], loc)) { return i; }
    }
    return -1;
}

// returns true if this location matches the location of the ship
// returns false otherwise
bool match(const ship& s, const location& l)
{
    // if both member variables match, return true
    if ((s.loc.x == l.x) && (s.loc.y == l.y)) { return true; }
    else                                      { return false; }
}

// returns true if at least one ship in the array is not sunk
bool operational(const ship s[], const int size)
{
    for(int i = 0; i < size; ++i) {
        if (s[i].sunk == false) { return true; }
    }
    return false;
}

// prints the location and status (sunk or not) of a single ship
void printShip(ship s)
{
    std::cout << s.loc.y << s.loc.x << ' ';
    if(s.sunk == true)        { std::cout << "sunk  "; }
    else if (s.sunk == false) { std::cout << "up  "; }
}

// prints the locations of all the ships and whether they are sunk
void printFleet(const ship s[], const int size)
{
    for(int i = 0; i < size; ++i) {
        printShip(s[i]);
    }
    std::cout << '\n';
}

// asks the user to input the coordinates of the next shot
location fire(int max)
{
    location temp;
    do {
        std::cout << "\nWhere would you like to fire a shot?\n"
                     "Y-Coordinate <0-9>: ";
        std::cin >> temp.y;
        std::cout << "X-Coordinate <0-9>: ";
        std::cin >> temp.x;
        std::cout << '\n';
    } while(    temp.x < 0 || max <= temp.x
             || temp.y < 0 || max <= temp.y );
    return temp;
}

// sinks the ship
void sink(ship& s) { s.sunk = true; }

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

Output:
WELCOME TO BATTLESHIP
_____________________

 -Sink enemy ships-


You have the option to view the status of the ships or go straight to the game.


Where would you like to fire a shot?
Y-Coordinate <0-9>: 5
X-Coordinate <0-9>: 4

HIT! Ship sunk.

  0 1 2 3 4 5 6 7 8 9
0
1
2
3
4
5         #
6
7
8
9


Where would you like to fire a shot?
Y-Coordinate <0-9>: 6
X-Coordinate <0-9>: 3

Sorry you missed, try again.

  0 1 2 3 4 5 6 7 8 9
0
1
2
3
4
5         #
6       S
7
8
9


Where would you like to fire a shot?
Y-Coordinate <0-9>:


Note: your code is becoming hard to manage without classes.
The S is supposed to show where the five submarines are already located, and the # will signify hitting the ship(Which is correct). I just want to know how to put the 5 submarines left on the board.
Last edited on
How would I edit my code so that a board is printed after each coordinate is guessed, that doesn't show the position of the ships, but shows where the user enter his guess with an S.
The S is supposed to show where the five submarines are already located, and the # will signify hitting the ship(Which is correct). I just want to know how to put the 5 submarines left on the board.

Sorry, could you please elaborate a little more what you aim to do?
Are there submarines... left? Are 'submarines' and 'ships' different things in your project?
Should submarines "come to light" with an S after the first shot from the user?
Sorry there are no ships only submarines. There are supposed to be five submarines in the field, and I just want to show their positions at all times. This is so my professor can see the placement of the submarines.
Hello cash,

I think you should post the link to the assignment instructions so everyone will know what is need.

This way they would know what "DE_BUG" is for and how it is used. Which you do not have along with the 2Darray that is needed.

Andy
Can anyone help how to incorporate a 2d array in the program.
Hello cash,

This may not fix what yu have, but as I understand the assignment it should help you get started.

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
#include <iostream>
#include <iomanip>
#include <vector>
#include <ctime>  // <--- OK, but not sure what it is needed for right now.
#include <cstdlib>  //  <--- May not be needed.

//  Constants for the program.
constexpr std::size_t MAXOCEANSIZE{ 10 };
constexpr bool DE_BUG{ true };  // <--- Change to "false" for normal run.
//constexpr bool DE_BUG{ false };  // <--- Used for testing.

// coordinates (location) of the ship and shots
struct Location
{
	std::size_t x{};  // 1 through 9
	std::size_t y{};  // 1 through 9
};

// contains ship's coordinates (location) and whether is was sunk
struct Ship
{
	Location loc;
	std::size_t distance{};  // Distance to nearest sub. May not be needed.
	bool sunk{ false };
};

void Printocean(int(&ocean)[MAXOCEANSIZE][MAXOCEANSIZE]);  //  Used for testing.
//void Printocean(Ship ocean[][MAXOCEANSIZE]); //  For normal use.

void InitOcean(int ocean[][MAXOCEANSIZE]);

int main()
{

	// A 2D array for the ocean ocean.
	int ocean[MAXOCEANSIZE][MAXOCEANSIZE];

	std::vector<Ship> sub_list(5);
	std::vector<Location> drop_list;

	InitOcean(ocean);

	//  Comment or remove these lines when not needed.
	ocean[2][4] = static_cast<int> ('S');  // Used for testing.
	ocean[3][0] = static_cast<int> ('#');  // Used for testing.
	ocean[6][5] = static_cast<int> ('S');  // Used for testing.
	ocean[9][8] = static_cast<int> ('S');  // Used for testing.

	Printocean(ocean);

	std::cout << std::endl;

	return 0;
}  // End main

void Printocean(int(&ocean)[MAXOCEANSIZE][MAXOCEANSIZE])  //  Used for testing.
//void Printocean(Ship ocean[][MAXOCEANSIZE])  // For normal use.
{
	std::string row{ "   ROW     " };
	std::cout << std::setw(16) << " " << "Column";
	std::cout << "\n      1  2  3  4  5  6  7  8  9  10" << std::endl;

	for (size_t lco = 0; lco < MAXOCEANSIZE; lco++)
	{
		std::cout << ' ' << row[lco] << std::setw(2) << lco + 1 << " ";

		for (size_t lc = 0; lc < MAXOCEANSIZE; lc++)
		{
			if (DE_BUG && ocean[lco][lc] == 'S')
				std::cout << ' ' << static_cast<char> (ocean[lco][lc]) << ' ';
			else if (!DE_BUG && ocean[lco][lc] == 'S')
				std::cout << ' ' << '.' << ' ';
			else
				std::cout << ' ' << static_cast<char> (ocean[lco][lc]) << ' ';
		}

		std::cout << std::endl;
	}
}

// Plaes a peroid in each element.
void InitOcean(int ocean[][MAXOCEANSIZE])
{
	for (size_t lco = 0; lco < MAXOCEANSIZE; lco++)
	{
		for (size_t lci = 0; lci < MAXOCEANSIZE; lci++)
		{
			ocean[lco][lci] = static_cast<int>('.');
		}
	}
}


You have missed so many parts of the instruction with your code it may be easier to start over and use part of what you have written in the new version.

Hope that helps,

Andy
Registered users can post here. Sign in or register to post.