Advertisement
Guest User

Untitled

a guest
Jul 20th, 2019
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.11 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <algorithm>
  4. #include <ctime>
  5. #include <array>
  6. #include <memory>
  7. typedef std::array<short int, 100> Grid;
  8. typedef short int Sint16;//Short Integer
  9. typedef std::string String;
  10. //Global Constants
  11. const std::array<String, 5> SHIP_NAMES = { "Destroyer", "Submarine", "Cruiser", "Battleship", "Airftact Carrier" };
  12. const Sint16 SHIP_HEALTH_RESET[5] = { 2, 3, 3, 4, 5 };
  13. const bool godMode = false;
  14. //Command Line Functions
  15. //Prints out a string in the command line
  16. void print(String message, bool newLine = true)
  17. {
  18. newLine ? std::cout << message << "\n" : std::cout << message;
  19. }
  20. void print(char* message, bool newLine = true)
  21. {
  22. newLine ? std::cout << message << "\n" : std::cout << message;
  23. }
  24. void print(int message, bool newLine = true)
  25. {
  26. newLine ? std::cout << message << "\n" : std::cout << message;
  27. }
  28. void print(short int* grid)
  29. { std::cout << " A B C D E F G H I J \n";
  30. for (int i = 0; i < 10; i++)
  31. { std::cout << i+1 << " ";
  32. for (int j = 0; j < 10; j++)
  33. { switch(grid[j + (10 * i)])
  34. { case 0:
  35. std::cout << '-'; break;
  36. case 1:
  37. std::cout << 'X'; break;
  38. case 2:
  39. std::cout << 'O'; break;
  40. case 3:
  41. std::cout << '+'; break;
  42. case 4:
  43. std::cout << '@'; break;
  44. case 5:
  45. std::cout << '#'; break;
  46. case 6:
  47. std::cout << '~'; break;
  48. }
  49. if (i != 10)
  50. { std::cout << " ";
  51. }
  52. }
  53. std::cout << "\n";
  54. }
  55. }
  56. //Returns user input
  57. String input()
  58. {
  59. String foo;
  60. std::cin >> foo;
  61. return foo;
  62. }
  63. //Flips a coin and takes user input
  64. bool coinToss()
  65. { String foo;
  66. Sint16 coinSide;
  67. coinSide = rand() % 2;
  68. do
  69. {//Repeat until a valid answer is given
  70. if (!godMode) system("CLS");
  71. print(" Heads or Tails? heads/tails");
  72. foo = input();
  73. } while (foo[0] != 'h' && foo[0] != 't');
  74. if (foo[0] == 'h' && coinSide == 0)
  75. {//User got heads correct
  76. print("heads, you win, you go first");
  77. return true;
  78. }
  79. else if (foo[0] == 't' && coinSide == 1)
  80. {//User got tails correct
  81. print("tails, you win, you go first");
  82. return true;
  83. }
  84. else
  85. {//Computer wins toss
  86. coinSide ? print("tails, you lost, AI goes first") : print("heads, you lost, AI goes first");
  87. return false;
  88. }
  89. }
  90. //Mathmatical Functions
  91. //Squares a number
  92. float sqr(float num)
  93. {
  94. return num * num;
  95. }
  96. //Functions
  97. void nullGrid(Sint16* pArray, int arraySize = 100)
  98. { //Nulls out a 1d grid of defined size
  99. for (int i = 0; i < arraySize; i++)
  100. {//Go through all rows in the array
  101. pArray[i] = 0;
  102. }
  103. }
  104. bool coordToInt(Sint16* coordX, Sint16* coordY, String coords)
  105. {
  106. if (coords[0] >= 'a' && coords[0] <= 'j')
  107. {//First char in coordsiantes is from 'a' to 'j'
  108. *coordX = coords[0] - 'a';
  109. }
  110. else if (coords[0] >= 'A' && coords[0] <= 'J')
  111. {//First char in coords is from 'A' to 'J'
  112. *coordX = coords[0] - 'A';
  113. }
  114. else
  115. {//coordinate location is invalid
  116. return false;
  117. }
  118. if (coords[1] >= '1' && coords[1] <= '9')
  119. {//Second char in coords is from '1' to '9'
  120. if (coords[1] == '1' && coords[2] == '0')
  121. {//coords ends in a 10
  122. *coordY = 9;
  123. }//Coord does not end in 10
  124. else
  125. { *coordY = coords[1] - '1';
  126. }
  127. return true;
  128. }//Invalid final coordiante
  129. else
  130. { return false;
  131. }
  132. }
  133. String intToCoord(Sint16 coordX, Sint16 coordY)
  134. {
  135. String foo;
  136. foo[0] = coordX + 'A';
  137. if (coordY == 9)
  138. { foo[1] = '1';
  139. foo[2] = '0';
  140. }
  141. else
  142. { foo[1] = coordY + '1';
  143. }
  144. }
  145. void recordGrid(Sint16* pArray, Sint16 coordX, Sint16 coordY, Sint16 inputValue)
  146. {
  147. pArray[coordX + (10 * coordY)] = inputValue;
  148. }
  149. Sint16 getGridValue(Sint16* pArray, Sint16 coordX, Sint16 coordY)
  150. {
  151. return pArray[coordX + (10 * coordY)];
  152. }
  153. void shipSetup(Sint16* playerShips, bool rand = false)
  154. {//Sets up the ships int he beginning of a new game
  155. String foo;
  156. Sint16 shipX;
  157. Sint16 shipY;
  158. std::time_t time = std::time(nullptr);
  159. bool isLocationValid;
  160. for (int i=0; i<5; i++)
  161. {//Repeat ship setup 5 times
  162. isLocationValid = false;
  163. if (!rand)
  164. {//Ships to be placed manually
  165. if (!godMode) system("CLS");
  166. print("This is your grid currently");
  167. print(playerShips);
  168. print("Enter the location of your ", false);
  169. print((SHIP_NAMES[i]), false);
  170. print(" Length ", false);
  171. print(SHIP_HEALTH_RESET[i], false);
  172. print(". A1 to J10");
  173. foo = input();
  174. if (coordToInt(&shipX, &shipY, foo))
  175. {//Coordinates are valid
  176. print("Would you like the ship to be vertical or horizontal? v/h");
  177. foo = input();
  178. switch(foo[0])
  179. {//Player selects horizontal
  180. case 'h':
  181. //Horizontal
  182. if (shipX+SHIP_HEALTH_RESET[i] < 10 )
  183. {//Ship does not spill to next line
  184. for (int j = 0; j < SHIP_HEALTH_RESET[i]; j++)
  185. { if (getGridValue(playerShips, shipX + j, shipY))
  186. {//Invalid ship location
  187. print("A ship is in the way");
  188. isLocationValid = false;
  189. break;
  190. }//Valid
  191. else isLocationValid = true;
  192. }
  193. }
  194. break;
  195. case 'v':
  196. if (shipY + SHIP_HEALTH_RESET[i] < 10)
  197. {//Ship doesn't spill to next line
  198. for (int j = 0; j < SHIP_HEALTH_RESET[i]; j++)
  199. { if (getGridValue(playerShips, shipX, shipY + j))
  200. {//Invalid ship location
  201. print("A ship is in the way");
  202. isLocationValid = false;
  203. break;
  204. }//Valid
  205. else isLocationValid = true;
  206. }
  207. }
  208. break;
  209. default:
  210. //Not vertical or horizontal selection
  211. print("You didn't select vertical or horizontal v/h");
  212. isLocationValid = false;
  213. break;
  214. }
  215. }//Invalid coordinate conversion
  216. else
  217. { isLocationValid = false;
  218. }
  219. while (!isLocationValid)
  220. {//Repeats until user complies with constraints or is happy with selection
  221. if (!godMode) system("CLS");
  222. print(playerShips);
  223. print("Please enter a valid location of your " + SHIP_NAMES[i] + " Length ", false);
  224. print(SHIP_HEALTH_RESET[i], false);
  225. print(". A1 to J10");
  226. foo = input();
  227. if (coordToInt(&shipX, &shipY, foo))
  228. {//Coordinates are valid
  229. print("Would you like the ship to be vertical or horizontal? v/h");
  230. foo = input();
  231. switch (foo[0])
  232. {//Player selects horizontal
  233. case 'h':
  234. //Horizontal
  235. if (shipX + SHIP_HEALTH_RESET[i] < 10)
  236. {//Ship does not spill to next line
  237. for (int j = 0; j < SHIP_HEALTH_RESET[i]; j++)
  238. { if (getGridValue(playerShips, shipX + j, shipY))
  239. {//Invalid ship location
  240. print("A ship is in the way");
  241. isLocationValid = false;
  242. break;
  243. }//Valid
  244. else isLocationValid = true;
  245. }
  246. }
  247. break;
  248. case 'v':
  249. if (shipY + SHIP_HEALTH_RESET[i] < 10)
  250. {//Ship doesn't spill to next line
  251. for (int j = 0; j < SHIP_HEALTH_RESET[i]; j++)
  252. { if (getGridValue(playerShips, shipX, shipY + j))
  253. {//Invalid ship location
  254. print("A ship is in the way");
  255. isLocationValid = false;
  256. break;
  257. }//Valid
  258. else isLocationValid = true;
  259. }
  260. }
  261. break;
  262. default:
  263. //Not vertical or horizontal selection
  264. print("You didn't select vertical or horizontal v/h");
  265. isLocationValid = false;
  266. break;
  267. }
  268. }
  269. }
  270. if (isLocationValid)
  271. { for (int j = 0; j < SHIP_HEALTH_RESET[i]; j++)
  272. {//Records the ship into the player's grid
  273. foo[0] == 'h' ? recordGrid(playerShips, shipX + j, shipY, SHIP_HEALTH_RESET[i]) : recordGrid(playerShips, shipX, shipY + j, SHIP_HEALTH_RESET[i]);
  274. }
  275. }
  276. }//Ships are to be randomised
  277. else
  278. { print("Randomising AI ships");
  279. while (!isLocationValid)
  280. { foo[0] = std::rand() % 2;
  281. if (foo[0] == 0)
  282. {//Ship will be horizontal
  283. shipX = std::rand() % (10-i);
  284. shipY = std::rand() % 10;
  285. if (shipX + SHIP_HEALTH_RESET[i] < 10)
  286. {//Ship doesn't spill to next line
  287. for (int j = 0; j < SHIP_HEALTH_RESET[i]; j++)
  288. { if (getGridValue(playerShips, shipX+j, shipY + j))
  289. {//Invalid ship location
  290. print("A ship is in the way");
  291. isLocationValid = false;
  292. break;
  293. }//Valid
  294. else isLocationValid = true;
  295. }
  296. }
  297. if (isLocationValid)
  298. { for (int j=0; j<SHIP_HEALTH_RESET[i]; j++)
  299. { recordGrid(playerShips, shipX+j, shipY, SHIP_HEALTH_RESET[i]);
  300. }
  301. }
  302. }//Ship will be horizontal
  303. else
  304. { shipX = std::rand() % (10 - i);
  305. shipY = std::rand() % 10;
  306. if (shipY + SHIP_HEALTH_RESET[i] < 10)
  307. {//Ship doesn't spill to next line
  308. for (int j = 0; j < SHIP_HEALTH_RESET[i]; j++)
  309. { if (getGridValue(playerShips, shipX, shipY + j))
  310. {//Invalid ship location
  311. print("A ship is in the way");
  312. isLocationValid = false;
  313. break;
  314. }//Valid
  315. else isLocationValid = true;
  316. }
  317. }
  318. if (isLocationValid)
  319. { for (int j = 0; j < SHIP_HEALTH_RESET[i]; j++)
  320. { recordGrid(playerShips, shipX, shipY + j, SHIP_HEALTH_RESET[i]);
  321. }
  322. }
  323. }
  324. }
  325. }
  326. print(shipX);
  327. print(shipY);
  328. print(playerShips);
  329. std::time(&time);
  330. srand(time);
  331. }
  332. print("Ship setup is done.");
  333. std::cout << "\n";
  334. }
  335. Sint16 shootGrid(Sint16* pEnemyShips, String coords, Sint16* pPlayerTargeting = nullptr)
  336. {
  337. Sint16 foo;
  338. Sint16 coordX;
  339. Sint16 coordY;
  340. if (coordToInt(&coordX, &coordY, coords))
  341. {
  342. foo = getGridValue(pEnemyShips, coordX, coordY);
  343. if (foo == 0 || foo == 6)
  344. {//Targeted grid coordinate is sea or destroyed ship part
  345. print("You missed...");
  346. //Records and returns miss
  347. if (pPlayerTargeting)
  348. recordGrid(pPlayerTargeting, coordX, coordY, 2);
  349. return 0;
  350. }
  351. else if (foo > 1 && foo < 6)
  352. {//Targeted grid coordinate is a ship
  353. print("You hit the ennemy ship!");
  354. //Records a hit
  355. recordGrid(pEnemyShips, coordX, coordY, 6);
  356. if (pPlayerTargeting) recordGrid(pPlayerTargeting, coordX, coordY, 1);
  357. return foo;
  358. }
  359. }//Invalid coordinate
  360. else
  361. {
  362. return -1;
  363. }
  364. }
  365. //ENTRY POINT
  366. int main(int argc, char** argv)
  367. { //Variable Setup
  368. enum Direction : int {up, down, left, right};
  369. bool isRunning = true;
  370. bool isGameOver = false;
  371. bool isPlayer1First = false;
  372. bool isPlayer1Turn = false;
  373. bool isInputInvalid = false;
  374. bool isComputerHunting = false;
  375. Sint16 player1Ships[100];
  376. Sint16 player1Targeting[100];
  377. Sint16 player2Ships[100];
  378. Sint16 player2Targeting[100];
  379. Sint16 player1ShipHealth[5];
  380. Sint16 player2ShipHealth[5];
  381. Sint16 player1ShipsRemaining;
  382. Sint16 player2ShipsRemaining;
  383. Sint16 turnCount;
  384. String userInput;
  385. Sint16 shotOutcome = -1;
  386. Sint16 shotsTried = 0;
  387. Sint16 randomX;
  388. Sint16 randomY;
  389. Sint16 hitX;
  390. Sint16 hitY;
  391. Sint16 shipValue;
  392. Sint16 currentTry;
  393. bool isDirectionTarget[4] = { true, true, true, true };
  394. //Reset Values
  395. std::time_t time;
  396. while (isRunning)
  397. {//New game
  398. std::time(&time);
  399. srand(time);
  400. turnCount = 0;
  401. for (int i=0; i<100; i++)
  402. {
  403. player1Ships[i] = 0;
  404. player2Ships[i] = 0;
  405. player1Targeting[i] = 0;
  406. player2Targeting[i] = 0;
  407. }
  408. nullGrid(player1Ships, 100);
  409. nullGrid(player1Targeting, 100);
  410. nullGrid(player2Ships, 100);
  411. nullGrid(player2Targeting, 100);
  412. player1ShipsRemaining = 5;
  413. player2ShipsRemaining = 5;
  414. isInputInvalid = false;
  415. isComputerHunting = false;
  416. currentTry = 0;
  417. for (int i=0; i<5; i++)
  418. {
  419. player1ShipHealth[i] = SHIP_HEALTH_RESET[i];
  420. player2ShipHealth[i] = SHIP_HEALTH_RESET[i];
  421. }
  422. if (godMode)
  423. { print("Randomize ships?");
  424. userInput = input();
  425. if (userInput == "yes") shipSetup(player1Ships, true);
  426. else shipSetup(player1Ships);
  427. }
  428. else
  429. { shipSetup(player1Ships);
  430. }
  431. shipSetup(player2Ships, true);
  432. isPlayer1First = coinToss();
  433. isPlayer1Turn = isPlayer1First;
  434. isGameOver = false;
  435. while (!isGameOver)
  436. {//GAME LOOP
  437. if (!godMode) std::system("CLS");
  438. print("Your ships:");
  439. print(player1Ships);
  440. print("Your view of enemy's grid:");
  441. print(player1Targeting);
  442. if (godMode)
  443. { print("Enemiy Ships DEBUG:");
  444. print(player2Ships);
  445. }
  446. if (turnCount >= 50)
  447. { print("50 turns has passed, the game is a stalemate");
  448. isGameOver = true;
  449. }
  450. else if (isPlayer1Turn || isInputInvalid)
  451. {//Player 1's turn
  452. print("Where do you want to shoot? A1 to J10");
  453. userInput = input();
  454. shotOutcome = shootGrid(player2Ships, userInput, player1Targeting);
  455. if (shotOutcome > 0 && shotOutcome < 6)
  456. {//Hit registered
  457. player2ShipHealth[shotOutcome-1]--;
  458. if (player2ShipHealth[shotOutcome-1] <= 0)
  459. {//0 ship health left on hit ship
  460. print("The enemy's " + SHIP_NAMES[shotOutcome-1] + " has been destroyed!");
  461. player2ShipsRemaining--;
  462. isInputInvalid = false;
  463. turnCount++;
  464. }
  465. }
  466. else if (shotOutcome == 0)
  467. {//Missed shot
  468. print("You missed the enemy...");
  469. isInputInvalid = false;
  470. turnCount++;
  471. }//Off-grid hit
  472. else
  473. { while (shotOutcome == -1)
  474. {//Shot location is invalid
  475. print("Please enter a valid grid location. A1 to J10");
  476. userInput = input();
  477. shotOutcome = shootGrid(player2Ships, userInput, player1Targeting);
  478. isInputInvalid = true;
  479. }
  480. }
  481. //Change player turn
  482. isPlayer1Turn = false;
  483. }//Player 2 Turn (AI)
  484. else if (!isPlayer1Turn)
  485. { if (isComputerHunting)
  486. {//AI enabled
  487. //Up Check
  488. if (hitY-1 >= 0)
  489. { shipValue = getGridValue(player2Targeting, hitX, hitY-1);
  490. if (shipValue)
  491. { isDirectionTarget[Direction::up] = false;
  492. }
  493. else
  494. { isDirectionTarget[Direction::up] = true;
  495. }
  496. }
  497. else
  498. { isDirectionTarget[Direction::up] = false;
  499. }//Left Check
  500. if (hitX-1 >= 0)
  501. { shipValue = getGridValue(player2Targeting, hitX-1, hitY);
  502. if (shipValue)
  503. { isDirectionTarget[Direction::left] = false;
  504. }
  505. else
  506. { isDirectionTarget[Direction::left] = true;
  507. }
  508. }
  509. else
  510. { isDirectionTarget[Direction::up] = false;
  511. }//Down Check
  512. if (hitY+1 <= 10)
  513. { shipValue = getGridValue(player2Targeting, hitX, hitY+1);
  514. if (shipValue)
  515. { isDirectionTarget[Direction::down] = false;
  516. }
  517. else
  518. { isDirectionTarget[Direction::down] = true;
  519. }
  520. }
  521. else
  522. { isDirectionTarget[Direction::up] = false;
  523. }//Right Check
  524. if (hitX+1 <= 10)
  525. { shipValue = getGridValue(player2Targeting, hitX, hitY+1);
  526. if (shipValue)
  527. { isDirectionTarget[Direction::right] = false;
  528. }
  529. else
  530. { isDirectionTarget[Direction::right] = true;
  531. }
  532. }
  533. else
  534. { isDirectionTarget[Direction::up] = false;
  535. }
  536. switch (currentTry)
  537. { case Direction::up:
  538. if (isDirectionTarget[Direction::up])
  539. { userInput = intToCoord(hitX, hitY-1);
  540. shotOutcome = shootGrid(player1Ships, userInput);
  541. print("Computer shot grid ", false);
  542. print(char( hitX + 'A' ), char(hitY + '1'-1));
  543. if (shotOutcome >= 1 && shotOutcome <= 5)
  544. { player1ShipHealth[shotOutcome-1]--;
  545. hitY--;
  546. }
  547. currentTry++;
  548. break;
  549. }
  550. case Direction::left:
  551. if (isDirectionTarget[Direction::left])
  552. { userInput = intToCoord(hitX-1, hitY);
  553. shotOutcome = shootGrid(player1Ships, userInput);
  554. print(char( hitX + 'A'-1 ), char(hitY + '1'));
  555. if (shotOutcome >= 1 && shotOutcome <= 5)
  556. { player1ShipHealth[shotOutcome-1]--;
  557. hitX--;
  558. }
  559. currentTry++;
  560. break;
  561. }
  562. case Direction::down:
  563. if (isDirectionTarget[Direction::down])
  564. { userInput = intToCoord(hitX, hitY+1);
  565. shotOutcome = shootGrid(player1Ships, userInput);
  566. print( char(hitX + 'A' ), char(hitY + '1'+1));
  567. if (shotOutcome >= 1 && shotOutcome <= 5)
  568. { player1ShipHealth[shotOutcome-1]--;
  569. hitY++;
  570. }
  571. currentTry++;
  572. break;
  573. }
  574.  
  575. case Direction::right:
  576. if (isDirectionTarget[Direction::right])
  577. { userInput = intToCoord(hitX+1, hitY);
  578. shotOutcome = shootGrid(player1Ships, userInput);
  579. print( char(hitX + 'A'+1) , char(hitY + '1'));
  580. if (shotOutcome >= 1 && shotOutcome <= 5)
  581. { player1ShipHealth[shotOutcome-1]--;
  582. hitX++;
  583. }
  584. currentTry++;
  585. break;
  586. }
  587. case 5:
  588. currentTry = 0;
  589. isComputerHunting = false;
  590. break;
  591. }
  592.  
  593. }//Computer has no idea where to shoot
  594. else
  595. { randomX = rand() % 10;
  596. randomY = rand() % 10;
  597. userInput[0] = randomX + 'A';
  598. if (randomY == 9)
  599. { userInput[1] = 1;
  600. userInput[2] = 0;
  601. }
  602. else userInput[1] = randomY + '1';
  603. shotOutcome = shootGrid(player1Ships, userInput, player2Targeting);
  604. print("Computer shot grid ", false);
  605. print( char(randomX + 'A') , char(randomY + '1'));
  606. if (shotOutcome >= 1 && shotOutcome <= 5)
  607. {//Shot was a hit
  608. hitX = randomX;
  609. hitY = randomY;
  610. player1ShipHealth[shotOutcome-1];
  611. isComputerHunting = true;
  612. }
  613. }
  614. isPlayer1Turn = true;
  615. turnCount++;
  616. }
  617. if (player1ShipsRemaining == 0 || player2ShipsRemaining == 0 || isGameOver)
  618. {//Player 1 has lost all ships
  619. player1ShipsRemaining == 0 ? print("You are victorious!") : print("You have lost...");
  620. print("Play again? y/n");
  621. userInput = input();
  622. if (userInput[0] == 'n')
  623. {//Quit is picked
  624. print("Are you sure you want to quit? y/n");
  625. userInput = input();
  626. while (userInput[0] == 'n')
  627. {//User is indecisive
  628. print("Play again? y/n");
  629. userInput = input();
  630. if (userInput[0] == 'n')
  631. {//Quit is picked again
  632. print("Are you sure you want to quit? y/n");
  633. userInput = input();
  634. if (userInput[0] == 'y')
  635. {//Quit is confirmed
  636. break;
  637. }
  638. }
  639. }
  640. if (userInput[0] == 'y')
  641. {//Quit is confirmed
  642. isGameOver = true;
  643. isRunning = false;
  644. print("Thanks for playing!");
  645. }
  646. }
  647. else
  648. { print("Resetting game...");
  649. isGameOver = true;
  650. }
  651. }
  652. }
  653. }//CLEANUP
  654. print("Cleaning up game...");
  655. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement