/* grid class implementation * J, B, D * 17 April 2012 */ #include #include #include "grid.h" using std::cout; using std::endl; //default constructor calls reset() function grid::grid() { reset(); } //parameters: an x and y coordinate //returns: the char at the position of board char grid::getChar(int x, int y) { return board[y][x]; } //parameters: an x and y coordinate //returns: true if those coordinates are in this grid, else false bool grid::contains(int x, int y) { return (x >= 0) && (x < GRID_SIZE) && (y >= 0) && (y < GRID_SIZE); } //parameters: two ships //returns: true if the ships share any cells, else false bool grid::intersect(ship ship1, ship ship2) { for(int i = 0; i < ship1.getSize(); i++) //goes through every coordinate in the first ship for(int j = 0; j < ship2.getSize(); j++) //goes through every coordinate in the second ship if((ship1.getx(i) == ship2.getx(j)) && (ship1.gety(i) == ship2.gety(j))) return true; return false; } //parameters: the two endpoints of a potential ship, the size it should be //by reference: the ship defined by those coordinates //returns: true if the ship is valid, else false bool grid::checkShip(int x1, int y1, int x2, int y2, int targetSize, ship& newShip) { if((x1 != x2) && (y1 != y2)) //returns false if the coordinates are not horizontal or vertical return false; if(!contains(x1, y1) || !contains(x2, y2)) //returns false if the coordinates are not in the grid return false; if(numShips >= TOTAL_SHIPS) //returns false if there are already TOTAL_SHIPS in this grid return false; newShip.setPosition(x1, y1, x2, y2); //sets the position of the new ship if(newShip.getSize() != targetSize) //returns false if the ship's size is not the target size return false; for(int i = 0; i < numShips; i++) //goes through all ships already in this grid if(intersect(newShip, ships[i])) //returns false if this ship intersects any ship in this grid return false; return true; } //parameters: a ship to show on the board //function: prints the board as it would appear with the new ship void grid::displayNewShip(ship newShip) { char tempBoard[10][10]; //creates a temporary array identical to board for(int i = 0; i < 10; i++) for(int j = 0; j < 10; j++) tempBoard[i][j] = board[i][j]; for(int i = 0; i < newShip.getSize(); i++) //changes the char in tempBoard at each coordinate in newShip to SHIP_CH tempBoard[newShip.getx(i)][newShip.gety(i)] = SHIP_CH; friendlyGridDisplay(tempBoard); //displays the tempBoard } //parameters: a ship to add to this grid //function: adds the ship to this grid, updates board, and updates numShips void grid::addShip(ship newShip) { ships[numShips] = newShip; numShips++; for(int i = 0; i < newShip.getSize(); i++) //changes the char in board at each coordinate in newShip to SHIP_CH board[newShip.gety(i)][newShip.getx(i)] = SHIP_CH; } //parameters: coordinates to shoot at //by-reference: which ship was sunk //returns: the char at that location on the board before taking a shot //function: if x,y was a valid shot, updates board and the hit ship char grid::takeShot(int x, int y, int& shipSunk) { char space = board[y][x]; shipSunk = 0; if(space == BLANK_CH) //if the shot was a miss, update board with MISS_CH board[y][x] = MISS_CH; else if(space == SHIP_CH) { board[y][x] = HIT_CH; //if the shot hit a ship, update board with HIT_CH int shipNum; for(int i = 0; i < TOTAL_SHIPS; i++) if(!ships[i].isSunk()) if(ships[i].hitCheck(x, y)) //call hit check on all coordinates in unsunk ships in the grid shipNum = i; //store the location in the ships array of the hit ship in i ship shipHit = ships[shipNum]; //create a temporary ship for easier coding if(shipHit.isSunk()) { for(int i = 0; i < shipHit.getSize(); i++) //if the ship was sunk, update board with SUNK_CH board[shipHit.gety(i)][shipHit.getx(i)] = SUNK_CH; if(shipHit.getName() == "PT Boat") //return which ship was sunk by reference shipSunk = 1; else if(shipHit.getName() == "Cruiser") shipSunk = 2; else if(shipHit.getName() == "Submarine") shipSunk = 3; else if(shipHit.getName() == "Battleship") shipSunk = 4; else if(shipHit.getName() == "Carrier") shipSunk = 5; } } return space; } //returns: true if all ships in this grid are sunk, else false bool grid::checkWin() { for(int i = 0; i < TOTAL_SHIPS; i++) //goes through all ships in this grid if(!ships[i].isSunk()) return false; return true; } //function: fills board with BLANK_CH and sets numShips to zero void grid::reset() { for(int i = 0; i < 10; i++) for(int j = 0; j < 10; j++) board[i][j] = BLANK_CH; numShips = 0; } //parameters: the board to be displayed //function: displays the parameter board as it actually appears void grid::friendlyGridDisplay(char tempBoard[10][10]) { cout << " +---+---+---+---+---+---+---+---+---+---+" << endl; for(int i = 0; i < 10; i++) { cout << i << " |"; for (int j = 0; j < 10; j++) cout << " " << tempBoard[i][j] << " |"; cout << endl << " +---+---+---+---+---+---+---+---+---+---+" << endl; } cout << " "; for(int i = 0; i < 10; i++) cout << i << " "; cout << endl; } //function: calls the previous function, passing this grid's board as the parameter void grid::friendlyGridDisplay() { friendlyGridDisplay(board); } //function: displays this grid's board without showing unhit ships void grid::enemyGridDisplay() { cout << " +---+---+---+---+---+---+---+---+---+---+" << endl; for(int i = 0; i < 10; i++) { cout << i << " |"; for (int j = 0; j < 10; j++) { if(board[i][j] == SHIP_CH) //if the char is SHIP_CH instead display BLANK_CH cout << " " << BLANK_CH; else cout << " " << board[i][j]; cout << " |"; } cout << endl << " +---+---+---+---+---+---+---+---+---+---+" << endl; } cout << " "; for(int i = 0; i < 10; i++) cout << i << " "; cout << endl; } //parameters: the name and size of the ship to be created //function: adds a ship to this grid at random location void grid::popShip(string name, int shipsize) { srand(time(NULL)); bool placed = false; ship boat(name); while (placed == false) //keep making random ships until one is valid in this grid { int xDiff = 0, yDiff = 0; int x = rand() % 10; //get random x coordinate int y = rand() % 10; //get random y coordinate int direction = rand() % 4; //get random direction switch(direction) { case 0: xDiff = shipsize - 1; break; case 1: xDiff = 1 - shipsize; break; case 2: yDiff = shipsize - 1; break; case 3: yDiff = 1 - shipsize; break; } placed = checkShip(x, y, x + xDiff, y + yDiff, shipsize, boat); //check if the ship starting at x,y going in direction is valid } addShip(boat); } //function: adds a random PT Boat, Cruiser, Submarine, Battleship, and Carrier // to this grid using popShip() void grid::popFleet() { popShip("Carrier", 5); popShip("Battleship", 4); popShip("Submarine", 3); popShip("Cruiser", 3); popShip("PT Boat", 2); } // bool grid::sunkcheck (int shipnumber, int shiphitcount) { shipnumber++; if (shipnumber < 3) shipnumber++; if (shiphitcount == shipnumber) return false; return true; } //parameters: killtracker array to help AI keep track of ships and potential shots //by-reference: x and y coordinate where the AI shot, whether a ship was sunk and which ship //function: if a ship has been hit, attempts to sink it, // else chooses a random cell in a set pattern based on the largest unsunk ship void grid::aifire (int killtracker[12][12], int& xvalue, int& yvalue, int& sunkship) { srand(time(NULL)); bool caseone = false; bool casetwo = false; bool fired = false; for (int i = 1; i < 11; i++){ for (int j = 1; j < 11; j++){ if (killtracker[i][j] > 5){ caseone = true; if (killtracker[i][j] > 6){ casetwo = true; } } } } int i = 0; int j = 0; if (caseone == true && casetwo == false){ while (killtracker[i][j] != 6){ i = rand() % 10 + 1; j = rand() % 10 + 1; } } if (casetwo == true){ while (killtracker[i][j] < 7){ i = rand() % 10 + 1; j = rand() % 10 + 1; } } while (fired == false && caseone == true){ if (casetwo == true){ int direction = killtracker[i][j] - 7; if (direction == 0){ i--; fired = true; if (takeShot(i - 1, j - 1, sunkship) == 'S'){ killtracker[i][j] = 7; if (sunkship == 1){ killtracker[i][j] = 0; killtracker[i+1][j] = 0; } if (sunkship == 2){ killtracker[i][j] = 1; killtracker[i+1][j] = 1; killtracker[1+2][j] = 1; } if (sunkship == 3){ killtracker[i][j] = 2; killtracker[i+1][j] = 2; killtracker[i+2][j] = 2; } if (sunkship == 4){ killtracker[i][j] = 3; killtracker[i+1][j] = 3; killtracker[1+2][j] = 3; killtracker[i+3][j] = 3; } if (sunkship == 5){ killtracker[i][j] = 4; killtracker[i+1][j] = 4; killtracker[i+2][j] = 4; killtracker[i+3][j] = 4; killtracker[i+4][j] = 4; } } } if (direction == 1){ i++; fired = true; if (takeShot(i - 1, j - 1, sunkship) == 'S'){ killtracker[i][j] = 7; if (sunkship == 1){ killtracker[i][j] = 0; killtracker[i-1][j] = 0; } if (sunkship == 2){ killtracker[i][j] = 1; killtracker[i-1][j] = 1; killtracker[1-2][j] = 1; } if (sunkship == 3){ killtracker[i][j] = 2; killtracker[i-1][j] = 2; killtracker[i-2][j] = 2; } if (sunkship == 4){ killtracker[i][j] = 3; killtracker[i-1][j] = 3; killtracker[i-2][j] = 3; killtracker[i-3][j] = 3; } if (sunkship == 5){ killtracker[i][j] = 4; killtracker[i-1][j] = 4; killtracker[i-2][j] = 4; killtracker[i-3][j] = 4; killtracker[i-4][j] = 4; } } } if (direction == 2){ j--; fired = true; if (takeShot(i - 1, j - 1, sunkship) == 'S'){ killtracker[i][j] = 9; if (sunkship == 1){ killtracker[i][j] = 0; killtracker[i-1][j] = 0; } if (sunkship == 2){ killtracker[i][j] = 1; killtracker[i-1][j] = 1; killtracker[1-2][j] = 1; } if (sunkship == 3){ killtracker[i][j] = 2; killtracker[i-1][j] = 2; killtracker[i-2][j] = 2; } if (sunkship == 4){ killtracker[i][j] = 3; killtracker[i-1][j] = 3; killtracker[i-2][j] = 3; killtracker[i-3][j] = 3; } if (sunkship == 5){ killtracker[i][j] = 4; killtracker[i-1][j] = 4; killtracker[i-2][j] = 4; killtracker[i-3][j] = 4; killtracker[i-4][j] = 4; } } } if (direction == 3){ j++; fired = true; if (takeShot(i - 1, j - 1, sunkship) == 'S'){ killtracker[i][j] = 10; if (sunkship == 1){ killtracker[i][j] = 0; killtracker[i][j-1] = 0; } if (sunkship == 2){ killtracker[i][j] = 1; killtracker[i][j-1] = 1; killtracker[i][j-2] = 1; } if (sunkship == 3){ killtracker[i][j] = 2; killtracker[i][j-1] = 2; killtracker[i][j-2] = 2; } if (sunkship == 4){ killtracker[i][j] = 3; killtracker[i][j-1] = 3; killtracker[i][j-2] = 3; killtracker[i][j-3] = 3; } if (sunkship == 5){ killtracker[i][j] = 4; killtracker[i][j-1] = 4; killtracker[i][j-2] = 4; killtracker[i][j-3] = 4; killtracker[i][j-4] = 4; } } } if (casetwo == false){ int direction = rand() % 4; fired = true; if (direction == 0){ if (killtracker[i+1][j] > 5){ if (takeShot(i - 1, j - 1, sunkship) == 'S'){ killtracker[i][j] = 7; if (sunkship == 1){ killtracker[i][j] = 0; killtracker[i+1][j] = 0; } if (sunkship == 2){ killtracker[i][j] = 1; killtracker[i+1][j] = 1; killtracker[1+2][j] = 1; } if (sunkship == 3){ killtracker[i][j] = 2; killtracker[i+1][j] = 2; killtracker[i+2][j] = 2; } if (sunkship == 4){ killtracker[i][j] = 3; killtracker[i+1][j] = 3; killtracker[1+2][j] = 3; killtracker[i+3][j] = 3; } if (sunkship == 5){ killtracker[i][j] = 4; killtracker[i+1][j] = 4; killtracker[i+2][j] = 4; killtracker[i+3][j] = 4; killtracker[i+4][j] = 4; } } else { killtracker[i][j] = -1; } } } if (direction == 1){ if (killtracker[i-1][j] > 5){ if (takeShot(i - 1, j - 1, sunkship) == 'S'){ killtracker[i][j] = 8; fired = true; if (sunkship == 1){ killtracker[i][j] = 0; killtracker[i-1][j] = 0; } if (sunkship == 2){ killtracker[i][j] = 1; killtracker[i-1][j] = 1; killtracker[1-2][j] = 1; } if (sunkship == 3){ killtracker[i][j] = 2; killtracker[i-1][j] = 2; killtracker[i-2][j] = 2; } if (sunkship == 4){ killtracker[i][j] = 3; killtracker[i-1][j] = 3; killtracker[1-2][j] = 3; killtracker[i-3][j] = 3; } if (sunkship == 5){ killtracker[i][j] = 4; killtracker[i-1][j] = 4; killtracker[i-2][j] = 4; killtracker[i-3][j] = 4; killtracker[i-4][j] = 4; } else { killtracker[i][j] = -1; } } } } if (direction == 2){ if (killtracker[i][j+1] > 5){ if (takeShot(i - 1, j - 1, sunkship) == 'S'){ killtracker[i][j] = 9; fired = true; if (sunkship == 1){ killtracker[i][j] = 0; killtracker[i][j+1] = 0; } if (sunkship == 2){ killtracker[i][j] = 1; killtracker[i][j+1] = 1; killtracker[1][j+2] = 1; } if (sunkship == 3){ killtracker[i][j] = 2; killtracker[i][j+2] = 2; killtracker[i][j+2] = 2; } if (sunkship == 4){ killtracker[i][j] = 3; killtracker[i][j+2] = 3; killtracker[1][j+2] = 3; killtracker[i][j+3] = 3; } if (sunkship == 5){ killtracker[i][j] = 4; killtracker[i][j+1] = 4; killtracker[i][j+2] = 4; killtracker[i][j+3] = 4; killtracker[i][j+4] = 4; } else { killtracker[i][j] = -1; } } } } if (direction == 3){ if (killtracker[i][j-1] > 5){ if (takeShot(i - 1, j - 1, sunkship) == 'S'){ killtracker[i][j] = 10; fired = true; if (sunkship == 1){ killtracker[i][j] = 0; killtracker[i][j-1] = 0; } if (sunkship == 2){ killtracker[i][j] = 1; killtracker[i][j-1] = 1; killtracker[1][j-2] = 1; } if (sunkship == 3){ killtracker[i][j] = 2; killtracker[i][j-1] = 2; killtracker[i][j-2] = 2; } if (sunkship == 4){ killtracker[i][j] = 3; killtracker[i][j-1] = 3; killtracker[1][j-2] = 3; killtracker[i][j-3] = 3; } if (sunkship == 5){ killtracker[i][j] = 4; killtracker[i][j-1] = 4; killtracker[i][j-2] = 4; killtracker[i][j-3] = 4; killtracker[i][j-4] = 4; } else { killtracker[i][j] = -1; } } } } } xvalue = i - 1; yvalue = j - 1; } } while (fired == false){ xvalue = rand() % 10; yvalue = rand() % 10; if (board[xvalue][yvalue] == 5){ takeShot(xvalue, yvalue, sunkship); fired = true; killtracker[xvalue + 1][yvalue + 1] = 6; } else killtracker[xvalue + 1][yvalue + 1] = -1; } }