Guest User

Untitled

a guest
Aug 21st, 2018
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.56 KB | None | 0 0
  1. /*Eric Schmid
  2. Zach Williams
  3. 12/4/10
  4. COP 3223H
  5. Final Project
  6. Battleship Game*/
  7.  
  8. #include <stdio.h>
  9. #include <time.h>
  10. #define LENGTH 10
  11. #define WIDTH 10
  12.  
  13. struct ship{
  14. char name[20];
  15. int size;
  16. };
  17.  
  18. int PlayerShipCheck(char array[][WIDTH], struct ship *s);
  19. int CompShipCheck(char array[][WIDTH], struct ship *s);
  20. void PrintGrid(char array[][WIDTH]);
  21. void AssignCompGrid(char array[][WIDTH], struct ship *s);
  22. int CompIntersectCheck(char array[][WIDTH], int n1, int n2, struct ship *s);
  23. int CharToInt(char letter);
  24. char IntToChar(int num);
  25. void AssignPlayerGrid(char array[][WIDTH], struct ship *s);
  26. int PlayerIntersectCheck(char array[][WIDTH], int coord1, int coord2, int coord3, int coord4);
  27. void FileInterface(int winner);
  28.  
  29. int main(){
  30.  
  31. //Establish random # generator, integers needed for whole of program, and the grids for use
  32. srand(time(0));
  33. int i, j, choice=1, check;
  34. char Comp_hide_grid[LENGTH][WIDTH], Comp_view_grid[LENGTH][WIDTH], Player_view_grid[LENGTH][WIDTH];
  35. //Player_view grid shows player ships, Comp_view_grid shows hits and misses, Comp_hide_grid stores computer's ships
  36.  
  37. //Set up each of the struct ship types
  38. struct ship Aircraft_Carrier;
  39. strcpy(Aircraft_Carrier.name, "Aircraft Carrier");
  40. Aircraft_Carrier.size = 5;
  41.  
  42. struct ship Battleship;
  43. strcpy(Battleship.name, "Battleship");
  44. Battleship.size = 4;
  45.  
  46. struct ship Cruiser;
  47. strcpy(Cruiser.name, "Cruiser");
  48. Cruiser.size = 3;
  49.  
  50. struct ship Submarine;
  51. strcpy(Submarine.name, "Submarine");
  52. Submarine.size = 3;
  53.  
  54. struct ship Destroyer;
  55. strcpy(Destroyer.name, "Destroyer");
  56. Destroyer.size = 2;
  57.  
  58. struct ship Hit;
  59. strcpy(Hit.name, "X");
  60. Hit.size = 1;
  61.  
  62. struct ship Miss;
  63. strcpy(Miss.name, "O");
  64. Miss.size = 1;
  65.  
  66. printf("Welcome to Battleship!\n\n");
  67.  
  68. //Use a do-while loop to cycle through gameplay at least once
  69. do{
  70.  
  71. //Set all the grids to have the emnpty value, a '~' for our case
  72. for(i=0; i<10; i++){
  73. for(j=0; j<10; j++){
  74. Comp_hide_grid[i][j] = '~';
  75. Comp_view_grid[i][j] = '~';
  76. Player_view_grid[i][j] = '~';
  77. }
  78. }
  79.  
  80. //Call custom function for randomly assigning each of the ships on the computer's grid
  81. AssignCompGrid(Comp_hide_grid, &Aircraft_Carrier);
  82. AssignCompGrid(Comp_hide_grid, &Battleship);
  83. AssignCompGrid(Comp_hide_grid, &Cruiser);
  84. AssignCompGrid(Comp_hide_grid, &Submarine);
  85. AssignCompGrid(Comp_hide_grid, &Destroyer);
  86.  
  87. //Call custom function to prompt the user for ship placement coordinates
  88. AssignPlayerGrid(Player_view_grid, &Aircraft_Carrier);
  89. AssignPlayerGrid(Player_view_grid, &Battleship);
  90. AssignPlayerGrid(Player_view_grid, &Cruiser);
  91. AssignPlayerGrid(Player_view_grid, &Submarine);
  92. AssignPlayerGrid(Player_view_grid, &Destroyer);
  93.  
  94. //Print out player's game board
  95. printf("Your game board:\n");
  96. PrintGrid(Player_view_grid);
  97. check=1;
  98. //Give user option to 'cheat'; if they want Easy, print the Computer's game board
  99. char ans[5];
  100. while(check){
  101. printf("Would you like to play on Easy or Hard? \n");
  102. scanf("%s", ans);
  103.  
  104. if(strcmp(ans, "Easy") == 0){
  105. printf("Computer's game board:\n");
  106. PrintGrid(Comp_hide_grid);
  107. check = 0;
  108. }
  109.  
  110. //If the user does not input 'Easy' or 'Hard'
  111. else if(strcmp(ans, "Hard")!= 0){
  112. printf("Not a valid answer, try again.\n");
  113. }
  114. else{
  115. check = 0;
  116. }
  117. }
  118.  
  119. //Establish variables for use in the gameplay
  120. printf("\nGAME ON!\n\n");
  121. int turn=1, play=1, coord2, compcoord1, compcoord2, winner;
  122.  
  123. //Initialize variables used in ship check to 0
  124. int a1=0, b1=0, c1=0, d1=0, s1=0, a2=0, b2=0, c2=0, d2=0, s2=0;
  125. char coord1, temp[3], coord1char;
  126.  
  127. while(play){ //As long as the program stays within this loop, the game is not over; gameplay continues
  128. if(turn){ //Determines the turns; if turn=1 it's the player's turn, turn=0 is the computer's
  129.  
  130. //Player goes first; prompt player for coordinate input
  131. printf("Your turn: \n");
  132. printf("Enter the target coordinates: \n");
  133. scanf("%s", temp);
  134.  
  135. //Parse the inputted data into the two separate coordinates
  136. coord1 = temp[0];
  137. coord2 = temp[1]-'0';
  138.  
  139. //Call custom function to convert char input into int value
  140. coord1 = CharToInt(coord1);
  141. check=1;
  142.  
  143. //If check=1, spot is occupied by a hit or miss; continue to reprompt player for coordinates; else move on
  144. while(check){
  145. if(Comp_view_grid[coord1][coord2] == Hit.name[0] || Comp_view_grid[coord1][coord2] == Miss.name[0]){
  146. printf("You have already shot there. Enter a different target.\n");
  147. scanf("%s", temp);
  148. coord1 = temp[0];
  149. coord2 = temp[1]-'0';
  150. coord1 = CharToInt(coord1);
  151. }
  152.  
  153. else{
  154. check = 0;
  155. }
  156. }
  157.  
  158. //Conditions for a hit; if inputted coordinate coorresponds to a value that isn't ~ on assigned CPU coordinates
  159. if(Comp_hide_grid[coord1][coord2] != '~'){
  160. printf("Direct hit!\n");
  161. //To make sure same spot isn't fired upon twice, change values in both CPU grids
  162. Comp_hide_grid[coord1][coord2] = '~';//change to ~
  163. Comp_view_grid[coord1][coord2] = Hit.name[0];//change to X
  164. }
  165. //Otherwise, the grid value is ~ and it's a miss, change view grid to O
  166. else{
  167. printf("Miss!\n");
  168. Comp_view_grid[coord1][coord2] = Miss.name[0];
  169. }
  170.  
  171. //Call custom functions to check which computer ships still survive
  172. if(a1==0){
  173. a1 = CompShipCheck(Comp_hide_grid, &Aircraft_Carrier);
  174. }
  175. if(b1==0){
  176. b1 = CompShipCheck(Comp_hide_grid, &Battleship);
  177. }
  178. if(c1==0){
  179. c1 = CompShipCheck(Comp_hide_grid, &Cruiser);
  180. }
  181. if(d1==0){
  182. d1 = CompShipCheck(Comp_hide_grid, &Destroyer);
  183. }
  184. if(s1==0){
  185. s1 = CompShipCheck(Comp_hide_grid, &Submarine);
  186. }
  187.  
  188. //Game over condition; all computer ships are sunk, victory for the player
  189. if(a1==1 && b1==1 && c1==1 && d1==1 && s1==1){
  190. printf("YOU WIN!\n");
  191. printf("\n");
  192. printf("Your board: \n");
  193. PrintGrid(Player_view_grid);
  194. printf("Shots taken: (O-miss, X-hit) \n");
  195. PrintGrid(Comp_view_grid);
  196. //Initialize variable for use in FileInterface
  197. winner = 1;
  198. break;
  199. }
  200.  
  201. printf("\n");
  202.  
  203. //Change turns
  204. turn=0;
  205. }
  206.  
  207. else{ //Now the computer plays
  208. printf("Computer's turn: \n");
  209. sleep(750); //Pause the program for .75 seconds to simulate the computer 'thinking'
  210.  
  211. //Generate random number 0-9 for target coordinates
  212. coord1=rand()%10;
  213. coord2=rand()%10;
  214. //Convert int to char for printing to screen
  215. coord1char=IntToChar(coord1);
  216. check=1;
  217.  
  218. //Loop to check if generating coordinate has already been fired upon
  219. while(check){
  220. if(Player_view_grid[coord1][coord2] == Hit.name[0] || Player_view_grid[coord1][coord2] == Miss.name[0]){
  221. coord1=rand()%10;
  222. coord2=rand()%10;
  223. }
  224. else{
  225. check = 0;
  226. }
  227. }
  228.  
  229. printf("The computer fired at point %c%d. \n", coord1char, coord2);
  230.  
  231. //Check if hit on player's grid, change corredsponding value to X on view grid
  232. if(Player_view_grid[coord1][coord2] != '~'){
  233. printf("Direct hit!\n");
  234. Player_view_grid[coord1][coord2] = Hit.name[0];
  235. }
  236.  
  237. //Otherwise, it's a miss and change corresponding value to O on view grid
  238. else{
  239. printf("Miss!\n");
  240. Player_view_grid[coord1][coord2] = Miss.name[0];
  241. }
  242.  
  243. //Call custom functions to check which player ships still survive
  244. if(a2==0){
  245. a2 = PlayerShipCheck(Player_view_grid, &Aircraft_Carrier);
  246. }
  247. if(b2==0){
  248. b2 = PlayerShipCheck(Player_view_grid, &Battleship);
  249. }
  250. if(c2==0){
  251. c2 = PlayerShipCheck(Player_view_grid, &Cruiser);
  252. }
  253. if(d2==0){
  254. d2 = PlayerShipCheck(Player_view_grid, &Destroyer);
  255. }
  256. if(s2==0){
  257. s2 = PlayerShipCheck(Player_view_grid, &Submarine);
  258. }
  259.  
  260. //Game over condition; all player ships are sunk, victory for the computer
  261. if(a2==1 && b2==1 && c2==1 && d2==1 && s2==1){
  262. printf("YOU LOSE!\n");
  263. winner = 0;
  264. printf("\n");
  265. printf("Your board: \n");
  266. PrintGrid(Player_view_grid);
  267. printf("Shots taken: (O-miss, X-hit) \n");
  268. PrintGrid(Comp_view_grid);
  269. break;
  270. }
  271. //Change turns back to player
  272. turn = 1;
  273. printf("\n");
  274.  
  275. //Print game boards; NOTE: you may want to maximize the screen, the game boards take up a lot of space
  276. printf("Your board: \n");
  277. PrintGrid(Player_view_grid);
  278. printf("Shots taken: (O-miss, X-hit) \n");
  279. PrintGrid(Comp_view_grid);
  280. }
  281.  
  282. }
  283. //Call custom function to update records by writing to text file
  284. FileInterface(winner);
  285.  
  286. check=1;
  287. //Prompt user if they wish to play again
  288. while(check){
  289. printf("\nWould you like to play again (Yes or No)?\n");
  290. scanf("%s", ans);
  291. if(strcmp(ans,"No")== 0){
  292. choice = 0;
  293. check = 0;
  294. }
  295.  
  296. //If they don't input 'Yes' or 'No, reprompt
  297. else if(strcmp(ans,"Yes")!=0){
  298. printf("Not a valid answer, try again.\n");
  299. }
  300. else{
  301. check = 0;
  302. }
  303. }
  304.  
  305. //If choice == 1, return to beginning of do-while, otherwise end game
  306. }while(choice);
  307.  
  308. printf("Thanks for playing!\n");
  309. system("PAUSE");
  310. return 0;
  311. }
  312.  
  313. //Function for assigning the computer's ships, takes in Computer's grid and each different ship type
  314. //Assigns the first letter of the ship name at the specific locations in the char grid
  315. void AssignCompGrid(char array[][WIDTH], struct ship *s){
  316.  
  317. //Delcare variables for use
  318. int i, n1, n2, align, check=1;
  319.  
  320. //Generates starting positions, checks to make sure no possible intersections
  321. while(check){
  322. n1=rand()%10;
  323. n2=rand()%10;
  324. //Call custom function for checking intersections; if it returns 0, go back and generate new start coordinates
  325. if(CompIntersectCheck(array, n1, n2, s)){
  326. check = 0;
  327. }
  328. }
  329.  
  330. align = rand()%2; //Align randomly orients the ships; if 1 then ship is horizontal, if 0 it is vertical
  331.  
  332. //If the ship's starting point is too far to the right and bottom (lower right corner of the grid)
  333. if(n1+((s->size)-1)>9 && n2+((s->size)-1)>9){
  334. for(i=0; i<(s->size); i++){
  335. if(align){ //If the ship is horizontal, increment up
  336. array[n1][n2-i] = s->name[0];
  337. }
  338. else{ //If vertical, increment left
  339. array[n1-i][n2] = s->name[0];
  340. }
  341. }
  342. }
  343.  
  344. //If the ship's starting point is only too close to the bottom
  345. else if(n1+((s->size)-1)>9){
  346. for(i=0; i<(s->size); i++){
  347. array[n1][n2+i] = s->name[0]; //Increment right
  348. }
  349. }
  350.  
  351. //If the ship's starting point is only too close to the right
  352. else if(n2+((s->size)-1)>9){
  353. for(i=0; i<(s->size); i++){
  354. array[n1+i][n2] = s->name[0]; //Increment down
  355. }
  356. }
  357.  
  358. //If there are no issues of running off the board, align the ship horizontal if align=1
  359. else if(align==1){
  360. for(i=0; i<(s->size); i++){
  361. array[n1][n2+i] = s->name[0];
  362. }
  363. }
  364.  
  365. //Otherwise, align=0 and the ship is aligned vertically
  366. else if(align==0){
  367. for(i=0; i<(s->size); i++){
  368. array[n1+i][n2] = s->name[0];
  369. }
  370. }
  371. }
  372.  
  373. //Function that checks for ship intersections on the computer grid
  374. int CompIntersectCheck(char array[][WIDTH], int n1, int n2, struct ship *s){
  375. int i, check=1;
  376. //Checks from start point and goes in all four directions as far as the ship size dictates
  377. for(i=0; i<((s->size)); i++){
  378. if(array[n1][n2+i] != '~'||array[n1][n2-i]!='~'||array[n1+i][n2] != '~' || array[n1-i][n2]!= '~'){
  379. check=0;//If non-~ values are found, return 0
  380. break;
  381. }
  382. }
  383. //If all values were ~, nothing intersects and function returns 1
  384. return check;
  385. }
  386.  
  387. //Function for assigning the player's ships on the grid, takes in grid and each of the different ship types
  388. void AssignPlayerGrid(char array[][WIDTH], struct ship *s){
  389.  
  390. int i, j=0, coord2, coord4, swap;
  391. char coord1, coord3, temp1[3], temp2[3];
  392. //Loop used to keep reprompting user if errors are made in entering coordinates
  393. while(j==0){
  394. //Prompts user for start and end coordinates, reads them in as strings
  395. printf("Please enter the beginning and ending coordinates of your %s: \n", (s->name));
  396. scanf("%s %s", temp1, temp2);
  397. //Parses each coordinate into two separate values
  398. coord1 = temp1[0];
  399. coord2 = temp1[1]-'0';//converts numerical char into int value
  400. coord3 = temp2[0];
  401. coord4 = temp2[1]-'0';
  402. //Calls custom function for converting char to int
  403. coord1 = CharToInt(coord1);
  404. coord3 = CharToInt(coord3);
  405.  
  406. //Calls custom function for checking intersections
  407. if(PlayerIntersectCheck(array, coord1, coord2, coord3, coord4)){
  408. printf("You already have a ship in that area.\n");
  409. }
  410.  
  411. //By default, the coordinates are interpreted right to left, up to down
  412. //If the user enters coordinates in 'backwards', swap values
  413. else{
  414. if(coord1>coord3){
  415. swap = coord1;
  416. coord1 = coord3;
  417. coord3 = swap;
  418. }
  419. if(coord2>coord4){
  420. swap = coord2;
  421. coord2 = coord4;
  422. coord4 = swap;
  423. }
  424.  
  425. //For horizontal ship
  426. if(coord1==coord3){
  427. if((coord4-coord2) !=((s->size)-1)) //If the length of inputted coordinates does not match ship size
  428. printf("You have entered invalid coordinates. \n");
  429.  
  430. else{ //Valid coordinates entered
  431. for(i=0; i<=(coord4-coord2); i++){
  432. array[coord1][coord2+i] = s->name[0];
  433. j=1;
  434. }
  435. }
  436. }
  437.  
  438. //For vertical ship
  439. else if(coord2==coord4){
  440. if((coord3-coord1) != ((s->size)-1)){ //Again, if length does not match ship size
  441. printf("You have entered invalid coordinates.\n");
  442. }
  443.  
  444. else{ //Valid cooraintes entered
  445. for(i=0; i<=(coord3-coord1); i++){
  446. array[coord1+i][coord2] = s->name[0];
  447. j=1;
  448. }
  449. }
  450. }
  451.  
  452. else{ //In cases of inputting coordinates diagonally
  453. printf("You have entered invalid coordinates.\n");
  454. }
  455. }
  456. }
  457. }
  458.  
  459. //Function that checks for ship intersections on the player grid
  460. int PlayerIntersectCheck(char array[][WIDTH], int coord1, int coord2, int coord3, int coord4){
  461. int i, check=0;
  462.  
  463. //If ship is aligned horizontally
  464. if(coord1==coord3){
  465. for(i=0; i<=(coord4-coord2);i++){
  466. if(array[coord1][coord2+i]!='~'){ //If any value along horizontal within size is not ~, a ship is already there
  467. check=1;
  468. break;
  469. }
  470. }
  471. }
  472.  
  473. //If ship is aligned vertically
  474. else if(coord2==coord4){
  475. for(i=0;i<=(coord3-coord1);i++){
  476. if(array[coord1+i][coord2]!='~'){ //If any value along horizontal within size is not ~, a ship is already there
  477. check=1;
  478. break;
  479. }
  480. }
  481. }
  482. return check;
  483. }
  484.  
  485. //Function that prints out desired grid
  486. void PrintGrid(char array[][WIDTH]){
  487. int i, j;
  488. printf(" ");
  489. //Print out 0-9 across the top
  490. for(i=0; i<10; i++){
  491. printf("%d ", i);
  492. }
  493.  
  494. //Print dashes to separate top numbers from board
  495. printf("\n ");
  496. for(i=0;i<19; i++){
  497. printf("-");
  498. }
  499.  
  500. //Print out rows, with each row starting with a corresponding A-J
  501. printf("\n");
  502. for(i=0; i<10; i++){
  503. printf("%c|", IntToChar(i));
  504. for(j=0; j<10; j++){
  505. printf("%c ", array[i][j]);
  506. }
  507. printf("\n");
  508. }
  509. }
  510.  
  511. //Converts char A-J to int value of 0-9 by casting char to ASCII value
  512. int CharToInt(char letter){
  513. int num;
  514. num = (int)letter-65;
  515. return num;
  516. }
  517.  
  518. //Converts int 0-9 to char A-J by added 65 to int value and casting to char
  519. char IntToChar(int num){
  520. char letter;
  521. letter = (char)(num+65);
  522. return letter;
  523. }
  524.  
  525. //Runs a check to see if a given ship is still present on computer's grid
  526. int CompShipCheck(char array[][WIDTH], struct ship *s){
  527. int i,j, check=1;
  528.  
  529. for(i=0; i<10; i++){
  530. for(j=0; j<10; j++){
  531. if(array[i][j]==s->name[0]){ //If the first char of a ship name is anywhere on the grid, the ship is still there
  532. return 0;
  533. }
  534. else{
  535. check = 1;
  536. }
  537. }
  538. }
  539.  
  540. //Otherwise, player has sunk the computer's ship
  541. if(check = 1){
  542. printf("You have sunk the computer's %s.\n", s->name);
  543. return 1;
  544. }
  545. }
  546.  
  547. //Runs a check to see if a given ship is still present on the player's grid
  548. int PlayerShipCheck(char array[][WIDTH], struct ship *s){
  549. int i,j, check=1;
  550.  
  551. for(i=0; i<10; i++){
  552. for(j=0; j<10; j++){
  553. if(array[i][j]==s->name[0]){ //If the first char of a ship name is anywhere on the grid, the ship is still there
  554. return 0;
  555. }
  556. else{
  557. check = 1;
  558. }
  559. }
  560. }
  561.  
  562. //Otherwise, computer has sunk the player's ship
  563. if(check = 1){
  564. printf("The computer has sunk your %s.\n", s->name);
  565. return 1;
  566. }
  567. }
  568.  
  569. //Function that accesses a file to keep a running record of human vs. computer wins
  570. void FileInterface(int winner){
  571. //Initialize file pointer and variables for score
  572. FILE *statFile;
  573. int playerscore, compscore;
  574.  
  575. //Open the file and read in the current scores
  576. statFile = fopen("winner.in", "r");
  577. fscanf(statFile, "%*s %d", &playerscore);
  578. fscanf(statFile, "%*s %d", &compscore);
  579.  
  580. //If winner=1, the human won the game, increment their score
  581. if(winner){
  582. playerscore++;
  583. }
  584.  
  585. //Else winner=0, the computer won; increment computer score
  586. else{
  587. compscore++;
  588. }
  589. fclose(statFile);
  590.  
  591. //Write the new results into the file
  592. fopen("winner.in", "w");
  593. fprintf(statFile, "Player %d\n", playerscore);
  594. fprintf(statFile, "Computer %d", compscore);
  595. fclose(statFile);
  596.  
  597. printf("\nThe current score is Player-%d, Computer-%d.\n", playerscore, compscore);
  598. }
Add Comment
Please, Sign In to add comment