Develop a C++ program to play a text-based, computerized-version of BATTLESHIP™
ID: 3763507 • Letter: D
Question
Develop a C++ program to play a text-based, computerized-version of BATTLESHIP™ using an instructor-provided library (battleship.o) and header file (battleship.h). I am given this as the main function:
#include "battleship.h"
int main() {
// variable declarations (you'll need others, of course)
bool done = false;
string move;
// Welcome the player to the game
welcome();
pauseForEnter();
// Initialize the game boards
initializeBoard()
// Play the game until one player has sunk the other's ships
while(!done) {
// Clear the screen to prepare show the game situation before the moves
clearTheScreen();
// Display the game board situation
// Get and validate the human player's move
// BTW, in the following while loop (and the if statements also), I have
// put a "0" in with the comments. This is because in order for the
// code to compile, you need to have something in between the parentheses
while(0/* need to make sure that the human player's move is valid*/) {
;
}
// Get and validate the computer's move
while(0/* need to make sure that the computer's move is valid*/) {
;
}
// Execute both moves
// Clear the screen to show the new game situation after the moves
// Display the new game board situation
// Display the move choices each player made
// Show the results of the moves
// Take note if there are any sunken ships
// determine if we have a winner
if(0/* has either player sunk five ships? */) {
// if one of the player's has sunk five ships the game is over
done = true;
} else {
// pause to let the user assess the situation
pauseForEnter();
}
}
// Announce the winner
if(0/* the human was the winner */) {
/* You won!!! */;
} else if (0/* the computer was the winner */) {
/* The computer won :( */;
} else {
/* The game was a tie */;
}
// pause to let the result of the game sink in
return 0;
}
And this is my header file:
// include files for implementing battleship
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <curses.h>
#include <kasbs.h>
using namespace std;
// use these constants to indicate if the player is a human or a computer
// battleship board size is 10x10 grid
const int BOARDSIZE = 10;
// data structure for position
struct Position {
int startRow; // ship's initial row
int startCol; // ship's initial column
int orient; // indicates whether the ship is running across
// or up and down
};
// data structure for ship
struct Ship {
Position pos; // where the ship is on the board
int size; // number of hits required to sink the ship
int hitsToSink; // number of hits remaining before the ship is sunk
char marker; // the ASCII marker used to denote the ship on the
// board
};
// a game board is made up of a 10x10 playing grid and the ships
struct Board {
char grid[BOARDSIZE][BOARDSIZE];
Ship s[6]; // NOTE: the first (zeroth) position is left empty
};
// use these constants for designating to which player we are referring
const int HUMAN = 0;
const int COMPUTER = 1;
// use these constants for deciding whether or not the user gave a proper move
const int VALID_MOVE = 0;
const int ILLEGAL_FORMAT = 1;
const int REUSED_MOVE = 2;
// functions for screen control and I/O
void welcome(bool debug = false, bool pf = false);
void clearTheLine(int x);
void clearTheScreen(void);
void pauseForEnter(void);
string getResponse(int x, int y, string prompt);
void writeMessage(int x, int y, string message);
void writeResult(int x, int y, int result, int playerType);
void displayBoard(int x, int y, int playerType, const Board &gameBoard);
// functions to control the board situation
void initializeBoard(Board &gameBoard, bool file = false);
int playMove(int row, int col, Board &gameBoard);
// function to tell what happened in the last play_move() command
bool isAMiss(int playMoveResult);
bool isAHit (int playMoveResult);
bool isASunk(int playMoveResult); // formerly named isItSunk()
int isShip (int playMoveResult);
// misc game functions
string randomMove(void);
int checkMove(string move, const Board &gameBoard, int &row, int &col);
void debug(string s, int x = 22, int y = 1);
string numToString(int x);
#ifdef BATTLESHIP_BACKWARD_COMPATIBILITY
// former function signatures
void debug(int x, int y, string s);
bool isItSunk(int playMoveResult);
// a debug macro
#ifdef DEBUG
#define DEBUGOUT(str) debug (22, 1, (str));
#else
#define DEBUGOUT(str)
#endif // DEBUG
#endif // BATTLESHIP_BACKWARD_COMPATABILITY
#endif // BATTLESHIP_H
Explanation / Answer
Discussion: To become familiar with the game you need to develop, you can play it a few times at /home/shomperk/CS1210/public/battle. I suggest you do this before trying to write the program.
After playing the game a time or two, take a look at the file battleship_main.cpp in /home/shomperk/CS1210/public. I have provided you this file to get you started, so copy it to the directory where you usually write your programs. By the way, you’ll also want to copy battleship.h and battleship.o. Notice that the file battleship_main.cpp has comments to give you the general idea on what order you need to do things for the game. Use those comments and the descriptions for the functions below, to figure out how to use the functions to build the main program for the game.
The functions available to you are listed in the header file battleship.h (and also below). They are:
•void welcome(): This function clears the screen and writes the message “Welcome to BATTLESHIP” to the screen several times. Example: welcome();
•void clearTheLine(int x): This function erases all characters on line x, where x is the line number, usually between 0 and 23. Example: clearTheLine(5);
•void clearTheScreen(): This function erases all the characters on your terminal screen leaving you with a blank screen. Example: clearTheScreen();
•void pauseForEnter(): This function writes the message “Press enter to continue” on line 23 and waits for you to just that (actually, it’ll let you proceed after typing any character). Example: pauseForEnter();
•string getResponse(int x, int y, string prompt): This function lets you write a user prompt, prompt, to the user beginning at line x and column y, and then get the user’s response as a string value. Use this function to get the human player’s move. Example: userMove = getResponse(16, 0, “Please enter your move”);
•void writeMessage(int x, int y, string message): This function lets you write message to the screen at line x, column y. Use this function to give feedback on the game. Example: writeMessage(18, 0, “The move you just typed is invalid”);
•void initializeBoard(Board &gameBoard): This function creates a new game board. Note: this function uses a new variable type called Board that you’ve not seen yet. This variable keeps track of each player’s game situation. You will need two of these variables, one for the human and one for the computer. You can declare a Board variable like any other variable (e.g., Board computerBoard;). Example: initializeBoard(computerBoard);
•void displayBoard(int x, int y, int playerType, Board gameBoard): Assuming you have declared and initialized a Board variable, displayBoard() will show it’s current configuration. The parameter playerType is either the constant HUMAN or COMPUTER to let the function know whose board is being displayed. The parameters x and y give the upper left row and column position of the board. Example: displayBoard(1, 1, HUMAN, humanBoard);
•int checkMove(string move, Board gameBoard, ,int &row, int &col): This function validates a player’s move. If the move is acceptable, it returns the constant VALID_MOVE and the variables row and col can be used in the call to playMove(). If the move string is badly formed (e.g., the user typed “10 A” instead of “A 10”) or move has already been used, then checkMove() returns the constants ILLEGAL_FORMAT or REUSED_MOVE, respectively. In this case, row and col contain the unusable values -1 and -1, respectively. Note: you need to keep checking the move (and asking for a new one, if necessary) until you get a valid move. Example: result = checkMove(move, humanBoard, row, col);
•int playMove(int row, int col, Board &gameBoard): This function is how you execute a move. Row and col are the move you want to make (you got these from checkMove()) and gameBoard is the board on which you want to make the move. Your program should call playMove() after using checkMove() to make sure the user (or computer) picked a valid move and set row and col to valid numbers. Example: result = playMove(row, col, humanBoard);
•void writeResult(int x, int y, int result, int playerType): This function uses the value returned from playMove() and writes a text message on line x, column y telling you whether the last move was a “hit” or a “miss” (and if the result was a “hit”, what ship was hit). The parameter playerType is either the constant HUMAN or COMPUTER to let the function know who made the move. Example: Suppose your program had the code: result = playMove(row, col, humanBoard);. You then take the variable result and pass it to writeResult() to report the outcome of the move, e.g., writeResult(20, 0, result, COMPUTER);
•bool isItSunk(int result): This function returns a true or false indicating whether or not the last playMove() sunk a ship. Example: Suppose your program had the code: result = playMove(row, col, humanBoard);. You then take the variable result and pass it to isItSunk() to report to the user the outcome of the move, e.g., if (isItSunk(result)) { /* do something */ };
•string randomMove(): This function allows the computer to pick a random move. Note the computer’s move must be validated, because it may pick a move that’s already been used. Example: computerMove = randomMove();
Hints:
a.Solve this problem step-by-step by implementing the directions provided by each comment in battleship_main.cpp one comment at a time. This way you can learn what each function does little-by-little.
b.You will need to use a while statement to validate the move for both the computer and the user (these while statements, but not their bodies, are provided for you).
c.The while statement for the overall game is also already provided for you. You just need to figure out how we know when we’re done. The comment in the if statement (within the while loop) which I’ve provided gives you a major clue. Also, you’ll need to declare two variables to keep track of how many ships the user and computer have sunk.
import java.util.Random;
import java.util.Scanner;
public class battleShip {
public static void main(String[] args) {
int[][] board = new int[5][5];
int[][] ships = new int[3][2];
int[] shoot = new int[2];
int attempts=0,
shotHit=0;
initBoard(board);
initShips(ships);
System.out.println();
do{
showBoard(board);
shoot(shoot);
attempts++;
if(hit(shoot,ships)){
hint(shoot,ships,attempts);
shotHit++;
}
else
hint(shoot,ships,attempts);
changeboard(shoot,ships,board);
}while(shotHit!=3);
System.out.println(" Battleship Java game finished! You hit 3 ships in "+attempts+" attempts");
showBoard(board);
}
public static void initBoard(int[][] board){
for(int row=0 ; row < 5 ; row++ )
for(int column=0 ; column < 5 ; column++ )
board[row][column]=-1;
}
public static void showBoard(int[][] board){
System.out.println(" 1 2 3 4 5");
System.out.println();
for(int row=0 ; row < 5 ; row++ ){
System.out.print((row+1)+"");
for(int column=0 ; column < 5 ; column++ ){
if(board[row][column]==-1){
System.out.print(" "+"~");
}else if(board[row][column]==0){
System.out.print(" "+"*");
}else if(board[row][column]==1){
System.out.print(" "+"X");
}
}
System.out.println();
}
}
public static void initShips(int[][] ships){
Random random = new Random();
for(int ship=0 ; ship < 3 ; ship++){
ships[ship][0]=random.nextInt(5);
ships[ship][1]=random.nextInt(5);
//let's check if that shot was already tried
//if it was, just finish the do...while when a new pair was randomly selected
for(int last=0 ; last < ship ; last++){
if( (ships[ship][0] == ships[last][0])&&(ships[ship][1] == ships[last][1]) )
do{
ships[ship][0]=random.nextInt(5);
ships[ship][1]=random.nextInt(5);
}while( (ships[ship][0] == ships[last][0])&&(ships[ship][1] == ships[last][1]) );
}
}
}
public static void shoot(int[] shoot){
Scanner input = new Scanner(System.in);
System.out.print("Row: ");
shoot[0] = input.nextInt();
shoot[0]--;
System.out.print("Column: ");
shoot[1] = input.nextInt();
shoot[1]--;
}
public static boolean hit(int[] shoot, int[][] ships){
for(int ship=0 ; ship<ships.length ; ship++){
if( shoot[0]==ships[ship][0] && shoot[1]==ships[ship][1]){
System.out.printf("You hit a ship located in (%d,%d) ",shoot[0]+1,shoot[1]+1);
return true;
}
}
return false;
}
public static void hint(int[] shoot, int[][] ships, int attempt){
int row=0,
column=0;
for(int line=0 ; line < ships.length ; line++){
if(ships[line][0]==shoot[0])
row++;
if(ships[line][1]==shoot[1])
column++;
}
System.out.printf(" Hint %d: Row %d -> %d ships " +
"Column %d -> %d ships ",attempt,shoot[0]+1,row,shoot[1]+1,column);
}
public static void changeboard(int[] shoot, int[][] ships, int[][] board){
if(hit(shoot,ships))
board[shoot[0]][shoot[1]]=1;
else
board[shoot[0]][shoot[1]]=0;
}
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.