В начале я отправляю строку таблиц с указанием места расположения вражеских кораблей. Затем в цикле (пока бесконечном) я пытаюсь отправить одно сообщение и прослушать одно в зависимости от того, какой ход. После одного сообщения отправленные и полученные циклы перестают работать. Я подозреваю, что это может быть связано с потоком, но я не знаю, как подойти к этому. Я не ожидаю, что кто-нибудь перебирает весь этот код, но я думаю, что лучше включать больше кода, чем меньше. Я в основном ищу какое-то руководство. Код ниже и спасибо за вашу помощь.
Основной класс (я думаю, что основными виновниками могут быть customMousePressed & actionPerformed)
открытый класс BattleShipGame расширяет JFrame, реализует ActionListener {
//this 268, Draw 112 /////////////////////////////////////
private Optional<Ship> newShip;
private int logicPosX;
private int logicPosY;
private Coordinates start;
static String coordinatesInput = "", coordinatesOutput = "";
static boolean myturn = false;
private static int counter = 0;
static boolean connected = false;
Captain player = new Captain();
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new BattleShipGame());
}
private BattleShipGame()
{
this.setTitle("Battleship Game");
this.setSize(1100, 500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setResizable(false);
JPanel panel = new JPanel();
player.initializeShips();
Timer timer = new Timer(20, this);
DrawBoardAndShips boardAndShips = new DrawBoardAndShips(player);
timer.start();
//create player
//set your ships (one map & ships to drag from place to place)
//when READY button clicked and all ships are on board ->
//->search for player (Connection - sockets)
//draw 2 maps (one with ships, one to shoot)
//receive coordinates (hit or miss - draw changes to 1 map) - win condition checker (send info to another player about shoot result)
//send coordinates
JButton reset = new JButton("RESET");
reset.addActionListener(e -> {
//set to default position of ships
player.resetPositions();
player.getShips().forEach(ship -> ship.setShipOnBoard(false));
});
JButton ready = new JButton("READY!");
ready.addActionListener((ActionEvent e) -> { //set logic when button ready pressed
//check if all ships are on board
//set ready = true
if (player.getShips().stream().filter(Ship::isShipOnBoard).count() == 10 && e.getSource() == ready) {
//set logic
for (Ship ship : player.getShips()) {
player.setMyBoard(ship);
}
//establish network connection
boolean outcome = serverOrClientDecision(JOptionPane.YES_OPTION, player);
if(outcome) {
panel.remove(reset);
panel.remove(ready);
}
revalidate();
repaint();
}
});
panel.add(reset);
panel.add(ready);
this.add(panel, BorderLayout.SOUTH);
this.add(boardAndShips, BorderLayout.CENTER);
boardAndShips.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
customMouseDragged(player, e);
}
});
boardAndShips.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
customMouseClicked(e, player);
}
@Override
public void mousePressed(MouseEvent e) {
customMousePressed(e, player);
}
@Override
public void mouseReleased(MouseEvent e) {
customMouseReleased(player);
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
this.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
if(!coordinatesInput.isEmpty() && !player.isMyTurn()){
String[] parts = coordinatesInput.split("\\."); //////////////////
logicPosX = Integer.parseInt(parts[0]);
logicPosY = Integer.parseInt(parts[1]);
if (player.getMyBoard()[logicPosX][logicPosY] == 1) {
player.getMyBoard()[logicPosX][logicPosY] = 2;
isSunk(player.getMyBoard());
}
else if(player.getMyBoard()[logicPosX][logicPosY] == 0)
player.getMyBoard()[logicPosX][logicPosY] = -1;
coordinatesInput = "";
player.setMyTurn(true);
}
repaint();
}
public boolean serverOrClientDecision(int decision, Captain player) {
Object[] options = {"CREATE", "JOIN", "EXIT"};
Object[] options2 = {"BACK", "TRY AGAIN", "EXIT"};
if (decision == JOptionPane.YES_OPTION) {
decision = JOptionPane.showOptionDialog(this, "Create game or join one?", "Battleship Game",
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, null);
}
//
if(decision == JOptionPane.CANCEL_OPTION)
return false;
if (decision == JOptionPane.YES_OPTION) {
//create server
SwingWorker<Void, Void> worker = new SwingWorker<>() {
@Override
protected Void doInBackground() throws Exception {
Server server = new Server(player);
return null;
}
};
worker.execute();
} else if (decision == JOptionPane.NO_OPTION) {
//getting IP
String serversIP = JOptionPane.showInputDialog("Type server's IP");
//creating client
SwingWorker<Void, Boolean> worker1 = new SwingWorker<>() {
@Override
protected Void doInBackground() throws IOException {
Client client = new Client(serversIP, player);
return null;
}
};
worker1.execute();
while (!worker1.isDone()) {
if (connected == true)
break;
}
if (!connected) {
decision = JOptionPane.showOptionDialog(this, "Host not responding", "Join Game",
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options2, null);
serverOrClientDecision(decision, player);
}
}
return true;
}
public void customMouseDragged(Captain player, MouseEvent e) {
if (player.getReady() == 0) {
newShip.filter(Ship::isHorizontal)
.ifPresent(ship -> ship.setCoordinates(new Coordinates(e.getX() - ship.getSize() * 16, e.getY() - 16)));
newShip.filter(ship -> !ship.isHorizontal())
.ifPresent(ship -> ship.setCoordinates(new Coordinates(e.getX() - 16, e.getY() - ship.getSize() * 16)));
}
}
public void customMouseClicked(MouseEvent e, Captain player) {
if (player.getReady() == 0) {
//ship is in bounds of the BOARD after rotating
player.getShips().stream()
.filter(ship -> ship.getBounds().contains(e.getPoint()))
.filter(ship -> (logicPosX < 11 && logicPosY + ship.getSize() < 11 && ship.isHorizontal())
|| (logicPosX + ship.getSize() < 11 && logicPosY < 11 && !ship.isHorizontal()))
.forEach(ship -> ship.setHorizontal(!ship.isHorizontal()));
//ship don't overlap space of other ship, if does revert rotation to previous state
if(newShip.isPresent()) {
player.getShips().stream()
.filter(ship -> ship.getId() != newShip.get().getId())
.filter(ship -> ship.getBigBounds().intersects(newShip.get().getBounds()))
.forEach(ship -> {
newShip.get().setHorizontal(!newShip.get().isHorizontal());
});
}
}
}
public void customMousePressed(MouseEvent e, Captain player) {
if (player.getReady() == 0) {
logicPosX = logicPosY = -1;
//picking up ship
newShip = player.getShips().stream().
filter(ship -> ship.getBounds().contains(e.getPoint()))
.findAny();
newShip.ifPresent(newShip -> start = newShip.getCoordinates());
} else if (player.getReady() == 2 && player.isMyTurn()) {
//System.out.println(e.getPoint().toString());
//-1 - uncovered (miss)
// 0 - covered (miss)
// 1 - covered (hit)
// 2 - uncovered (hit)
// 3 - uncovered (hit and sunk)
// is shoot in bounds of the enemy BOARD
if ((e.getX() > 600 && e.getX() < 920) && (e.getY() > 50 && e.getY() < 370)){
logicPosX = (e.getX() - 600) / 32;
logicPosY = (e.getY() - 50) / 32;
if (player.getEnemyBoard()[logicPosX][logicPosY] == 1) { // if covered (hit)
player.getEnemyBoard()[logicPosX][logicPosY] = 2;// set as uncovered (hit)
//check if ship sunk
isSunk(player.getEnemyBoard());
coordinatesOutput = Integer.toString(logicPosX) + "." + Integer.toString(logicPosY);
player.setMyTurn(false);
coordinatesOutput = "";
}
else if (player.getEnemyBoard()[logicPosX][logicPosY] == 0) { //if covered (miss)
player.getEnemyBoard()[logicPosX][logicPosY] = -1; // set as uncovered (miss)
coordinatesOutput = Integer.toString(logicPosX) + "." + Integer.toString(logicPosY);
player.setMyTurn(false);
coordinatesOutput = "";
}
}
}
}
public void customMouseReleased(Captain player) {
if (player.getReady() == 0) {
if (newShip.isPresent()) {
logicPosX = (newShip.get().getCoordinates().getX() - 150) / 32;
logicPosY = (newShip.get().getCoordinates().getY() - 50) / 32;
//ship placed on board
if (((logicPosX + newShip.get().getSize() < 11) && (logicPosY < 11) && newShip.get().isHorizontal() && logicPosX > -1 && logicPosY > -1)
|| ((logicPosX < 11) && (logicPosY + newShip.get().getSize() < 11) && !newShip.get().isHorizontal() && logicPosX > -1 && logicPosY > -1)) {
//adjust to grid
newShip.get().getCoordinates().setX(150 + logicPosX * 32);
newShip.get().getCoordinates().setY(50 + logicPosY * 32);
newShip.ifPresent(newShip -> newShip.setShipOnBoard(true));
//ship don't overlap space of other ship, if does revert move
player.getShips().stream()
.filter(ship -> ship.getId() != newShip.get().getId())
.filter(ship -> ship.getBigBounds().intersects(newShip.get().getBounds()))
.forEach(ship -> {
newShip.get().setCoordinates(start);
newShip.get().setShipOnBoard(false);
});
} else {
newShip.get().setHorizontal(true);
newShip.get().setCoordinates(start);
}
}
}
}
private void isSunk(int[][] board) {
int struck = 0;
int notStruck = 0;
Point[] struckPositions = new Point[4];
//checking every direction for not struck poles in ship
for (int n = 0; n < 4; n++) {
if (logicPosY - n > 0){
if (board[logicPosX][logicPosY - n] == 2) {
struckPositions[struck] = new Point(logicPosX, logicPosY);
struck++;
}
else if(board[logicPosX][logicPosY - n] == 1)
notStruck++;
else if(board[logicPosX][logicPosY - n] == 0)
break;
}
else
break;
}
for (int s = 1; s < 4; s++) {
if (logicPosY + s < 10){
if (board[logicPosX][logicPosY + s] == 2) {
struckPositions[struck] = new Point(logicPosX, logicPosY);
struck++;
}
else if(board[logicPosX][logicPosY + s] == 1)
notStruck++;
else if(board[logicPosX][logicPosY + s] == 0)
break;
}
else
break;
}
for (int e = 1; e < 4; e++) {
if (logicPosX + e < 10){
if (board[logicPosX + e][logicPosY] == 2) {
struckPositions[struck] = new Point(logicPosX, logicPosY);
struck++;
}
else if(board[logicPosX + e][logicPosY] == 1)
notStruck++;
else if(board[logicPosX + e][logicPosY] == 0)
break;
}
else
break;
}
for (int w = 1; w < 4; w++) {
if (logicPosX - w > 0){
if (board[logicPosX - w][logicPosY] == 2) {
struckPositions[struck] = new Point(logicPosX, logicPosY);
struck++;
}
else if(board[logicPosX - w][logicPosY] == 1)
notStruck++;
else if(board[logicPosX - w][logicPosY] == 0)
break;
}
else
break;
}
// if sunk change it in logical table
if (notStruck == 0){
for (Point p : struckPositions){
board[p.x][p.y] = 3;
//return int = struck
}
}
//else return -1; - in future to display sunk ships as small squares next to tables
}
}
Сервер
Сервер класса расширяет поток {
ServerSocket serverSocket;
Socket socket;
DataInputStream dataInputStream;
DataOutputStream dataOutputStream;
String sendMessage = "", message1 = "", receivedMessage = "";
public Server(Captain player) throws IOException {
System.out.println("SERVER");
int asd = 0;
player.setReady(1);
serverSocket = new ServerSocket(6666);
socket = serverSocket.accept();
player.setReady(2);
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
//send logic table at the beginning of the game
for(int i1 = 0; i1 < player.getMyBoard().length; i1++){
for (int j = 0; j < player.getMyBoard()[i1].length; j++){
if(player.getMyBoard()[j][i1] == 1) /////////////////////
sendMessage += "1";
else
sendMessage += "0";
}
}
dataOutputStream.writeUTF(sendMessage);
sendMessage = "";
/*System.out.println("Sever get from Client: " + dataInputStream.readUTF());
System.out.println("Server send: " + start);*/
//receive String and convert it to enemy logic table
receivedMessage = dataInputStream.readUTF();
player.setEnemyBoard(receivedMessage);
receivedMessage = "";
player.setMyTurn(true);
while(!message1.equals("WIN") || !message1.equals("LOOSE")){
dataOutputStream.writeUTF(BattleShipGame.coordinatesOutput);
BattleShipGame.coordinatesOutput = "";
System.out.println("__");
if(!player.isMyTurn()) {
receivedMessage = dataInputStream.readUTF();
System.out.println("server NOT my turn");
if(!receivedMessage.isEmpty()) {
BattleShipGame.coordinatesInput = receivedMessage;
receivedMessage = "";
//player.setMyTurn(true);
}
} else {
sendMessage = BattleShipGame.coordinatesOutput;
System.out.print(asd++);
if(!sendMessage.isEmpty()) {
dataOutputStream.writeUTF(sendMessage);
sendMessage = "";
//player.setMyTurn(false);
}
}
dataOutputStream.flush();
}
dataInputStream.close();
socket.close();
serverSocket.close();
}
}
Клиент
Клиент публичного класса {
Socket socket;
DataInputStream dataInputStream;
DataOutputStream dataOutputStream;
BufferedReader bufferedReader;
String sendMessage = "", message1 = "", receivedMessage = "";
public Client(String host, Captain player) throws IOException {
System.out.println("CLIENT");
socket = new Socket(host, 6666);
player.setReady(2);
BattleShipGame.connected = socket.isConnected();
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
bufferedReader = new BufferedReader(new InputStreamReader(System.in));
//send logic table at the beginning of the game
for(int i1 = 0; i1 < player.getMyBoard().length; i1++){
for (int j = 0; j < player.getMyBoard()[i1].length; j++){
if(player.getMyBoard()[j][i1] == 1)
sendMessage += "1";
else
sendMessage += "0";
}
}
dataOutputStream.writeUTF(sendMessage);
sendMessage = "";
/*System.out.println("Client get from Server: " + dataInputStream.readUTF());
System.out.println("Client sends: " + start);*/
//receive String and convert it to enemy logic table
receivedMessage = dataInputStream.readUTF();
player.setEnemyBoard(receivedMessage);
receivedMessage = "";
player.setMyTurn(false);
while(!message1.equals("WIN") || !message1.equals("LOOSE")){
System.out.print("c");
if(!player.isMyTurn()) {
receivedMessage = dataInputStream.readUTF();
System.out.println("client NOT my turn"); /////////////////////////////
if(!receivedMessage.isEmpty()) {
BattleShipGame.coordinatesInput = receivedMessage;
receivedMessage = "";
}
} else {
sendMessage = BattleShipGame.coordinatesOutput;
System.out.println("client MY turn"); ////////////////////////////
if(!sendMessage.isEmpty()) {
dataOutputStream.writeUTF(sendMessage);
sendMessage = "";
}
}
dataOutputStream.flush();
}
dataInputStream.close();
socket.close();
}
* *} Тысяча двадцать-один