오목

윤준석·2025년 4월 7일

package org.example;

import java.net.;
import java.io.
;

public class GameClient {
public static void main(String[] args) throws IOException {
String serverIP = "localhost"; // 실제 서버 IP로 변경
Socket socket = new Socket(serverIP, 4998);
System.out.println("서버에 연결됨");

    new OmokUI(socket, false).start();
}

}

package org.example;

import java.net.;
import java.io.
;

public class GameServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(4998);
System.out.println("서버 시작. 클라이언트를 기다리는 중...");
Socket socket = serverSocket.accept();
System.out.println("클라이언트 연결됨: " + socket.getInetAddress());

    new OmokUI(socket, true).start();
}

}

package org.example;

public class OmokBoard {
public static final int SIZE = 15;
public int[][] board = new int[SIZE][SIZE];

public boolean placeStone(int x, int y, int player) {
    if (board[y][x] == 0) {
        board[y][x] = player;
        return true;
    }
    return false;
}

public int checkWin() {
    for (int y = 0; y < SIZE; y++) {
        for (int x = 0; x < SIZE; x++) {
            int player = board[y][x];
            if (player == 0) continue;
            if (checkDirection(x, y, 1, 0, player) ||
                checkDirection(x, y, 0, 1, player) ||
                checkDirection(x, y, 1, 1, player) ||
                checkDirection(x, y, 1, -1, player)) {
                return player;
            }
        }
    }
    return 0;
}

private boolean checkDirection(int x, int y, int dx, int dy, int player) {
    for (int i = 0; i < 5; i++) {
        int nx = x + dx * i;
        int ny = y + dy * i;
        if (nx < 0 || ny < 0 || nx >= SIZE || ny >= SIZE) return false;
        if (board[ny][nx] != player) return false;
    }
    return true;
}

}

package org.example;

import org.example.OmokBoard;

import javax.swing.;
import java.awt.
;
import java.awt.event.;
import java.io.
;
import java.net.Socket;

public class OmokUI {
private Socket socket;
private boolean isServer;
private OmokBoard board = new OmokBoard();
private JFrame frame;
private JPanel boardPanel;
private JTextArea chatArea;
private JTextField chatField;
private JScrollPane chatScroll;
private int currentPlayer = 1;
private boolean myTurn;

private BufferedReader in;
private PrintWriter out;

public OmokUI(Socket socket, boolean isServer) {
    this.socket = socket;
    this.isServer = isServer;
    this.myTurn = isServer;
}

public void start() {
    try {
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        out = new PrintWriter(socket.getOutputStream(), true);
    } catch (IOException e) {
        e.printStackTrace();
    }

    frame = new JFrame("네트워크 오목 - " + (isServer ? "서버" : "클라이언트"));
    frame.setSize(600, 750);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLayout(new BorderLayout());

    frame.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e) {
            try {
                socket.close();
                System.out.println("소켓 연결 종료");
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    });

    boardPanel = new JPanel() {
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            setBackground(new Color(222, 184, 135)); // 연한 갈색
            drawBoard(g);
        }
    };
    boardPanel.setPreferredSize(new Dimension(600, 600));
    boardPanel.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            if (!myTurn) return;
            int x = e.getX() / 40;
            int y = e.getY() / 40;
            if (x < 0 || y < 0 || x >= OmokBoard.SIZE || y >= OmokBoard.SIZE) return;
            if (board.placeStone(x, y, currentPlayer)) {
                boardPanel.repaint();
                out.println("MOVE:" + x + "," + y);
                int winner = board.checkWin();
                if (winner != 0) {
                    JOptionPane.showMessageDialog(frame, "플레이어 " + winner + " 승리!");
                    out.println("RESET");
                    resetGame();
                    return;
                }
                myTurn = false;
            }
        }
    });

    JPanel chatPanel = new JPanel(new BorderLayout());
    chatArea = new JTextArea();
    chatArea.setEditable(false);
    chatArea.setFont(new Font("맑은 고딕", Font.PLAIN, 14));
    chatArea.setBackground(new Color(248, 248, 255));
    chatScroll = new JScrollPane(chatArea);
    chatScroll.setPreferredSize(new Dimension(600, 100));

    chatField = new JTextField();
    chatField.setFont(new Font("맑은 고딕", Font.PLAIN, 14));
    chatField.addActionListener(e -> {
        String msg = chatField.getText();
        if (!msg.trim().isEmpty()) {
            out.println("CHAT:" + msg);
            chatArea.append("나: " + msg + "\n");
            chatArea.setCaretPosition(chatArea.getDocument().getLength()); // 맨 아래로
            chatField.setText("");
        }
    });

    chatPanel.add(chatScroll, BorderLayout.CENTER);
    chatPanel.add(chatField, BorderLayout.SOUTH);
    chatPanel.setPreferredSize(new Dimension(600, 150));

    frame.add(boardPanel, BorderLayout.CENTER);
    frame.add(chatPanel, BorderLayout.SOUTH);
    frame.setVisible(true);

    new Thread(this::listen).start();
}

private void drawBoard(Graphics g) {
    for (int i = 0; i < OmokBoard.SIZE; i++) {
        g.setColor(Color.BLACK);
        g.drawLine(20, 20 + i * 40, 20 + (OmokBoard.SIZE - 1) * 40, 20 + i * 40);
        g.drawLine(20 + i * 40, 20, 20 + i * 40, 20 + (OmokBoard.SIZE - 1) * 40);
    }
    for (int y = 0; y < OmokBoard.SIZE; y++) {
        for (int x = 0; x < OmokBoard.SIZE; x++) {
            int stone = board.board[y][x];
            if (stone != 0) {
                g.setColor(stone == 1 ? Color.BLACK : Color.WHITE);
                g.fillOval(20 + x * 40 - 15, 20 + y * 40 - 15, 30, 30);
            }
        }
    }
}

private void resetGame() {
    board = new OmokBoard();
    boardPanel.repaint();
    myTurn = isServer;
}

private void listen() {
    String line;
    try {
        while ((line = in.readLine()) != null) {
            if (line.startsWith("MOVE:")) {
                String[] parts = line.substring(5).split(",");
                int x = Integer.parseInt(parts[0]);
                int y = Integer.parseInt(parts[1]);
                board.placeStone(x, y, 3 - currentPlayer);
                boardPanel.repaint();
                int winner = board.checkWin();
                if (winner != 0) {
                    JOptionPane.showMessageDialog(frame, "플레이어 " + winner + " 승리!");
                    resetGame();
                }
                myTurn = true;
            } else if (line.startsWith("CHAT:")) {
                chatArea.append("상대: " + line.substring(5) + "\n");
                chatArea.setCaretPosition(chatArea.getDocument().getLength()); // 맨 아래로
            } else if (line.equals("RESET")) {
                resetGame();
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

0개의 댓글