Advertisement
Guest User

Untitled

a guest
Jun 27th, 2017
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 43.36 KB | None | 0 0
  1. #include <cstdio>
  2. #include <iostream>
  3. #include <windows.h>
  4. #include <ctime>
  5.  
  6. using namespace std;
  7.  
  8. #define ROW 10
  9. #define COL 10
  10.  
  11. // The size of each type of ship
  12. #define S_CARRIER 5
  13. #define S_BATTLESHIP 4
  14. #define S_DESTROYER 3
  15. #define S_SUBMARINE 3
  16. #define S_PATROLBOAT 2
  17.  
  18. #define BOATCOUNT 5
  19.  
  20. #define UP 1
  21. #define DOWN 2
  22. #define RIGHT 3
  23. #define LEFT 4
  24.  
  25. // Defines for the deck in ai_attack_random();
  26. #define D_ROW 0
  27. #define D_COL 1
  28. #define D_SCORE 2
  29. #define D_SIZE 3 // col size in the 2d array
  30.  
  31. #define AI_ACCURACY_ADJACENT 50 // Modifier defining how likely the AI is to attack spaces adjacent to hits.  0 = never, 34 + 4 * AI_ACCURACY_DIAGONAL = always
  32. #define AI_ACCURACY_DIAGONAL 8 // Modifier that tweaks accuracy of AI attacking spaces adjacent to hits. 0 = inaccurate, AI_ACCURACY_ADJACENT / 4 makes AI dumb as a brick
  33.  
  34. enum hit {
  35.   BLANK = ' ',
  36.   MISS = '*',
  37.   HIT = 'x',
  38.   CARRIER = 'C',
  39.   BATTLESHIP = 'B',
  40.   DESTROYER = 'D',
  41.   SUBMARINE = 'S',
  42.   PATROLBOAT = 'P'
  43. };
  44.  
  45. // Various prototypes for the functions
  46. void welcome_display();
  47. bool play();
  48.  
  49. void player_populate(hit players_board_def[ROW][COL]);
  50. void boat_check(hit players_board_def[ROW][COL], int boat_type);
  51.  
  52. void board_display(hit board[ROW][COL]);
  53. void board_display(hit board[ROW][COL], const hit ref[ROW][COL]);
  54.  
  55. bool is_sunk(hit boat, hit board[ROW][COL], const hit ref[ROW][COL]);
  56. bool is_game_over(hit board[ROW][COL], const hit ref[ROW][COL]);
  57.  
  58. int hit2space(int space);
  59. char * hit2string(int space);
  60.  
  61. void ai_attack(hit board[ROW][COL], int &x, int &y);
  62. void ai_attack_random(hit board[ROW][COL], int &col, int &row, int boats[BOATCOUNT], int boatsize);
  63. int ai_calculate_score(hit board[ROW][COL], int r, int c, const int boats[BOATCOUNT], const int boatsize);
  64. void ai_sort_deck(int scores[][D_SIZE], int rows);
  65.  
  66. void player_attack(const hit computer_const_board_ref[ROW][COL], hit player_board_off[ROW][COL], int &r, int &c);
  67. void process_attack_off(hit offense[ROW][COL], const hit reference[ROW][COL], int r, int c);
  68. void process_attack_def(hit defense[ROW][COL], const hit reference[ROW][COL], int r, int c);
  69.  
  70. void placeBoat(hit board[][COL]);
  71. void direction(hit board[][COL],int randDirection,int x, int y,int limit, hit boatType);
  72. bool checkBlank(hit board[][COL], const int x, const int y, const int limit, int direction);
  73.  
  74. /*********************************************************************************************************
  75. Purpose: This is the main function that continues while the user wants to start a new game and exits when
  76. the user no longer wants to play anymore games with our awesome AI
  77.  
  78. Input: Nothing
  79.  
  80. Returns: Nothing
  81. *********************************************************************************************************/
  82. int main()
  83. {
  84.     srand(time(NULL));
  85.     bool valid=true;
  86.  
  87.     // Clears the screen then displays a graphic for the startup of the program
  88.     welcome_display();
  89.    
  90.     do{
  91.         valid = play();
  92.     }while (valid);
  93.  
  94.     printf("\n ");
  95.     system("pause");
  96. }
  97.  
  98. /*********************************************************************************************************
  99. Purpose: This is where all of the gameplay happens, from getting the user to fill their board to the computer
  100. filling its board. To then playing the game until a winner is declared.
  101.  
  102. Input: Nothing
  103.  
  104. Returns: new_game - This determines whether or not the user wants to start a new game
  105. *********************************************************************************************************/
  106. bool play(){
  107.  
  108.     bool valid;
  109.     bool new_game;
  110.     char choice;
  111.     int x=0;
  112.     int r, c;
  113.     bool computer = false, player=false;
  114.    
  115.     // For the players own board
  116.     hit player_board_def[ROW][COL];
  117.     hit computer_board_def[ROW][COL];
  118.    
  119.     // Invisible reference board keeping track of boat locations... ((Should be const))
  120.     hit player_const_board_ref[ROW][COL];
  121.     hit computer_const_board_ref[ROW][COL];
  122.        
  123.     // For the board the players will be attacking
  124.     hit player_board_off[ROW][COL];
  125.     hit computer_board_off[ROW][COL];
  126.    
  127.     for(int i = 0; i < ROW; i++)
  128.            for(int j = 0; j < COL; j++)
  129.                player_board_def[i][j] = computer_board_def[i][j] = player_const_board_ref[i][j] = computer_const_board_ref[i][j] = player_board_off[i][j] = computer_board_off[i][j] = BLANK;
  130.  
  131.     player_populate(player_board_def);
  132.     printf("\nYour board is...\n");
  133.     board_display(player_board_def, player_const_board_ref);
  134.    
  135. /*    // This is to verify that the computer player placing it's boats correctly  
  136.     printf("\n\n The computer players 'random' board is... \n ");
  137.     placeBoat(computer_board_def);
  138.     board_display(computer_board_def);
  139. */  
  140.     system("pause");
  141.     system("cls");
  142.    
  143.     // Assume all boards are set at this point so copy said boards
  144.     for(int i = 0; i < ROW; i++)
  145.         for(int j = 0; j < COL; j++){
  146.         player_const_board_ref[i][j] = player_board_def[i][j];
  147.         computer_const_board_ref[i][j] = computer_board_def[i][j];
  148.         }
  149.    
  150.     do{
  151.         ai_attack(computer_board_off, c, r); // Get coordinates to attack
  152.         process_attack_off(computer_board_off, player_const_board_ref, r, c); // Attack on offensive board
  153.         process_attack_def(player_board_def, player_const_board_ref, r, c); // Attack on defensive board
  154.         printf("\n AI has attacked %c%d\n", c+'A', r);
  155.         if(is_sunk(player_const_board_ref[r][c], player_board_def, player_const_board_ref))
  156.             printf("\n AI has sunk your %s!\n", hit2string((int) player_const_board_ref[r][c]));
  157.                
  158.         printf("\n Human player's board...\n");
  159.         board_display(player_board_def, player_const_board_ref);
  160.         computer = is_game_over(player_board_def, player_const_board_ref); // Make sure computer hasn't already won
  161.                
  162.         printf("\n Computer player's board...\n");
  163.         board_display(player_board_off);
  164.                        
  165.         if(!computer){
  166.             player_attack(computer_const_board_ref, player_board_off, r, c); // Get coordinates to attack
  167.             process_attack_off(player_board_off, computer_const_board_ref, r, c); // Attack on offensive board
  168.             process_attack_def(computer_board_def, computer_const_board_ref, r, c); // Attack on defensive board
  169.                                    
  170.             // printf(" Human has attacked %c%d\n", c+'A', r);
  171.             player = is_game_over(computer_board_def, computer_const_board_ref); // Make sure player hasn't already won
  172.         }
  173.                
  174.         system("cls");
  175.     }while (!player && !computer); // Exit when someone wins
  176.  
  177.     printf("\n GAME OVER. %s player won!\n\n", computer ? "Computer" : "Human");
  178.     printf(" Your ship locations were...\n");
  179.     board_display(player_const_board_ref);
  180.     printf("\n Computer player's ships locations where...\n");
  181.     board_display(computer_const_board_ref);
  182.    
  183.     // This is just to ask if you want to make a new game or not. Based on that it will start a new game or quit
  184.     // This can be put in a separate function if needed later...
  185.     do{
  186.         printf("\n\n Do you want to start a new game? (y/n): ");
  187.         scanf("%c", &choice);
  188.         fflush(stdin);
  189.         switch (toupper(choice)){
  190.             case 'Y':
  191.                 x=1;
  192.                 new_game=true;
  193.                 break;    
  194.             case 'N':
  195.                 x=2;
  196.                 new_game=false;
  197.                 break;
  198.             default:
  199.                 printf("\n\n Incorrect option entered, please choose again\n\n");
  200.                 x=3;
  201.         }
  202.     }while (x==3);
  203.     return (new_game);
  204. }
  205.  
  206. /*********************************************************************************************************
  207. Purpose: Process an attack on the offensive board.  Translate sinks into boat types so the player/computer
  208.         can figure out what type of boat he just sunk.
  209.  
  210. Input:  hit offense[ROW][COL]                   offense board to modify
  211.                 const hit reference[ROW][COL]   reference board to check for ships
  212.                 int r                                                   Row to aim at
  213.                 int c                                                   Column to aim at
  214.  
  215. Returns: Nothing
  216. *********************************************************************************************************/
  217. void process_attack_off(hit offense[ROW][COL], const hit reference[ROW][COL], int r, int c)
  218. {
  219.         if(reference[r][c] != BLANK)
  220.         {
  221.                 offense[r][c] = HIT;
  222.                 if(is_sunk(reference[r][c], offense, reference))
  223.                         for(int i = 0; i < ROW; i++)
  224.                                 for(int j = 0; j < COL; j++)
  225.                                         if(reference[i][j] == reference[r][c])
  226.                                                 offense[i][j] = reference[r][c];
  227.         }
  228.         else
  229.         {
  230.                 offense[r][c] = MISS;
  231.         }
  232. }
  233.  
  234. /*********************************************************************************************************
  235. Purpose: Process an attack on the defensive board, add hits when needed and misses where necessary.  DO
  236.         NOT translate sinks.
  237.  
  238. Input:  hit defense[ROW][COL]                   defensive board to modify
  239.                 const hit reference[ROW][COL]   reference board to check for ships
  240.                 int r                                                   Row to aim at
  241.                 int c                                                   Column to aim at
  242.  
  243. Returns: Nothing
  244. *********************************************************************************************************/
  245. void process_attack_def(hit defense[ROW][COL], const hit reference[ROW][COL], int r, int c)
  246. {
  247.         // This tests if the coordinate entered by the user is a ship piece on the computers board, if it is then
  248.         // we mark it as a hit. If it equals a blank spot on the computers board then it equals a miss.
  249.         if (reference[r][c] != BLANK)
  250.         defense[r][c] = HIT;
  251.     else
  252.         defense[r][c] = MISS;
  253. }
  254.  
  255. /*********************************************************************************************************
  256. Purpose: This function simply grabs input from the user for the coordinates they wish to attack
  257.  
  258. Input:  const hit computer_const_board_ref[ROW][COL], hit player_board_off[ROW][COL], int &r, int &c
  259.  
  260. Returns: Nothing
  261. *********************************************************************************************************/
  262. void player_attack(const hit computer_const_board_ref[ROW][COL], hit player_board_off[ROW][COL], int &r, int &c){
  263.    
  264.     char coord[3]={0};
  265.     char tchar;
  266.     bool valid;
  267.  
  268.  
  269.     do{  
  270.         do{
  271.             valid = true;
  272.             printf("\n Enter the coordinate you want to attack: ");
  273.                 fgets(coord, 3, stdin);
  274.                 fflush(stdin);
  275.                 strupr(coord);
  276.                 if(!isalpha(coord[0])){
  277.                         tchar = coord[0];
  278.                         coord[0] = coord[1];
  279.                         coord[1] = tchar;
  280.                 }
  281.                 if ((coord[0] < 'A' || coord[0] > 'J') || (coord[1] <'0' || coord[1] >'9')){
  282.                 printf("\n Incorrect coordinate entered. Please choose again.\n");
  283.                 valid = false;
  284.             }else
  285.                 valid = true;
  286.         }while (!valid);
  287.  
  288.         coord[0] -= 'A';
  289.         coord[1] -= '0';
  290.        
  291.         // This checks to make sure the spot the user choose is actually a blank spot so that way they
  292.         // cannot attack the same spot twice.
  293.         if (player_board_off[coord[1]][coord[0]] != BLANK){
  294.             printf("\n That coordinate has already been attacked. Please choose again.\n");
  295.             valid = false;
  296.         }
  297.  
  298.         }while (!valid);
  299.  
  300.     printf(" You are attacking: %c%d\n", coord[0] + 'A', coord[1]);
  301.     r = coord[1];
  302.     c = coord[0];
  303. }
  304.  
  305. /*********************************************************************************************************
  306. Purpose: This is to have the player choose which boat they want to place and then proceed to
  307. another function that based on the boat choosen will ask for coordinates and valid them. This continues
  308. until all boats have been placed.
  309.  
  310. Input: hit board[ROW][COL]
  311.  
  312. Returns: Nothing
  313. *********************************************************************************************************/
  314. void player_populate(hit player_board_def[ROW][COL]){
  315.    
  316.     int boattypes[5] = { CARRIER, BATTLESHIP, DESTROYER, SUBMARINE, PATROLBOAT };
  317.     bool boatplaced[5] = { false } ;
  318.     int boats = 0;
  319.     int choice;
  320.     bool valid;
  321.    
  322.     printf("\n");
  323.    
  324.     do{
  325.         do{
  326.             valid = true;
  327.             board_display(player_board_def);
  328.             printf("\n 1) Aircraft Carrier\n 2) Battleship\n 3) Destroyer\n 4) Submarine\n 5) Patrol Boat\n\n");
  329.             printf(" Choose which ship you want to place: ");
  330.             scanf("%d", &choice);
  331.             fflush(stdin);
  332.             if (choice > 0 && choice < 6){
  333.                 valid = true;
  334.             }else{
  335.                 printf("\n Incorrect option entered. Please choose again.\n\n");
  336.                 valid = false;
  337.             }
  338.         }while (!valid);
  339.        
  340.         choice--;
  341.         if(!boatplaced[choice]){ // Keeping track of which boats we have placed
  342.             boat_check(player_board_def, boattypes[choice]);
  343.             boats++; // Number of boats we have placed so far, when 5 stop placing boats.
  344.             boatplaced[choice] = true;
  345.         }else{
  346.             printf("\n You have already placed that ship. Please choose a different ship.\n\n ");
  347.             system("pause");
  348.         }
  349.         system("cls");
  350.     }while (boats < 5);
  351. }
  352.  
  353. /*********************************************************************************************************
  354. Purpose: This is to have the player choose which boat they want to place and then proceed to
  355. another function that based on the boat choosen will ask for coordinates and valid them. This continues
  356. until all boats have been placed.
  357.  
  358. Input: hit player_board_def[ROW][COL]
  359.  
  360. Returns: Nothing
  361. *********************************************************************************************************/
  362. void boat_check(hit player_board_def[ROW][COL], int boat_type)
  363. {
  364.         char coord1[3]={0};
  365.     char coord2[3]={0};
  366.     char tchar;
  367.     bool valid;
  368.        
  369.     do{
  370.                 valid = true;
  371.                
  372.                 // Input & validation for the start coordinates from the user
  373.                 do{
  374.                         printf("\n Enter first coordinate: ");
  375.                         fgets(coord1, 3, stdin);
  376.                         fflush(stdin);
  377.                         strupr(coord1);
  378.                         if(!isalpha(coord1[0])){
  379.                                 tchar = coord1[0];
  380.                                 coord1[0] = coord1[1];
  381.                                 coord1[1] = tchar;
  382.                         }
  383.         }while ((coord1[0] < 'A' || coord1[0] > 'J') && (coord1[0] <'0' || coord1[0] >'9'));
  384.        
  385.         // Input & validation for the end coordinates from the user      
  386.         do{
  387.                         printf(" Enter second coordinate: ");
  388.             fgets(coord2, 3, stdin);
  389.             fflush(stdin);
  390.             strupr(coord2);
  391.             if(!isalpha(coord2[0])){
  392.                                 tchar = coord2[0];
  393.                 coord2[0] = coord2[1];
  394.                 coord2[1] = tchar;
  395.                         }
  396.                 }while ((coord2[1] < 'A' || coord2[1] > 'J') && (coord2[1] <'0' || coord2[1] >'9'));
  397.                
  398.         // This changes the chars in the arrays to an actual number so that we can use them to interface
  399.         // with the location in the array it corrisponds to.
  400.         coord1[0] -= 'A';
  401.         coord1[1] -= '0';
  402.         coord2[0] -= 'A';
  403.         coord2[1] -= '0';
  404.                
  405.         // This checks the inputted numbers to see if they are valid by one of the element pairs being equal
  406.         // to each other. Such as if you have A2 & D2 as the coordinates the second element in both arrays
  407.         // are the same or if you have A2 & A5, the 'A's are the same (This verifies that the start & end points
  408.         // are truly in a horizontal or vertical line)
  409.                
  410.         if ((coord1[0]==coord2[0] && coord1[1]!=coord2[1]) || (coord1[0]!=coord2[0] && coord1[1]==coord2[1]))
  411.                 {
  412.                         for(int i = 0; i < 2; i++)
  413.             {
  414.                                 if(coord1[i] > coord2[i]) // Exchange coordinates to make 2nd larger than 1st
  415.                 {
  416.                                         for(int j = 0; j < 2; j++)
  417.                     {
  418.                                                 tchar = coord1[j];
  419.                         coord1[j] = coord2[j];
  420.                         coord2[j] = tchar;
  421.                                         }
  422.                                 }
  423.             }
  424.                        
  425.             // We have already guaranteed that at least 1 is the same, so we can MATHS to divine the boat size and determine its valid
  426.             if((coord2[0] - coord1[0]) + (coord2[1] - coord1[1]) + 1 != hit2space(boat_type))
  427.                                 valid = false;
  428.                        
  429.                         for(int i = coord1[0]; i <= coord2[0]; i++) // Checking horizontal
  430.                                 if(player_board_def[coord1[1]][i] != BLANK)
  431.                                         valid = false;
  432.                        
  433.                         for(int i = coord1[1]; i <= coord2[1]; i++) // Checking vertical
  434.                                 if(player_board_def[i][coord1[0]] != BLANK)
  435.                                         valid = false;
  436.                        
  437.                 }
  438.                 // If none of the previous checks have not been met then the coordinates cannot be
  439.         // correct therefore we must ask again
  440.         else
  441.         {
  442.                         valid = false;
  443.                 }
  444.         if (!valid)
  445.                 printf("\n Incorrect coordinates entered, please choose again\n");
  446.         } while (!valid);
  447.        
  448.     for(int i = coord1[0]; i <= coord2[0]; i++)
  449.                 player_board_def[coord1[1]][i] = (hit) boat_type; // Or respective boat type
  450.        
  451.         for(int i = coord1[1]; i <= coord2[1]; i++)
  452.                 player_board_def[i][coord1[0]] = (hit) boat_type; // Or respective boat type
  453. }
  454.  
  455.  
  456. /*********************************************************************************************************
  457. Purpose: This function simply prints out any array it is given in the board format that the battleship
  458. game is supposed to be displayed in
  459.  
  460. Input: hit board[ROW][COL]
  461.  
  462. Returns: Nothing
  463. *********************************************************************************************************/
  464. void board_display(hit board[ROW][COL]){
  465.  
  466.     char letters_array[11]={' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'};
  467.  
  468.     // This is for displaying the first line of dashes
  469.     for (int z=0; z < 4*COL+4; z++){
  470.         printf("-");
  471.     }
  472.     printf("\n");
  473.    
  474.     // This is for displaying A-J
  475.     for (int x=0; x < 11; x++){
  476.         printf(" %c |", letters_array[x]);
  477.     }
  478.     printf("\n");    
  479.    
  480.     // These for loops are for making the board dynamically based on the #define values and displays
  481.     // what is in the array in the board format accordingly
  482.     for (int x=0, y=0; x < ROW; x++, y++){
  483.         for (int z=0; z < 4*COL+4; z++){
  484.            printf("-");
  485.         }
  486.         printf("\n");
  487.        
  488.         // This is for displaying 0-9
  489.         printf(" %d |", y);
  490.        
  491.         // This is for displaying the contents of the element of the array we are currently at
  492.         for (int y=0; y < COL; y++){
  493.             printf(" %c |", board[x][y]);
  494.         }
  495.         printf("\n");
  496.     }
  497.  
  498.     // This is for displaying the last line of dashes
  499.     for (int z=0; z < 4*COL+4; z++){
  500.         printf("-");
  501.     }
  502.     printf("\n");
  503. }    
  504.  
  505. /*********************************************************************************************************
  506. Purpose: This is the overloaded version of the function that prints out any array it is given in the board
  507. format that the battleship game is supposed to be displayed in. This functions takes two boards
  508.  
  509. Input: hit board[ROW][COL] & hit ref[ROW][COL]
  510.  
  511. Returns: Nothing
  512. *********************************************************************************************************/
  513. void board_display(hit board[ROW][COL], const hit ref[ROW][COL]){
  514.  
  515.     char letters_array[11]={' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'};
  516.  
  517.     // This is for displaying the first line of dashes
  518.     for (int z=0; z < 4*COL+4; z++){
  519.         printf("-");
  520.     }
  521.     printf("\n");
  522.    
  523.     // This is for displaying A-J
  524.     for (int x=0; x < 11; x++){
  525.         printf(" %c |", letters_array[x]);
  526.     }
  527.     printf("\n");    
  528.    
  529.     // These for loops are for making the board dynamically based on the #define values and displays
  530.     // what is in the array in the board format accordingly
  531.     for (int x=0, y=0; x < ROW; x++, y++){
  532.         for (int z=0; z < 4*COL+4; z++){
  533.            printf("-");
  534.         }
  535.         printf("\n");
  536.        
  537.         // This is for displaying 0-9
  538.         printf(" %d |", y);
  539.        
  540.         // This is for displaying the contents of the element of the array we are currently at
  541.         for (int y=0; y < COL; y++){
  542.             printf(" %c |", is_sunk(ref[x][y], board, ref) ? tolower(ref[x][y]) : board[x][y]);
  543.         }
  544.         printf("\n");
  545.     }
  546.  
  547.     // This is for displaying the last line of dashes
  548.     for (int z=0; z < 4*COL+4; z++){
  549.         printf("-");
  550.     }
  551.     printf("\n");
  552. }
  553.  
  554. /*********************************************************************************************************
  555. Purpose: Determine whether or not all the boats on a board have been sunk
  556.  
  557. Input:  hit board[ROW][COL]             Board to look for sunken boats
  558.                 const hit ref[ROW][COL] Reference board for ship placement
  559.  
  560. Returns: bool                                   True if all boats are sunk, false otherwise.
  561. *********************************************************************************************************/
  562. bool is_game_over(hit board[ROW][COL], const hit ref[ROW][COL])
  563. {
  564.         hit boats[BOATCOUNT] = { CARRIER, BATTLESHIP, DESTROYER, SUBMARINE, PATROLBOAT };
  565.         int sinks = BOATCOUNT;
  566.        
  567.         for(int i = 0; i < BOATCOUNT; i++)
  568.                 if(is_sunk(boats[i], board, ref))
  569.                         sinks--;
  570.         return !sinks;
  571. }
  572.  
  573. /*********************************************************************************************************
  574. Purpose: Function to determine if a single boat has sunk already
  575.  
  576. Input:  hit boat                                Boat to check if has sunk
  577.                 hit board[ROW][COL]             Gameboard to check
  578.                 const hit ref[ROW][COL] Reference board to refer to for boat placement
  579.  
  580. Returns: bool                                   True if boat has sunk, false otherwise
  581. *********************************************************************************************************/
  582. bool is_sunk(hit boat, hit board[ROW][COL], const hit ref[ROW][COL])
  583. {
  584.         int size = hit2space(boat);
  585.         if(!size)
  586.                 return false;
  587.        
  588.         for(int i = 0; i < ROW; i++)
  589.                 for(int j = 0; j < COL; j++)
  590.                         if(ref[i][j] == boat && board[i][j] == HIT)
  591.                                 size--;
  592.         return (!size);
  593. }
  594.  
  595. /*********************************************************************************************************
  596. Purpose: Returns the number of spaces that the passed boat will take up.  A glorified switch statement, but
  597.         used everywhere.
  598.  
  599. Input:  int space               type of boat to check
  600.  
  601. Returns: int            Number of spaces that the ship will take up, counting from 1.  EG. Carrier would return 5
  602. *********************************************************************************************************/
  603. int hit2space(int space)
  604. {
  605.         switch(space)
  606.         {
  607.                 case CARRIER:           return S_CARRIER;
  608.                 case BATTLESHIP:        return S_BATTLESHIP;
  609.                 case DESTROYER:         return S_DESTROYER;
  610.                 case SUBMARINE:         return S_SUBMARINE;
  611.                 case PATROLBOAT:        return S_PATROLBOAT;
  612.                 default:                        return 0;
  613.     }
  614. }
  615.  
  616. /*********************************************************************************************************
  617. Purpose: Returns the number of spaces that the passed boat will take up.  A glorified switch statement, but
  618.         used everywhere.
  619.  
  620. Input:  int space               type of boat to check
  621.  
  622. Returns: int            Number of spaces that the ship will take up, counting from 1.  EG. Carrier would return 5
  623. *********************************************************************************************************/
  624. char *hit2string(int space)
  625. {
  626.         switch(space)
  627.         {
  628.                 case CARRIER:                   return "Carrier";
  629.                 case BATTLESHIP:                return "Battleship";
  630.                 case DESTROYER:                 return "Destroyer";
  631.                 case SUBMARINE:                 return "Submarine";
  632.                 case PATROLBOAT:                return "Patrol Boat";
  633.                 case MISS:                              return "Miss";
  634.                 case HIT:                               return "Hit";
  635.                 case BLANK:                             return "BLANK";
  636.         }
  637. }
  638.  
  639. /*********************************************************************************************************
  640. Purpose: This just prints out the first screen to display with a cool ascii graphic for the player to see
  641.  
  642. Input: Nothing
  643.  
  644. Returns: Nothing
  645. *********************************************************************************************************/
  646. void welcome_display(){
  647.    
  648.     // This just gives time for the user so they can fullscreen the command prompt to be able to see
  649.     // the game without scrolling up & down
  650.     printf("\n Loading; Please wait");
  651.     for (int x=0; x<3; x++){
  652.         printf(". ");
  653.         Sleep(1150);
  654.     }
  655.     system("cls");
  656.    
  657.     // This is fairly obvious that this is the title and graphic that is displayed when you start the program
  658.     printf("\n");
  659.     printf("\t\t\t\tWelcome to\n");
  660.     printf("\t\t\t     ================\n");
  661.     printf("   ____              __    __    ___                   __                    \n");
  662.     printf("  /\\  _`\\           /\\ \\__/\\ \\__/\\_ \\                 /\\ \\      __           \n");
  663.     printf("  \\ \\ \\_\\ \\     __  \\ \\ ,_\\ \\ ,_\\//\\ \\      __    ____\\ \\ \\___ /\\_\\  _____   \n");
  664.     printf("   \\ \\  _ <'  /'__`\\ \\ \\ \\/\\ \\ \\/ \\ \\ \\   /'__`\\ /',__\\\\ \\  _ `\\/\\ \\/\\ '__`\\ \n");
  665.     printf("    \\ \\ \\_\\ \\/\\ \\_\\.\\_\\ \\ \\_\\ \\ \\_ \\_\\ \\_/\\  __//\\__, `\\\\ \\ \\ \\ \\ \\ \\ \\ \\_\\ \\\n");
  666.     printf("     \\ \\____/\\ \\__/.\\_\\\\ \\__\\\\ \\__\\/\\____\\ \\____\\/\\____/ \\ \\_\\ \\_\\ \\_\\ \\ ,__/\n");
  667.     printf("      \\/___/  \\/__/\\/_/ \\/__/ \\/__/\\/____/\\/____/\\/___/   \\/_/\\/_/\\/_/\\ \\ \\/ \n");
  668.     printf("                                                                       \\ \\_\\ \n");    
  669.     printf("   Developers:                                                          \\/_/ \n");
  670.     printf("                                      #    _                                    ");
  671.     printf("   Larry Ing                       _ # #  (.)\n");
  672.     printf("   Luke Kontes               =====|_|#_#___|__                                  ");
  673.     printf("   Erich Healy                _  |____________|  _                              ");
  674.     printf("   Mark de Guzman       =====|.| | .  .  .  . | |.|====                         ");
  675.     printf("                       _ .---------------------------. _                        ");
  676.     printf("                 =====|.||  .  .  .  .  .  .  .  .   ||.|====\n");
  677.     printf("   \\---------------------'                           `--------------/\n");
  678.     printf("    \\ .  .  .  .           .  .  .  .        .  .  .  .     USS-42 /\n");
  679.     printf("     \\          .  .  .  .           .  .  .           .  .  .  . /\n");
  680.     printf("      \\__________________________________________________________/\n");
  681.     printf("  wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww\n");
  682.     printf(" wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww\n");
  683.     printf("   wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww \n");
  684.     printf("\n");
  685.     printf("\n ");    
  686.    
  687.     // Possibly use a sleep instead here...
  688.     system("pause");
  689.     system("cls");    
  690. }
  691.  
  692. /*********************************************************************************************************
  693. Purpose: This is the main attacking function for the AI.  It gathers information about the board and passes it
  694.         off to the other AI functions.  Coordinates to attack are passed by reference.
  695.  
  696. Input:  hit board[ROW][COL]             Gameboard that AI will be attacking
  697.                 int col                                 Column passed by reference that the AI will decide to attack
  698.                 int row                                 Row passed by reference that the AI will decide to attack
  699.  
  700. Returns: Nothing
  701. *********************************************************************************************************/
  702. void ai_attack(hit board[ROW][COL], int &col, int &row)
  703. {
  704.         int boatlist[BOATCOUNT] = { CARRIER, BATTLESHIP, DESTROYER, SUBMARINE, PATROLBOAT };
  705.         int boatsize = BOATCOUNT;
  706.         int i;
  707.        
  708.         // REMEMBER: col and row are passed by reference
  709.         for(int r = 0; r < ROW; r++)
  710.         {
  711.                 for(int c = 0; c < COL; c++)
  712.                 {
  713.                         if(board[r][c] != MISS && board[r][c] != BLANK) // Boat is an actual boat and needs to be removed from the boatlist
  714.                         {
  715.                                 for(i = 0; i < BOATCOUNT && board[r][c] != boatlist[i]; i++);
  716.                                 if(i != BOATCOUNT) // Otherwise this boat has already been removed
  717.                                 {
  718.                                         for(; i < BOATCOUNT - 1; i++)
  719.                                                 boatlist[i] = boatlist[i+1]; // Remove the boat from the list
  720.                                         boatsize--;
  721.                                 }
  722.                         }
  723.                 }
  724.         }
  725.         for(i = 0; i < boatsize; i++) // Convert boatlist to sizes
  726.                 boatlist[i] = hit2space(boatlist[i]);
  727.         ai_attack_random(board, col, row, boatlist, boatsize);
  728. }
  729.  
  730. /*********************************************************************************************************
  731. Purpose: This tries to pick the best space to attack on the board using a weighted system
  732.  
  733. Input:  hit board[ROW][COL]             Gameboard that AI will be attacking
  734.                 int col                                 Column passed by reference that the AI will decide to attack
  735.                 int row                                 Row passed by reference that the AI will decide to attack
  736.                 int boats[BOATCOUNT]    Array of boat sizes that still have not been sunk yet
  737.                 int boatsize                    Size of the boats array.
  738.  
  739. Returns: Nothing
  740. *********************************************************************************************************/
  741. void ai_attack_random(hit board[ROW][COL], int &col, int &row, int boats[BOATCOUNT], int boatsize)
  742. {
  743.         // The theory behind the AI here is thus:
  744.         // create a 2D deck for each space in the array holding coordinates and the score for that space
  745.         // The score represents how many variations of each type of remaining battleship can intercept that space
  746.         // Such that spaces without many hits nearby will have a higher weight than those adjacent to the edge of the board
  747.         // or next to miss markers.
  748.         // The deck is then sorted according to score and a random space from the list of top scorers is chosen and the AI targets that
  749.        
  750.         // TODO:
  751.         // As it stands, the AI here is too smart and thus too predictable.  need to figure out a way to make it slightly more random.
  752.         // Unless thats unneccesary...
  753.         int deck[ROW*COL][D_SIZE];
  754.         int decksize = 0;
  755.         int target, x;
  756.        
  757.         for(int i = 0; i < ROW; i++) // populate the deck and generate scores
  758.         {
  759.                 for(int j = 0; j < COL; j++)
  760.                 {
  761.                         if(board[i][j] == BLANK)
  762.                         {
  763.                                 deck[decksize][D_ROW] = i;
  764.                                 deck[decksize][D_COL] = j;
  765.                                 deck[decksize][D_SCORE] = ai_calculate_score(board, i, j, boats, boatsize);
  766.                                 decksize++;
  767.                         }
  768.                 }
  769.         }
  770.        
  771.         ai_sort_deck(deck, decksize - 1); // Sort the deck based on scores
  772.         for(target = 0, x = deck[0][D_SCORE]; x == deck[target][D_SCORE] && target < decksize; target++); // find the range of possible targets
  773.         target = rand() % target; // Pick the target to use
  774.         col = deck[target][D_COL];
  775.         row = deck[target][D_ROW];
  776. }
  777.  
  778. /*********************************************************************************************************
  779. Purpose: This calculates the weight score of a particular board space and returns that score.  Score is
  780.         based on how many possible ship combinations can legally overlap that space.  It then adds or subtracts
  781.         a modifier to the score based on adjacent and diagonal hits.
  782.  
  783. Input:  hit board[ROW][COL]             Main gameboard that it must calculate
  784.                 int r                                   Row number to check
  785.                 int c                                   Column number to check
  786.                 int boats[BOATCOUNT]    List of boats to check against space
  787.                 int boatsize                    Size of boats array
  788.  
  789. Returns: int    Weight score for that particular space
  790. *********************************************************************************************************/
  791. int ai_calculate_score(hit board[ROW][COL], int r, int c, const int boats[BOATCOUNT], const int boatsize)
  792. {
  793.         // Scoring algorithm works like such:  add 1 to the weight of the space for each section of a ship it can contain
  794.         // both horizontaly and verticaly
  795.         // Thus, x_?__x (x = miss, _ = blank, ? = coordinates) would have a score of:
  796.         //              +2 for patrol boat
  797.         //              +2 for sub and destroyer apiece
  798.         //              +1 for battleship since there is only one legal configuration in this section that would store the ? within the battleship
  799.         //              +0 for carrier since it cannot fit between those misses
  800.         // Additionally, score is only added for ships that have not yet been sunk, as defined by int boats.
  801.         // By this method, each space has a theoretical score limit of 34
  802.        
  803.         // Modifiers:
  804.         // Spaces will be modified based on their proximity to a hit.  such that spaces directly adjacent to hits will recieve extra points and
  805.         // spaces diagonally adjacent to hits will be demoted points
  806.         int score = 0;
  807.         int startpos, endpos;
  808.        
  809.         // Calculate the horizontal.
  810.         for(int boat = 0; boat < BOATCOUNT; boat++)
  811.         {
  812.                 for(startpos = c; startpos < COL - 1 && (board[r][startpos] == BLANK || board[r][startpos] == HIT) && startpos - c + 1 < boats[boat]; startpos++); // Move the start counter all the way to the right
  813.                 for(endpos = c; endpos >= 0 && (board[r][endpos] == BLANK || board[r][endpos] == HIT) && startpos - endpos + 1 < boats[boat]; endpos--); // Move end counter to the left to encompase size of boat
  814.                 if(startpos - endpos + 1 == boats[boat]) // make sure it can actually hold the boat before continuing
  815.                         for(; endpos >= 0 && startpos >= c && (board[r][endpos] == BLANK || board[r][endpos] == HIT) && (board[r][startpos] == BLANK || board[r][startpos] == HIT); startpos--, endpos--)
  816.                                 score++; // Move counters to the left and add one to the score for each successful move
  817.         }
  818.        
  819.         // Now the vertical, mainly the same thing
  820.         for(int boat = 0; boat < BOATCOUNT; boat++)
  821.         {
  822.                 for(startpos = r; startpos < ROW - 1 && (board[startpos][c] == BLANK || board[startpos][c] == HIT) && startpos - r + 1 < boats[boat]; startpos++); // Move the start counter all the way to the right
  823.                 for(endpos = r; endpos >= 0 && (board[endpos][c] == BLANK || board[endpos][c] == HIT) && startpos - endpos + 1 < boats[boat]; endpos--); // Move end counter to the left to encompase size of boat
  824.                 if(startpos - endpos + 1 == boats[boat]) // make sure it can actually hold the boat before continuing
  825.                         for(; endpos >= 0 && startpos >= r && (board[endpos][c] == BLANK || board[endpos][c] == HIT) && (board[startpos][c] == BLANK || board[startpos][c] == HIT); startpos--, endpos--)
  826.                                 score++; // Move counters to the left and add one to the score for each successful move
  827.         }
  828.        
  829.         // Process directly adjacent modifiers
  830.         if(r - 1 >= 0  && board[r-1][c] == HIT) score += AI_ACCURACY_ADJACENT;
  831.         if(r + 1 < ROW && board[r+1][c] == HIT) score += AI_ACCURACY_ADJACENT;
  832.         if(c - 1 >= 0  && board[r][c-1] == HIT) score += AI_ACCURACY_ADJACENT;
  833.         if(c + 1 < COL && board[r][c+1] == HIT) score += AI_ACCURACY_ADJACENT;
  834.        
  835.         // Process diagonally adjacent modifiers
  836.         if(r - 1 >= 0 && c - 1 >= 0   && board[r-1][c-1] == HIT) score -= AI_ACCURACY_DIAGONAL;
  837.         if(r + 1 < ROW && c - 1 >= 0  && board[r+1][c-1] == HIT) score -= AI_ACCURACY_DIAGONAL;
  838.         if(r - 1 >= 0 && c + 1 < COL  && board[r-1][c+1] == HIT) score -= AI_ACCURACY_DIAGONAL;
  839.         if(r + 1 < ROW && c + 1 < COL && board[r+1][c+1] == HIT) score -= AI_ACCURACY_DIAGONAL;
  840.        
  841.         return score;
  842. }
  843.  
  844. /*********************************************************************************************************
  845. Purpose: Sorting function for use in ai_attack_random.  Sorts a 2d array based on the third item in the
  846.         second array.  Bubblesort style
  847.  
  848. Input:  hit scores[][D_SIZE]    2d array that it needs to sort
  849.                 int rows                                Size of scores array counting from zero
  850.  
  851. Returns: Nothing
  852. *********************************************************************************************************/
  853. void ai_sort_deck(int scores[][D_SIZE], int rows) // munged bubblesort
  854. {
  855.         int temp, index;
  856.        
  857.         for(; rows > 0; rows--)
  858.         {
  859.                 for(index = 0; index < rows; index++)
  860.                 {
  861.                         if(scores[index][D_SCORE] < scores[index+1][D_SCORE])
  862.                         {
  863.                                 for(int i = 0; i < D_SIZE; i++)
  864.                                 {
  865.                                         temp = scores[index+1][i];
  866.                                         scores[index+1][i] = scores[index][i];
  867.                                         scores[index][i] = temp;
  868.                                 }
  869.                         }
  870.                 }
  871.         }
  872. }
  873.  
  874. /************************************************************
  875. Name: placementBoat
  876. Purpose: This function uses a switch-case statment to place the carrier, battleship, destroyer, submarine, and patrol boat, in that order.  It places them by calling the direction function.
  877. Input: hit board[][COL] - This is the board that will contain all the AI's boats.
  878.           int x - This is the randomly generated X cordinate.
  879.           int y - This is the randomly generated Y cordinate.  Together with the random X cordinate, these will serve as teh starting point for all points.
  880. Output: NA.
  881. ************************************************************/
  882. void placeBoat(hit board[][COL]){
  883.         int x, y;
  884.         int randDirection;
  885.         hit boats[BOATCOUNT] = { CARRIER, BATTLESHIP, DESTROYER, SUBMARINE, PATROLBOAT};
  886.         for(int i = 0; i < BOATCOUNT; i++)
  887.         {
  888.                 do{
  889.                 randDirection = (rand()%4)+1;
  890.                         x = rand()%ROW;
  891.                         y = rand()%COL;
  892.                 }while( !checkBlank(board,x,y,hit2space((int) boats[i]),randDirection) );
  893.                 direction(board,randDirection,x,y,hit2space((int) boats[i]),boats[i]);
  894.         }
  895. }
  896.  
  897. /************************************************************
  898. Name: direction
  899. Purpose: Based upon a randomly generated number, this function will decide which direction to place the remaining points for a said boat.
  900. Input: hit board[][COL] - This is the board that will contain all the AI's boats.
  901.           int x and int y - These are the basis upon which all other points will be place as explain in the previous function.
  902. Output: NA.
  903. ************************************************************/
  904. void direction(hit board[][COL],int randDirection,int x, int y,int limit, hit boatType){
  905.         for(int i=0;i<limit;i++){
  906.                 if(randDirection==UP){
  907.                         board[x][y-i] = boatType;
  908.                 }else if(randDirection == DOWN){  //If the direction is down this will be done.
  909.                         board[x][y+i] = boatType;
  910.                 }else if(randDirection==RIGHT){
  911.                         board[x-i][y] = boatType;
  912.                 }else{  //If the direction is left this will be done.
  913.                         board[x+i][y] = boatType;
  914.                 }
  915.     }  
  916. }
  917.  
  918. /************************************************************
  919. Name: checkBlank
  920. Purpose: This will check the spots that the Ai wishes to place the boat on an confirm it is able
  921. Input: hit board[][COL] - This is the board that will contain all the AI's boats.
  922.           int x and int y - These are the basis upon which all other points will be place as explain in the previous function.
  923.           int direction - A randomly generated direction
  924. Output: Returns true or false
  925. ************************************************************/
  926. bool checkBlank(hit board[][COL], const int x, const int y, const int limit, int direction){
  927.         int i;
  928.         bool valid = true;
  929.  
  930.     switch (direction){
  931.         case UP:
  932.             for(i=0;i<limit;i++){
  933.                 if(y-limit < 0 || board[x][y-i] != BLANK) valid = false;
  934.             }
  935.         case DOWN:
  936.             for(i=0;i<limit;i++){
  937.                 if(y+limit >= ROW || board[x][y+i] != BLANK) valid = false;
  938.             }
  939.         case RIGHT:
  940.             for(i=0;i<limit;i++){
  941.                 if(x-limit < 0 || board[x-i][y] != BLANK) valid = false;
  942.             }
  943.         case LEFT:
  944.             for(i=0;i<limit;i++){
  945.                 if(x+limit >= COL || board[x+i][y] != BLANK) valid = false;
  946.             }
  947.     }
  948.         return valid;
  949. }
  950.  
  951. /*    
  952. void say_qoute(){
  953.    
  954.         char *qoutes[] = {
  955.                 "Always in motion is the future...",
  956.                 "The force is strong with this one...",
  957.                 "The rumors of my death have been greatly exagerated",
  958.                 "All your base are belong to us",
  959.                 "May the force be with you.",
  960.                 "...Admiral, I want that ship - not excuses!",
  961.                 "There is a great disturbance in the Force",
  962.                 "We have a new enemy, the young Rebel who destroyed the Death Star.",
  963.                 "Impressive, most impressive. Obi-Wan has taught you well.",
  964.                 "There is no escape. Don't make me destroy you.",
  965.                 "You are beaten. It is useless to resist.",
  966.                 "I have you now!",
  967.                 "It's a trap!",
  968.                 "Don't underestimate the Force.",
  969.                 "I find your lack of faith disturbing.",
  970.         "Man your ships... and may the Force be with you."
  971.         }
  972.         puts(qoutes[rand() % 5]);
  973. }
  974. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement