Single Player Console Battleship with Artificial Intelligence
/* | |
Author: John Martin | |
Class: Introduction to C++ | |
Assignment: Final Project | |
Date Assigned: May 7, 2013 | |
Due Date: May 14, 2013 | |
Description: This program uses all concepts learned in the class to create | |
a single player battleship game with an Artificial Intelligence. | |
Certification of Authenticity: | |
I certify that this assignment is entirely my own work. | |
*/ | |
#include <iostream> | |
#include <string> | |
#include <time.h> | |
using namespace std; | |
bool canFire(int, int, int); | |
void updateMap(); | |
string fire(int, int, int); | |
void displayGame(); | |
void displayPlayerBoard(); | |
void populatePlayerBoard(); | |
void populateComputerBoard(); | |
string computerMove(); | |
bool placeShip(int, int, int, int, bool); | |
void updateScore(); | |
//Declaration of global variables | |
//KEY FOR BOARD: | |
const string EMPTY = " "; | |
const string SHIP = "H"; | |
const string HIT = "X"; | |
const string MISS = "O"; | |
string board1[10][10] = {{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}}, | |
board2[10][10] = {{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}}, | |
map[10][10] = {{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}, | |
{EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY}}; | |
int turn = 0, playerHits = 0, computerHits = 0; //scoring | |
int currentPlayerPiece = 0, targeting = -1; //AI processing | |
int patrolBoat[2][2], destroyer[3][2], submarine[3][2], battleship[4][2], aircraftCarrier[5][2]; | |
bool activeTargeting = false; | |
int main() | |
{ | |
int row, column; | |
string fired; | |
//Opening sequences | |
cout << "Welcome to John Martin's amazing BATTLE SHIP BOARD GAME!!\n" | |
<< "This is a standard game of BATTLE SHIP, but against an Aritifical Intelligence.\n\n" | |
<< "You will need to know the piece values:\n" | |
<< "SHIP = H\nHIT = X\nMISS = O\n\n" | |
<< "Now you can assign your ships to the board..."; | |
populatePlayerBoard(); | |
cout << "\nPlease wait while computer board is populated...\n"; | |
populateComputerBoard(); | |
for(int i = 0; i < 4; i++) | |
{ | |
cout << battleship[i][0] << battleship[i][1]; | |
} | |
cout << "\n\n\n\n\n OKAY, WE'RE READY TO PLAY!\nENTER YOUR FIRE COORDINATES WHEN PROMPTED\n\n"; | |
//Game loop to continue until one player has 17 hits (all ships sunk) | |
while(playerHits < 17 && computerHits < 17) | |
{ | |
displayGame(); //1 Display the game | |
do{ //2 Ask for coordinates until can fire | |
cout << "It's your turn to fire!\nRow: "; | |
cin >> row; | |
cout << "Column: "; | |
cin >> column; | |
row = row - 1; | |
column = column - 1; | |
} | |
while(!canFire(2, row, column)); | |
fired = fire(2, row, column); //3 Player fire | |
if(fired == SHIP) //4 Inform player of his or her result | |
cout << "Player: HIT!!"; | |
else | |
cout << "Player: MISS"; | |
cout << "Computer: " << computerMove(); //5 Command computer to fire & print result | |
updateScore(); //6 Update score and count for next turn | |
turn++; | |
} | |
return 0; | |
} | |
//This function returns true if the target space on the target board is either | |
//EMPTY or SHIP, otherwise returns false. | |
bool canFire(int fireAt, int row, int column) | |
{ | |
if(fireAt == 2){ | |
if(board2[row][column] == EMPTY || board2[row][column] == SHIP) | |
return true; | |
else | |
return false; | |
} | |
else{ | |
if(board1[row][column] == EMPTY || board1[row][column] == SHIP) | |
return true; | |
else | |
return false; | |
} | |
} | |
//This function updates the player's map based on the computer's board. | |
void updateMap() | |
{ | |
for(int r = 0; r < 10; r++) | |
{ | |
for(int c = 0; c < 10; c++) | |
{ | |
if(board2[r][c] == HIT) | |
map[r][c] = HIT; | |
else if(board2[r][c] == MISS) | |
map[r][c] = MISS; | |
else; | |
} | |
} | |
} | |
//This function accepts a firing command from either player and returns the value that | |
//was in the space on the board of the other player. Also updates player's map on turn by turn basis. | |
string fire(int fireAt, int row, int column) | |
{ | |
string previousValue; | |
//Instructions for player firing at computer | |
if(fireAt == 2) | |
{ | |
previousValue = board2[row][column]; | |
if(board2[row][column] == EMPTY){ | |
board2[row][column] = MISS; | |
map[row][column] = MISS;} | |
else if(board2[row][column] == SHIP){ | |
board2[row][column] = HIT; | |
map[row][column] = HIT;} | |
else; | |
} | |
//Instructions for computer firing at player | |
else | |
{ | |
previousValue = board1[row][column]; | |
if(board1[row][column] == EMPTY) | |
board1[row][column] = MISS; | |
else if(board1[row][column] == SHIP) | |
board1[row][column] = HIT; | |
else; | |
} | |
return previousValue; | |
} | |
//This function displays the board and map to the player. | |
void displayGame() | |
{ | |
cout << "\n\n\n\nTurn: " << turn << endl; | |
cout << "Player: " << playerHits << "\nComputer: " << computerHits << endl; | |
cout << "===============YOUR MAP=================" << endl; | |
cout << " | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|" << endl; | |
for(int r = 0; r < 10; r++) | |
{ | |
cout << r + 1; | |
if(r != 9) | |
cout << " "; | |
for(int c = 0; c < 10; c++) | |
{ | |
if(c == 0) | |
cout << "| "; | |
else | |
cout << " | "; | |
cout << map[r][c]; | |
} | |
cout << endl; | |
if(r != 9) | |
cout << "-------------------------------------------\n"; | |
} | |
cout << "\n\n\n"; | |
cout << "==============YOUR BOARD================" << endl; | |
cout << " | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|" << endl; | |
for(int r = 0; r < 10; r++) | |
{ | |
cout << r + 1; | |
if(r != 9) | |
cout << " "; | |
for(int c = 0; c < 10; c++) | |
{ | |
if(c == 0) | |
cout << "| "; | |
else | |
cout << " | "; | |
cout << board1[r][c]; | |
} | |
cout << endl; | |
if(r != 9) | |
cout << "-------------------------------------------\n"; | |
} | |
} | |
//This function allows the computer to make it's intelligent move and return result. | |
string computerMove() | |
{ | |
int row, column; | |
activeTargeting = false; | |
string hitOrMiss; | |
//If computer is targeting a damaged ship | |
if(targeting != -1) | |
{ | |
if(targeting = 0){ | |
for(int i = 0; i < 2; i++){ | |
if(board1[patrolBoat[i][0]][patrolBoat[i][1]] == SHIP){ | |
row = patrolBoat[i][0]; | |
column = patrolBoat[i][1]; | |
activeTargeting = true;} | |
} | |
} | |
else if(targeting = 1){ | |
for(int i = 0; i < 3; i++){ | |
if(board1[destroyer[i][0]][destroyer[i][1]] == SHIP){ | |
row = destroyer[i][0]; | |
column = destroyer[i][1]; | |
activeTargeting = true;} | |
} | |
} | |
else if(targeting = 2){ | |
for(int i = 0; i < 3; i++){ | |
if(board1[submarine[i][0]][submarine[i][1]] == SHIP){ | |
row = submarine[i][0]; | |
column = submarine[i][1]; | |
activeTargeting = true;} | |
} | |
} | |
else if(targeting = 3){ | |
for(int i = 0; i < 4; i++){ | |
if(board1[battleship[i][0]][battleship[i][1]] == SHIP){ | |
row = battleship[i][0]; | |
column = battleship[i][1]; | |
activeTargeting = true;} | |
} | |
} | |
else{ | |
for(int i = 0; i < 5; i++){ | |
if(board1[aircraftCarrier[i][0]][aircraftCarrier[i][1]] == SHIP){ | |
row = aircraftCarrier[i][0]; | |
column = aircraftCarrier[i][1]; | |
activeTargeting = true;} | |
} | |
} | |
} | |
//If no intelligent moves, make a random move | |
if(!activeTargeting) | |
{ | |
do{ | |
srand(time(NULL)); | |
row = rand() % 10; | |
srand(rand()/0.97653467896); | |
column = rand() % 10; | |
} | |
while(!canFire(1, row, column)); | |
} | |
//fire | |
string result = fire(1, row, column); | |
if(result == SHIP) | |
{ | |
hitOrMiss = "HIT"; | |
//which ship was hit? | |
for(int i = 0; i < 2; i++){ | |
if(patrolBoat[i][0] == row && patrolBoat[i][1] == column) | |
targeting = 0;} | |
for(int i = 0; i < 3; i++){ | |
if(destroyer[i][0] == row && destroyer[i][1] == column) | |
targeting = 1;} | |
for(int i = 0; i < 3; i++){ | |
if(submarine[i][0] == row && submarine[i][1] == column) | |
targeting = 2;} | |
for(int i = 0; i < 4; i++){ | |
if(battleship[i][0] == row && battleship[i][1] == column) | |
targeting = 3;} | |
for(int i = 0; i < 5; i++){ | |
if(aircraftCarrier[i][0] == row && aircraftCarrier[i][1] == column) | |
targeting = 4;} | |
cout << targeting; | |
} | |
else | |
{ | |
hitOrMiss = "MISS"; | |
targeting = -1; | |
} | |
return hitOrMiss; | |
} | |
//This function displays the players board only; with NO MAP. | |
void displayPlayerBoard() | |
{ | |
cout << " | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|" << endl; | |
for(int r = 0; r < 10; r++) | |
{ | |
cout << r + 1; | |
if(r != 9) | |
cout << " "; | |
for(int c = 0; c < 10; c++) | |
{ | |
if(c == 0) | |
cout << "| "; | |
else | |
cout << " | "; | |
cout << board1[r][c]; | |
} | |
cout << endl; | |
if(r != 9) | |
cout << "-------------------------------------------\n"; | |
} | |
cout << endl << endl; | |
} | |
//This function is run at the start of the game to populate the player's board with ships. | |
void populatePlayerBoard() | |
{ | |
int placement, row, column; | |
bool isVertical = false, isPlaced; | |
cout << "\n\nPLEASE REMEMBER TO PLACE YOUR SHIPS IN ADJACENT HORIZONTAL OR VERTICAL LINES\n" | |
<< "NEVER EXIT THE RANGE OF 1-10 WHEN USING THE COORDINATE SYSTEM!\n" | |
<< "IF THE SYSTEM ASKS YOU FOR THE SAME BOAT INFORMATION AGAIN, YOU CHOSE AN INVALID PLACEMENT\n\n"; | |
//PATROL BOAT | |
cout << "Here is your board for your reference: \n"; | |
displayPlayerBoard(); | |
do{ | |
cout << "First, place your PATROL BOAT (2 spaces).\n" | |
<< "Would you like this placed vertically (1) or horizontally (2)? (Enter '1' or '2'): "; | |
cin >> placement; | |
if(placement == 1) | |
isVertical = true; | |
else | |
isVertical = false; | |
cout << "Row: "; | |
cin >> row; | |
cout << "Column: "; | |
cin >> column; | |
row = row - 1; | |
column = column - 1; | |
isPlaced = placeShip(1, 2, row, column, isVertical); | |
} | |
while(!isPlaced); | |
currentPlayerPiece++; | |
//DESTROYER | |
cout << "Here is your board for your reference: \n"; | |
displayPlayerBoard(); | |
do{ | |
cout << "Place your DESTROYER (3 spaces).\n" | |
<< "Would you like this placed vertically (1) or horizontally (2)? (Enter '1' or '2'): "; | |
cin >> placement; | |
if(placement == 1) | |
isVertical = true; | |
else | |
isVertical = false; | |
cout << "Row: "; | |
cin >> row; | |
cout << "Column: "; | |
cin >> column; | |
row = row - 1; | |
column = column - 1; | |
isPlaced = placeShip(1, 3, row, column, isVertical); | |
} | |
while(!isPlaced); | |
currentPlayerPiece++; | |
//SUBMARINE | |
cout << "Here is your board for your reference: \n"; | |
displayPlayerBoard(); | |
do{ | |
cout << "Place your DESTROYER (3 spaces).\n" | |
<< "Would you like this placed vertically (1) or horizontally (2)? (Enter '1' or '2'): "; | |
cin >> placement; | |
if(placement == 1) | |
isVertical = true; | |
else | |
isVertical = false; | |
cout << "Row: "; | |
cin >> row; | |
cout << "Column: "; | |
cin >> column; | |
row = row - 1; | |
column = column - 1; | |
isPlaced = placeShip(1, 3, row, column, isVertical); | |
} | |
while(!isPlaced); | |
currentPlayerPiece++; | |
//BATTLESHIP | |
cout << "Here is your board for your reference: \n"; | |
displayPlayerBoard(); | |
do{ | |
cout << "Place your BATTLESHIP (4 spaces).\n" | |
<< "Would you like this placed vertically (1) or horizontally (2)? (Enter '1' or '2'): "; | |
cin >> placement; | |
if(placement == 1) | |
isVertical = true; | |
else | |
isVertical = false; | |
cout << "Row: "; | |
cin >> row; | |
cout << "Column: "; | |
cin >> column; | |
row = row - 1; | |
column = column - 1; | |
isPlaced = placeShip(1, 4, row, column, isVertical); | |
} | |
while(!isPlaced); | |
currentPlayerPiece++; | |
//AIRCRAFT CARRIER | |
cout << "Here is your board for your reference: \n"; | |
displayPlayerBoard(); | |
do{ | |
cout << "Place your AIRCRAFT CARRIER (5 spaces).\n" | |
<< "Would you like this placed vertically (1) or horizontally (2)? (Enter '1' or '2'): "; | |
cin >> placement; | |
if(placement == 1) | |
isVertical = true; | |
else | |
isVertical = false; | |
cout << "Row: "; | |
cin >> row; | |
cout << "Column: "; | |
cin >> column; | |
row = row - 1; | |
column = column - 1; | |
isPlaced = placeShip(1, 5, row, column, isVertical); | |
} | |
while(!isPlaced); | |
} | |
//This function populates the computer's board with ships | |
void populateComputerBoard() | |
{ | |
int row, column, vert, ships[5] = {2, 3, 3, 4, 5}; | |
bool isPlaced, isVertical; | |
for(int i = 0; i < 5; i++) | |
{ | |
do{ | |
srand(time(NULL)); | |
row = rand() % 10; | |
column = rand() % 10; | |
vert = rand() % 2; | |
if(vert == 1) | |
isVertical = true; | |
else | |
isVertical = false; | |
isPlaced = placeShip(2, ships[i], row, column, isVertical); | |
} | |
while(!isPlaced); | |
} | |
} | |
//This function attempts to place a ship on the specified board, returns false if it cannot. | |
bool placeShip(int board, int size, int row, int column, bool isVertical) | |
{ | |
bool isPlaced = true; | |
int i = 0; | |
//For human player | |
if(board == 1) | |
{ | |
if(isVertical) | |
{ //row alternates | |
if(!(row + size > 9)) | |
{ | |
for(int r = row; r < row + size; r++) | |
{ | |
if(board1[r][column] != EMPTY) | |
isPlaced = false; | |
} | |
if(isPlaced == true) | |
{ | |
for(int r = row; r < row + size; r++) | |
{ | |
board1[r][column] = SHIP; | |
if(currentPlayerPiece == 0) | |
{ | |
patrolBoat[i][0] = r; | |
patrolBoat[i][1] = column; | |
} | |
else if(currentPlayerPiece == 1) | |
{ | |
destroyer[i][0] = r; | |
destroyer[i][1] = column; | |
} | |
else if(currentPlayerPiece == 2) | |
{ | |
submarine[i][0] = r; | |
submarine[i][1] = column; | |
} | |
else if(currentPlayerPiece = 3) | |
{ | |
battleship[i][0] = r; | |
battleship[i][1] = column; | |
} | |
else | |
{ | |
aircraftCarrier[i][0] = r; | |
aircraftCarrier[i][1] = column; | |
} | |
i++; | |
} | |
} | |
} | |
else | |
isPlaced = false; | |
} | |
else | |
{ //column alternates | |
if(!(column + size > 9)) | |
{ | |
for(int c = column; c < column + size; c++) | |
{ | |
if(board1[row][c] != EMPTY) | |
isPlaced = false; | |
} | |
if(isPlaced == true) | |
{ | |
for(int c = column; c < column + size; c++) | |
{ | |
board1[row][c] = SHIP; | |
if(currentPlayerPiece == 0) | |
{ | |
patrolBoat[i][0] = row; | |
patrolBoat[i][1] = c; | |
} | |
else if(currentPlayerPiece == 1) | |
{ | |
destroyer[i][0] = row; | |
destroyer[i][1] = c; | |
} | |
else if(currentPlayerPiece == 2) | |
{ | |
submarine[i][0] = row; | |
submarine[i][1] = c; | |
} | |
else if(currentPlayerPiece = 3) | |
{ | |
battleship[i][0] = row; | |
battleship[i][1] = c; | |
} | |
else | |
{ | |
aircraftCarrier[i][0] = row; | |
aircraftCarrier[i][1] = c; | |
} | |
i++; | |
} | |
} | |
} | |
else | |
isPlaced = false; | |
} | |
} | |
//For computer player | |
else | |
{ | |
if(isVertical) | |
{ //row alternates | |
if(!(row + size > 9)) | |
{ | |
for(int r = row; r < row + size; r++) | |
{ | |
if(board2[r][column] != EMPTY) | |
isPlaced = false; | |
} | |
if(isPlaced == true) | |
{ | |
for(int r = row; r < row + size; r++) | |
{ | |
board2[r][column] = SHIP; | |
} | |
} | |
} | |
else | |
isPlaced = false; | |
} | |
else | |
{ //column alternates | |
if(!(column + size > 9)) | |
{ | |
for(int c = column; c < column + size; c++) | |
{ | |
if(board2[row][c] != EMPTY) | |
isPlaced = false; | |
} | |
if(isPlaced == true) | |
{ | |
for(int c = column; c < column + size; c++) | |
{ | |
board2[row][c] = SHIP; | |
} | |
} | |
} | |
else | |
isPlaced = false; | |
} | |
} | |
return isPlaced; | |
} | |
//This function updates the score | |
void updateScore() | |
{ | |
int comp = 0, player = 0; | |
for(int r = 0; r < 10; r++) | |
{ | |
for(int c = 0; c < 10; c++) | |
{ | |
if(board1[r][c] == HIT) | |
comp++; | |
if(board2[r][c] == HIT) | |
player++; | |
} | |
} | |
computerHits = comp; | |
playerHits = player; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment