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();
}
}
}