Witam,
Tak jak w temacie. Pytanie od profesora. Na szczęście projekt zaliczony, jedynie wysłać sprawozdanie w którym graficznie przedstawię jak działają sockety. Ogólnie jeśli chodzi o szczegóły pytania brzmiało następująco: "Co jest wysyłane do servera?"
"Skąd wie gdzie postawić znak na drugiej planszy? Np. gracz1 postawił znak X na środku pola, to skąd druga plansza wie zeby tam postawić, a nie w całkowicie randomowym miejscu?"
Byłbym bardzo wdzięczny za dość łopatologiczną odpowiedź żebym mógł zrozumieć :). Tutaj kod:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TicTacToeServer {
public static void main(String[] args) throws Exception {
ServerSocket listener = new ServerSocket(8901);
System.out.println("Serwer TicTacToe działa");
try {
while (true) {
Game game = new Game();
Game.Player playerX = game.new Player(listener.accept(), 'X');
Game.Player playerO = game.new Player(listener.accept(), 'O');
playerX.setOpponent(playerO);
playerO.setOpponent(playerX);
game.currentPlayer = playerX;
playerX.start();
playerO.start();
}
} finally {
listener.close();
}
}
}
class Game {
private Player[] board = {
null, null, null,
null, null, null,
null, null, null};
Player currentPlayer;
public boolean hasWinner() {
return
(board[0] != null && board[0] == board[1] && board[0] == board[2])
||(board[3] != null && board[3] == board[4] && board[3] == board[5])
||(board[6] != null && board[6] == board[7] && board[6] == board[8])
||(board[0] != null && board[0] == board[3] && board[0] == board[6])
||(board[1] != null && board[1] == board[4] && board[1] == board[7])
||(board[2] != null && board[2] == board[5] && board[2] == board[8])
||(board[0] != null && board[0] == board[4] && board[0] == board[8])
||(board[2] != null && board[2] == board[4] && board[2] == board[6]);
}
public boolean boardFilledUp() {
for (int i = 0; i < board.length; i++) {
if (board[i] == null) {
return false;
}
}
return true;
}
public synchronized boolean legalMove(int location, Player player) {
if (player == currentPlayer && board[location] == null) {
board[location] = currentPlayer;
currentPlayer = currentPlayer.opponent;
currentPlayer.otherPlayerMoved(location);
return true;
}
return false;
}
class Player extends Thread {
char mark;
Player opponent;
Socket socket;
BufferedReader input;
PrintWriter output;
/// Tworzy wątek obsługi dla danego gniazda i oznaczenia
// inicjalizuje pola strumienia, wyświetla pierwsze dwa
//powitalne wiadomości.
public Player(Socket socket, char mark) {
this.socket = socket;
this.mark = mark;
try {
input = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
output = new PrintWriter(socket.getOutputStream(), true);
output.println("WELCOME " + mark);
output.println("MESSAGE Czekaj na przeciwnika");
} catch (IOException e) {
System.out.println("Player died: " + e);
}
}
/// akceptuje przeciwnika
public void setOpponent(Player opponent) {
this.opponent = opponent;
}
public void otherPlayerMoved(int location) {
output.println("OPPONENT_MOVED " + location);
output.println(
hasWinner() ? "DEFEAT" : boardFilledUp() ? "TIE" : "");
}
public void run() {
try {
output.println("MESSAGE Gracze połączeni");
if (mark == 'X') {
output.println("MESSAGE Twój ruch");
}
// otrzymuje polecenia od klienta i przetwarza je
while (true) {
String command = input.readLine();
if (command.startsWith("MOVE")) {
int location = Integer.parseInt(command.substring(5));
if (legalMove(location, this)) {
output.println("VALID_MOVE");
output.println(hasWinner() ? "VICTORY"
: boardFilledUp() ? "TIE"
: "");
} else {
output.println("MESSAGE ?");
}
} else if (command.startsWith("QUIT")) {
return;
}
}
} catch (IOException e) {
System.out.println("Player died: " + e);
} finally {
try {socket.close();} catch (IOException e) {}
}
}
}
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TicTacToeClient {
private JFrame frame = new JFrame("Tic Tac Toe");
private JLabel messageLabel = new JLabel("");
private ImageIcon icon;
private ImageIcon opponentIcon;
private Square[] board = new Square[9];
private Square currentSquare;
private static int PORT = 8901;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public TicTacToeClient(String serverAddress) throws Exception {
socket = new Socket(serverAddress, PORT);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// GUI
messageLabel.setBackground(Color.lightGray);
frame.getContentPane().add(messageLabel, "South");
JPanel boardPanel = new JPanel();
boardPanel.setBackground(Color.black);
boardPanel.setLayout(new GridLayout(3, 3, 3, 3));
for (int i = 0; i < board.length; i++) {
final int j = i;
board[i] = new Square();
board[i].addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
currentSquare = board[j];
out.println("MOVE " + j);}});
boardPanel.add(board[i]);
}
frame.getContentPane().add(boardPanel, "Center");
}
public void play() throws Exception {
String response;
try {
response = in.readLine();
if (response.startsWith("WELCOME")) {
char mark = response.charAt(8);
if(mark == 'X')
{
icon = new ImageIcon("x.gif");
opponentIcon = new ImageIcon("o.gif");
}
else if(mark == 'O')
{
icon = new ImageIcon("o.gif");
opponentIcon = new ImageIcon("x.gif");
}
frame.setTitle("Tic Tac Toe - Player " + mark);
}
while (true) {
response = in.readLine();
if (response.startsWith("VALID_MOVE")) {
messageLabel.setText("Prawidłowy ruch, czekaj");
currentSquare.setIcon(icon);
currentSquare.repaint();
} else if (response.startsWith("OPPONENT_MOVED")) {
int loc = Integer.parseInt(response.substring(15));
board[loc].setIcon(opponentIcon);
board[loc].repaint();
messageLabel.setText("Przeciwnik skończył, twój ruch");
} else if (response.startsWith("VICTORY")) {
messageLabel.setText("WYGRAŁEŚ");
break;
} else if (response.startsWith("DEFEAT")) {
messageLabel.setText("Przegrałeś");
break;
} else if (response.startsWith("TIE")) {
messageLabel.setText("Remisik");
break;
} else if (response.startsWith("MESSAGE")) {
messageLabel.setText(response.substring(8));
}
}
out.println("QUIT");
}
finally {
socket.close();
}
}
private boolean wantsToPlayAgain() {
int response = JOptionPane.showConfirmDialog(frame,
"Jeszcze raz?",
"Tic Tac Toe",
JOptionPane.YES_NO_OPTION);
frame.dispose();
return response == JOptionPane.YES_OPTION;
}
static class Square extends JPanel {
JLabel label = new JLabel((Icon)null);
public Square() {
setBackground(Color.white);
add(label);
}
public void setIcon(Icon icon) {
label.setIcon(icon);
}
}
public static void main(String[] args) throws Exception {
while (true) {
String serverAddress = (args.length == 0) ? "localhost" : args[1];
TicTacToeClient client = new TicTacToeClient(serverAddress);
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setSize(300, 300);
client.frame.setVisible(true);
client.frame.setResizable(false);
client.play();
if (!client.wantsToPlayAgain()) {
break;
}
}
}
}