From 90379fe39b140d86a53ba1ee2e7a949c1cfb6a78 Mon Sep 17 00:00:00 2001 From: Mehrdad Shirvani Date: Mon, 12 May 2025 23:35:40 +0330 Subject: [PATCH] feat: add BattleShipClient --- src/main/java/Client/BattleShipClient.java | 302 +++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 src/main/java/Client/BattleShipClient.java diff --git a/src/main/java/Client/BattleShipClient.java b/src/main/java/Client/BattleShipClient.java new file mode 100644 index 0000000..02ca9fb --- /dev/null +++ b/src/main/java/Client/BattleShipClient.java @@ -0,0 +1,302 @@ +package Client; + +import javax.sound.sampled.*; +import java.io.*; +import java.net.Socket; +import java.net.URL; +import java.util.*; +import Client.utils.AnsiColor; + +public class BattleShipClient { + private static final String SPACING = " "; + private static final String IP_ADDRESS = "127.0.0.1"; + private static final int PORT_NUMBER = 3737; + static final int SIZE = 10; + static final Random rand = new Random(); + + private final Socket clientSocket; + BattleShipCell[][] playerBoard; + BattleShipCell[][] enemyBoard; + + static int lastEnemyRow; + static int lastEnemyCol; + + + volatile boolean isBoardSet = false; + boolean isTurn = false; + volatile boolean otherPlayerJoined = false; + DataOutputStream out; + + public BattleShipClient(Socket clientSocket) { + this.clientSocket = clientSocket; + + try { + //TODO: initialize out + this.out = new DataOutputStream(clientSocket.getOutputStream()); + //TODO: create a BattleShipClientNetworkHandler + //TODO: start it in another thread + + System.out.println("Enter Username: "); + Scanner usernameScanner = new Scanner(System.in); + + String username = usernameScanner.next(); + sendUsername(username); + initializeBoards(); + + System.out.println("Waiting for the other player to join"); + while(!otherPlayerJoined) + { + Thread.onSpinWait(); + } + + printBoards(); + while(true) + { + while(!isTurn) + { + Thread.onSpinWait(); + } + + System.out.println("Your Turn Now!"); + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + Scanner scanner = new Scanner(System.in); + + lastEnemyRow = -1; + lastEnemyCol = -1; + + while (lastEnemyRow < 0 || lastEnemyRow >= 10 || lastEnemyCol < 0 || lastEnemyCol >= 10) { + System.out.println("Type Row and Column (e.g., A1):"); + + String input = scanner.nextLine().trim().toUpperCase(); + + if (input.matches("^[A-J]([1-9]|10)$")) { + lastEnemyCol = input.charAt(0) - 'A'; + lastEnemyRow = Integer.parseInt(input.substring(1)) - 1; + + if (lastEnemyRow >= 0 && lastEnemyRow < 10 && lastEnemyCol >= 0 && lastEnemyCol < 10) { + System.out.println("You selected Row: " + (lastEnemyRow + 1) + ", Column: " + (char)('A' + lastEnemyCol)); + } else { + System.out.println("Invalid input! Row must be between 1 and 10, and Column must be between A and J."); + lastEnemyRow = -1; + lastEnemyCol = -1; + } + } else { + System.out.println("Invalid format! Please enter a valid input like A1, B10, J5."); + } + } + + System.out.println("Move is being sent. Waiting for processing"); + attack(); + } + } catch (IOException e) { + System.out.println("Could not connect to the server!\n\n"); + } + } + + //Actions + private void attack() { + //TODO: send attack message to server + isTurn = false; + } + private void sendUsername(String username) throws IOException { + //TODO: send username to server + } + public void setEnemyResult(boolean hit, String shipName) { + enemyBoard[lastEnemyRow][lastEnemyCol].setEnemyShip(hit); + enemyBoard[lastEnemyRow][lastEnemyCol].setMarked(true); + printBoards(); + playSound((hit?"hit_sound.wav":"miss_sound.wav")); + System.out.println((hit?"You hit the target!":"You missed!")); + } + public void setPlayerNumber(int i) { + if(i == 0) isTurn = true; + } + public void setOtherPlayerJoined() { + otherPlayerJoined = true; + } + public String getHit(int row, int col){ + String message = ""; + playerBoard[row][col].setMarked(true); + String sankBattleShipName = "NONE"; + if(playerBoard[row][col].isShip() && playerBoard[row][col].getBattleShip().isAllHit()){ + sankBattleShipName = playerBoard[row][col].getBattleShip().getType(); + } + message = playerBoard[row][col].isShip() ? ("HIT," + sankBattleShipName) : "MISS,NONE"; + printBoards(); + boolean hit = playerBoard[row][col].isShip(); + System.out.println((hit?"They hit a target!":"They missed!")); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + + } + isTurn = true; + return message; + } + private static void playSound(String soundFileName) { + try { + // Load the sound file from the resources folder + URL soundFileURL = BattleShipClient.class.getClassLoader().getResource( soundFileName); + + if (soundFileURL == null) { + System.out.println("Sound file not found: " + soundFileName); + return; + } + + AudioInputStream audioStream = AudioSystem.getAudioInputStream(soundFileURL); + Clip clip = AudioSystem.getClip(); + clip.open(audioStream); + clip.start(); + } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) { + System.out.println("Error playing sound: " + e.getMessage()); + } + } + + //Board + public void initializeBoards() { + playerBoard = createBoard(); + enemyBoard = new BattleShipCell[SIZE][SIZE]; + for (int i = 0; i < SIZE; i++) { + for (int j = 0; j < SIZE; j++){ + enemyBoard[i][j] = new BattleShipCell(); + } + } + isBoardSet = true; + } + public void printBoards() { + clearScreen(); + + System.out.printf(" %-40s%s%-40s%n", "PLAYER BOARD", SPACING ," ENEMY BOARD"); + + printColumnHeaders(); + System.out.print(SPACING); + printColumnHeaders(); + System.out.println(); + + for (int row = 0; row < SIZE; row++) { + printRowSeparator(); + System.out.print(SPACING); + printRowSeparator(); + System.out.println(); + + printRowContent(playerBoard[row], row); + System.out.print(SPACING); + printRowContent(enemyBoard[row], row); + System.out.println(); + } + + printRowSeparator(); + System.out.print(SPACING); + printRowSeparator(); + System.out.println(); + } + private void clearScreen() { + for (int i = 0; i < 20; i++) { + System.out.println(); + } + } + private void printColumnHeaders() { + System.out.print(" "); + for (char c : "ABCDEFGHIJ".toCharArray()) { + System.out.print(AnsiColor.CYAN + " " + c + " " + AnsiColor.RESET); + } + } + private void printRowSeparator() { + System.out.print(AnsiColor.BORDER + " +" + AnsiColor.RESET); + for (int i = 0; i < SIZE; i++) { + System.out.print(AnsiColor.BORDER + "---+" + AnsiColor.RESET); + } + } + private void printRowContent(BattleShipCell[] rowData, int rowNum) { + System.out.printf(AnsiColor.BORDER +"%2d |" + AnsiColor.RESET, rowNum + 1); + for (BattleShipCell cell : rowData) { + System.out.printf( " %s " , cell); + System.out.print(AnsiColor.BORDER +"|" + AnsiColor.RESET); + } + } + public BattleShipCell[][] createBoard() { + BattleShipCell[][] board = new BattleShipCell[SIZE][SIZE]; + + // Initialize grids with water + for (int i = 0; i < SIZE; i++) { + for (int j = 0; j < SIZE; j++) { + board[i][j] = new BattleShipCell(); // water + } + } + + for (Map.Entry entry : BattleShip.ships.entrySet()) { + BattleShip battleShip = new BattleShip(entry.getKey()); + placeShip(board, battleShip); + } + return board; + } + public static void placeShip(BattleShipCell[][] board, BattleShip battleShip) { + boolean placed = false; + + while(!placed) + { + boolean horizontal = rand.nextBoolean(); + int row = rand.nextInt(SIZE); + int col = rand.nextInt(SIZE); + placed = tryPlace(board, row, col, horizontal, battleShip); + } + + } + private static boolean tryPlace(BattleShipCell[][] board, int row, int col, boolean horizontal, BattleShip battleShip) { + + int length = battleShip.getLength(); + if(horizontal && col + length <= SIZE) + { + for(int i = 0; i < length; i++) + { + if(board[row][col + i].isShip()) + { + return false; + } + } + for(int i = 0; i < length; i++) + { + board[row][col + i].setBattleShip(battleShip); + } + return true; + } + + if(!horizontal && row + length <= SIZE) + { + for(int i = 0; i < length; i++) + { + if(board[row + i][col].isShip()) + { + return false; + } + } + for(int i = 0; i < length; i++) + { + board[row + i][col].setBattleShip(battleShip); + battleShip.addShipCell(board[row + i][col]); + } + return true; + } + + return false; + } + + public static void main(String[] args) throws IOException { + Socket clientSocket = null; + //TODO: get IP_Address + + try { + //initialize clientSocket + //initialize BattleShipClient + } finally { + try { + if (clientSocket != null) { + clientSocket.close(); + } + } catch (IOException e) { + System.out.println("Error closing resources: " + e.getMessage()); + } + } + } + +}