Compare commits
10
Commits
0610b9d686
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65fb68c233 | ||
|
|
b3237169d6 | ||
|
|
f95cf6e7ef | ||
|
|
90fd825bfe | ||
|
|
1487b6dfac | ||
|
|
2d6b702d37 | ||
|
|
90379fe39b | ||
|
|
d45f55c0ca | ||
|
|
eb81c7ab19 | ||
|
|
3da6673156 |
@@ -0,0 +1,305 @@
|
|||||||
|
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 Client {
|
||||||
|
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 Client(Socket clientSocket) {
|
||||||
|
this.clientSocket = clientSocket;
|
||||||
|
|
||||||
|
try {
|
||||||
|
//TODO: initialize out
|
||||||
|
this.out = new DataOutputStream(clientSocket.getOutputStream());
|
||||||
|
//TODO: create a ClientNetworkReceiver
|
||||||
|
//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 void finishGame(boolean won){
|
||||||
|
//TODO:
|
||||||
|
}
|
||||||
|
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 = Client.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<String, Integer> 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 Client
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (clientSocket != null) {
|
||||||
|
clientSocket.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("Error closing resources: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package Client;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
public class ClientNetworkReceiver implements Runnable{
|
||||||
|
private Client client;
|
||||||
|
private DataInputStream in;
|
||||||
|
|
||||||
|
public ClientNetworkReceiver(Socket clientSocket, Client client) throws IOException {
|
||||||
|
// initialize client
|
||||||
|
// initialize in
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while(true) {
|
||||||
|
//TODO: get response
|
||||||
|
String response = "";
|
||||||
|
|
||||||
|
if(false) // TODO: set player number ( 0 or 1)
|
||||||
|
{
|
||||||
|
int number = 0;
|
||||||
|
client.setPlayerNumber(number);
|
||||||
|
}
|
||||||
|
else if(false) // TODO: other player joined the game
|
||||||
|
{
|
||||||
|
client.setOtherPlayerJoined();
|
||||||
|
}
|
||||||
|
else if(false){ // TODO: handle incoming hit
|
||||||
|
int row = 0; //TODO: extract row
|
||||||
|
int col = 0; //TODO: extract col
|
||||||
|
String message = client.getHit(row, col);
|
||||||
|
//TODO: inform server
|
||||||
|
}
|
||||||
|
else if(false) //TODO: handle hit result from opponent
|
||||||
|
{
|
||||||
|
client.setEnemyResult(false, "NONE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package Server;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
public class ClientHandler implements Runnable {
|
||||||
|
private Socket client;
|
||||||
|
private DataInputStream in;
|
||||||
|
private DataOutputStream out;
|
||||||
|
private boolean isFirst;
|
||||||
|
private String username;
|
||||||
|
ClientHandler enemy;
|
||||||
|
|
||||||
|
public void sendData(String request) {
|
||||||
|
//TODO: write to output and flush
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnemy(ClientHandler enemy) throws IOException {
|
||||||
|
this.enemy = enemy;
|
||||||
|
}
|
||||||
|
public String getUsername()
|
||||||
|
{
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientHandler(Socket client, boolean isFirst) throws IOException {
|
||||||
|
//initialize client
|
||||||
|
//initialize in
|
||||||
|
//initialize out
|
||||||
|
//initialize isFirst
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
while(true) {
|
||||||
|
// TODO: Read a UTF-encoded string from the client
|
||||||
|
String request = "";
|
||||||
|
if (false) { //TODO: Set Username
|
||||||
|
int playerNumber = isFirst?0:1;
|
||||||
|
// TODO: Send player number to client
|
||||||
|
|
||||||
|
username = "";//TODO extract username
|
||||||
|
//TODO: wait till enemy is specified
|
||||||
|
//TODO: tell the clients that the other player joined
|
||||||
|
}
|
||||||
|
else if (false) { //TODO: Handle Attack
|
||||||
|
int row = 0;//TODO: extract row and col
|
||||||
|
int col = 0;//TODO: extract row and col
|
||||||
|
//TODO: inform enemy of the attack
|
||||||
|
}
|
||||||
|
else if (false) { //TODO: Handle Attack Result
|
||||||
|
// TODO: Notify the attacker about the result of their attack (hit or miss)
|
||||||
|
}
|
||||||
|
//TODO(for later): handle winning and losing
|
||||||
|
}
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
// close in
|
||||||
|
// close out
|
||||||
|
// close client
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package Server;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class Server {
|
||||||
|
private static int PORT = 3737;
|
||||||
|
// TODO: Create a collection to keep track of connected clients
|
||||||
|
private static ArrayList<ClientHandler> clients = new ArrayList();
|
||||||
|
private static ExecutorService pool = Executors.newFixedThreadPool(4);
|
||||||
|
|
||||||
|
static ClientHandler playerOne;
|
||||||
|
static ClientHandler playerTwo;
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ServerSocket listener = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// TODO: Create a ServerSocket to listen for incoming connections
|
||||||
|
//int i = 0;
|
||||||
|
while(true) {
|
||||||
|
|
||||||
|
// TODO: Accept a client connection
|
||||||
|
// TODO: Create a ClientHandler named clientThread for the connected client
|
||||||
|
// TODO: uncomment this code
|
||||||
|
//if(i == 0) {
|
||||||
|
// playerOne = clientThread;
|
||||||
|
//}
|
||||||
|
//if(i == 1) {
|
||||||
|
// playerTwo = clientThread;
|
||||||
|
// playerOne.setEnemy(playerTwo);
|
||||||
|
// playerTwo.setEnemy(playerOne);
|
||||||
|
//}
|
||||||
|
//i++;
|
||||||
|
//TODO add clientThread to clients and executor service
|
||||||
|
|
||||||
|
//TODO(for later): handle the situation where more than two players join at the same time
|
||||||
|
//TODO(for later): handle the situation where more than one game happens
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (listener != null) {
|
||||||
|
try {
|
||||||
|
listener.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pool.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user