• Do not use Fstream and Fget in the questions.
• Late submission of your solution is not allowed.
• You are not allowed to copy solutions from other students. We will check your code for plagiarism
using plagiarism checkers. If any sort of cheating is found, heavy penalties will be given to all
students involved.
• Submit the code files. Do not submit Zip files.

Question 1 : BattleShip Game [50 marks]
Design a Battleship game in C++ using pipes, where two players (Player 1 and Player 2) play against each other on
a 5x5 grid. The game will be played between two separate processes, and all communication between the players
will happen through pipes. Each player controls a fleet of 3 ships, and the goal is to sink the opponent’s ships by
guessing their positions.
Requirements:
1. Game Board:
o Each player has a 5x5 grid, where each space can either be empty or occupied by a ship.
o Each player controls 3 ships placed at the start of the game. The ship sizes are fixed: 2, 3, and 4
spaces long, and can be placed either horizontally or vertically on the grid.
o Players place their ships on their grid before the game starts, with proper validation to avoid
overlapping ships.
2. Pipes for Communication:
o The game will use two pipes for communication between Player 1 and Player 2 processes.
▪ Pipe 1: Used for Player 1 to send their guesses to Player 2.
▪ Pipe 2: Used for Player 2 to send their guesses to Player 1.

o Players will also communicate their responses (hit or miss) using the same pipes, ensuring a turn-
based gameplay loop.

o Players must wait for the other player's guess and response before proceeding with their own turn.
3. Turn-Based Gameplay:
o Players take turns guessing the opponent’s ship positions by sending (row, col) coordinates through
the pipe.
o After a guess, the opponent responds with either:
▪ H (Hit) if a ship is hit.
▪ M (Miss) if the guess misses the ships.
o The response is sent back through the same pipe.
4. Game Termination:
o The game ends when one player successfully sinks all 3 of the opponent’s ships.
o Each ship requires multiple hits to sink, based on its size (e.g., a ship of size 3 requires 3 hits to
sink).
o Once a player sinks all the opponent’s ships, the game declares the winner and both processes
terminate gracefully.

Game Flow:
• Player 1 Process:
1. Place Ships: Before the game starts, Player 1 places their ships on a private 5x5 grid.
2. Send Guess: Player 1 sends a guess (row, col) to Player 2 through Pipe 1.
3. Receive Response: Player 1 waits for Player 2’s response (Hit/Miss) through Pipe 1.
4. If all of Player 2’s ships are hit, Player 1 wins, and the game ends.
5. If Player 1 does not win, control is passed to Player 2.
• Player 2 Process:
1. Place Ships: Player 2 places their ships on their private 5x5 grid.
2. Receive Guess: Player 2 receives Player 1’s guess (row, col) through Pipe 1.
3. Check Hit or Miss: Player 2 checks if Player 1’s guess hits or misses a ship on their grid and sends
the response (Hit/Miss) back to Player 1 through Pipe 1.
4. Send Guess: Player 2 then sends a guess (row, col) to Player 1 through Pipe 2.
5. Receive Response: Player 2 waits for Player 1’s response (Hit/Miss) through Pipe 2.
6. If all of Player 1’s ships are hit, Player 2 wins, and the game ends.
7. If Player 2 does not win, control is passed back to Player 1.

Synchronization:
• The pipes are used for communication, ensuring that only one player can make a move at a time.
• The guessing process is synchronized using the turn-based system, where a player sends their guess and
waits for the opponent’s response before taking their next turn.
• There should be proper synchronization to ensure that one player cannot make multiple guesses in a row
without waiting for the other player's move.
Pipes Error Handling:
• Implement error handling for the pipes to ensure proper communication. If there’s a failure to send or
receive data through the pipes, the game should handle this scenario gracefully.  #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <sys/wait.h>

#define GRID_SIZE 5
#define NUM_SHIPS 3
#define MAX_BUFFER 256

typedef struct {
    int size;
    int hits;
} Ship;

typedef struct {
    char grid[GRID_SIZE][GRID_SIZE];
    Ship ships[NUM_SHIPS];
} Player;

void initializePlayer(Player *player) {
    for (int i = 0; i < GRID_SIZE; i++) {
        for (int j = 0; j < GRID_SIZE; j++) {
            player->grid[i][j] = '.';
        }
    }
    player->ships[0] = (Ship){2, 0};
    player->ships[1] = (Ship){3, 0};
    player->ships[2] = (Ship){4, 0};
}

int canPlaceShip(Player *player, int row, int col, int size, int horizontal) {
    if (horizontal) {
        if (col + size > GRID_SIZE) return 0;
        for (int i = 0; i < size; i++) {
            if (player->grid[row][col + i] != '.') return 0;
        }
    } else {
        if (row + size > GRID_SIZE) return 0;
        for (int i = 0; i < size; i++) {
            if (player->grid[row + i][col] != '.') return 0;
        }
    }
    return 1;
}

void placeShip(Player *player, int row, int col, int size, int horizontal) {
    if (horizontal) {
        for (int i = 0; i < size; i++) {
            player->grid[row][col + i] = 'S';
        }
    } else {
        for (int i = 0; i < size; i++) {
            player->grid[row + i][col] = 'S';
        }
    }
}

void placeShipsRandomly(Player *player) {
    for (int i = 0; i < NUM_SHIPS; i++) {
        int placed = 0;
        while (!placed) {
            int row = rand() % GRID_SIZE;
            int col = rand() % GRID_SIZE;
            int horizontal = rand() % 2;
            if (canPlaceShip(player, row, col, player->ships[i].size, horizontal)) {
                placeShip(player, row, col, player->ships[i].size, horizontal);
                placed = 1;
            }
        }
    }
}

char checkGuess(Player *player, int row, int col) {
    if (player->grid[row][col] == 'S') {
        player->grid[row][col] = 'H';
        return 'H';
    }
    return 'M';
}

int allShipsSunk(Player *player) {
    for (int i = 0; i < GRID_SIZE; i++) {
        for (int j = 0; j < GRID_SIZE; j++) {
            if (player->grid[i][j] == 'S') return 0;
        }
    }
    return 1;
}

void playerProcess(int read_fd, int write_fd, int player_num) {
    Player player;
    char buffer[MAX_BUFFER];
    int row, col;

    srand(time(NULL) + player_num);
    initializePlayer(&player);
    placeShipsRandomly(&player);

    while (1) {
        if (player_num == 1) {
            // Player 1's turn
            printf("Player 1, enter your guess (row col): ");
            scanf("%d %d", &row, &col);
            sprintf(buffer, "%d %d", row, col);
            write(write_fd, buffer, strlen(buffer) + 1);

            read(read_fd, buffer, MAX_BUFFER);
            printf("Result: %s\n", buffer);

            if (strcmp(buffer, "You win!") == 0) break;
        } else {
            // Player 2's turn
            read(read_fd, buffer, MAX_BUFFER);
            sscanf(buffer, "%d %d", &row, &col);

            char result = checkGuess(&player, row, col);
            if (allShipsSunk(&player)) {
                strcpy(buffer, "You win!");
            } else {
                buffer[0] = result;
                buffer[1] = '\0';
            }
            write(write_fd, buffer, strlen(buffer) + 1);

            if (strcmp(buffer, "You win!") == 0) break;

            printf("Player 2, enter your guess (row col): ");
            scanf("%d %d", &row, &col);
            sprintf(buffer, "%d %d", row, col);
            write(write_fd, buffer, strlen(buffer) + 1);

            read(read_fd, buffer, MAX_BUFFER);
            printf("Result: %s\n", buffer);

            if (strcmp(buffer, "You win!") == 0) break;
        }
    }
}

int main() {
    int pipe1[2], pipe2[2];
    pid_t pid;

    if (pipe(pipe1) == -1 || pipe(pipe2) == -1) {
        perror("pipe");
        exit(1);
    }

    pid = fork();
    if (pid == -1) {
        perror("fork");
        exit(1);
    } else if (pid == 0) {
        // Child process (Player 2)
        close(pipe1[1]);
        close(pipe2[0]);
        playerProcess(pipe1[0], pipe2[1], 2);
        close(pipe1[0]);
        close(pipe2[1]);
    } else {
        // Parent process (Player 1)
        close(pipe1[0]);
        close(pipe2[1]);
        playerProcess(pipe2[0], pipe1[1], 1);
        close(pipe2[0]);
        close(pipe1[1]);
        wait(NULL);
    }

    return 0;
} code output wrong iot:~/Desktop/eval$ ./a.out
Player 1, enter your guess (row col): 1
2
Result: M
Player 1, enter your guess (row col): Player 2, enter your guess (row col): 1 2
2
1
Result: 1 2
Result: 2 1
Player 1, enter your guess (row col): 1
2
Player 2, enter your guess (row col): Result: M
Player 1, enter your guess (row col): 1
1
1
2
Result: 1 1
Result: 1 2
Player 1, enter your guess (row col): 2
2
Player 2, enter your guess (row col): Result: H
Player 1, enter your guess (row col):