// Finishing Battleship game import std.stdio: writeln, write, readf; import std.conv: to; import std.random: uniform; // game states enum GameState { MENU, PLAY, HELP, EXIT } /* gameState = MENU; -> mainMenu(); // managing main menu gameState = HELP; -> help(); // how to play gameState = PLAY; -> play(); // game logic gameState = EXIT; -> break out from the loop and quit */ immutable int NUM_SHIPS = 10; void main() { // gameState variable GameState gameState = GameState.MENU; // while gameState does not equal to EXIT, run the game while(gameState != GameState.EXIT) { if(gameState == GameState.MENU) { mainMenu(gameState); } else if(gameState == GameState.HELP) { help(gameState); } if(gameState == GameState.PLAY) { gamePlay(gameState); } } writeln("Thanks for playing!"); } // print 30 empty lines (for formatting) void clear() { for(int i = 0; i < 30; i++) { writeln(); } } // MENU state: the code for handling main menu void mainMenu(ref GameState gameState) { clear(); writeln("Hi and welcome!"); writeln(); writeln("(1) Play"); writeln("(2) Help"); writeln("(3) Exit"); writeln(); write("Choice >> :_"); char c; readf(" %s", c); if(c == '1' || c == 'p' || c == 'P') { gameState = GameState.PLAY; } else if(c == '2' || c == 'h' || c == 'H') { gameState = GameState.HELP; } else if(c == '3' || c == 'e' || c == 'E') { gameState = GameState.EXIT; } else { writeln("\n\nError! Please try again!\n"); } } // HELP state: displaying helpful information void help(ref GameState gameState) { clear(); writeln("1. Each player must secretly place their ships on a grid \nof ten columns by ten rows."); writeln("\n2. Each player will also be in possession of a second grid \nof the same size. Where the first grid is their own ships, \nthe second one (which is blank at the beginning of the game) \nis a mirror of their opponent’s battlefield."); writeln("\n3. Players pick a square at random, calling it by its row and \ncolumn number. This represents their firing a missile \ndirectly at that square."); writeln("\n4. The player who successfully locates all their opponent’s \nships first by hitting each square they occupy is the winner \nas all ships have been destroyed."); write("\nChoice(2) >> :_"); char c; readf(" %s", c); gameState = GameState.MENU; } // PLAY state: game logic void gamePlay(ref GameState gameState) { clear(); // creating our maps char[5][5] playerMap = ' '; char[5][5] enemyMap = ' '; char[5][5] territory = ' '; // initializing ships initShipPos(playerMap); // init player's ships (manually, by the player himself) initEnemyShipPos(enemyMap); // init enemy's ships (randomization) int player_ships_destroyed = 0; int enemy_ships_destroyed = 0; bool gameWon = false; while(gameState != GameState.EXIT) { // displaying player's map writeln("Your MAP, Captain: "); display(playerMap); // displaying empty territory writeln("\n", "Enemy's hiding somewhere, Captain: "); display(territory); writeln("Let's scout the area and attack (", player_ships_destroyed, " of ", NUM_SHIPS, " ships destroyed)!"); // reading user input char x; char y; write("X coord to attack(e to exit): >>_"); readf(" %s", x); if(x == 'e') { // if input = 'e', exit the game gameState = GameState.EXIT; } write("Y coord to attack(e to exit): >>_"); readf(" %s", y); if(y == 'e') { // if input = 'e', exit the game gameState = GameState.EXIT; } // converting (x, y) coordinates to integers int ix = to!int(x - '0'); int iy = to!int(y - '0'); clear(); // clearing the screen by inserting new lines // if (x, y) coordinates are greater than the length of the map or negative, go to the begining if(ix < 0 || ix > territory.length-1 || iy < 0 || iy > territory.length-1) { continue; } // if the coordinate isn't empty, go to the begining if(territory[ix][iy] != ' ') { continue; } // if player hit enemy's ship, mark it with 'x', otherwise mark it with'o' if(enemyMap[ix][iy] == '1') { territory[ix][iy] = enemyMap[ix][iy] = 'x'; player_ships_destroyed++; } else { territory[ix][iy] = enemyMap[ix][iy] = 'o'; } // if player destroyed all of the enemy's ships, exit if(player_ships_destroyed >= NUM_SHIPS) { gameState = GameState.EXIT; gameWon = true; // the player has won } enemyAttack(playerMap, enemy_ships_destroyed); // if enemy destroyed all of the player's ships, exit if(enemy_ships_destroyed >= NUM_SHIPS) { gameState = GameState.EXIT; gameWon = false; // the player has lost } } clear(); if(gameWon) { writeln("YOU WON!"); } else { writeln("Your MAP, Captain: "); display(playerMap); writeln("\nYOU LOST!"); } } // read the comments in the gamePlay function, the code is pretty much the same void initShipPos(ref char[5][5] array) { int i = 0; while(i < NUM_SHIPS) { display(array); writeln("Enter your ship's position(", i, " of ", NUM_SHIPS," ships):"); char x; char y; write("X coord: >>_"); readf(" %s", x); write("Y coord: >>_"); readf(" %s", y); int ix = to!int(x - '0'); int iy = to!int(y - '0'); clear(); if(ix < 0 || ix > array.length-1 || iy < 0 || iy > array.length-1) { writeln("\nERROR! TRY AGAIN!"); continue; } if(array[ix][iy] != ' ') { writeln("\nERROR! SHIP (", ix, ", ", iy, ") ALREADY EXISTS!"); writeln("TRY AGAIN!\n"); continue; } array[ix][iy] = '1'; i++; } } // randomizing enemy's ships void initEnemyShipPos(ref char[5][5] array) { int i = 0; while(i < NUM_SHIPS) { int x = uniform(0, array.length.to!int); int y = uniform(0, array.length.to!int); if(array[x][y] != ' ') { continue; } array[x][y] = '1'; i++; } } void enemyAttack(ref char[5][5] array, ref int ships_destroyed) { while(true) { int x = uniform(0, array.length.to!int); int y = uniform(0, array.length.to!int); // if enemy has already attacked this position, go to the beginig of the loop if(array[x][y] == 'x' || array[x][y] == 'o') { continue; } // if ship is found, destroy the ship if(array[x][y] == '1') { array[x][y] = 'x'; ships_destroyed++; } else { array[x][y] = 'o'; // otherwise, mark it with 'o' } break; } } // printing the entire array in a table-like format void display(char[5][5] array) { write(" "); for(int i = 0; i < array.length; i++) { write(" ", i); } writeln(); writeln("_ _ _ _ _ _ _ _ _ _ _ _"); for(int i = 0; i < array.length; i++) { write(i, " "); for(int j = 0; j < array[i].length; j++) { write(" | ", array[i][j]); } writeln(); writeln("_ _ _ _ _ _ _ _ _ _ _ _"); } writeln(); writeln(); }