Created
February 11, 2015 04:37
-
-
Save john4/0b01928877477469fcdb to your computer and use it in GitHub Desktop.
Single Player Console Battleship with Artificial Intelligence
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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