2013-11-04 07:48:39Morris

[JAVA][重製] 聊天室遊戲製作







根據以前寫的進行修改與擴充。

- 增加隨機對戰,多人遊戲改成對戰遊戲
- 將 Server 端的遊戲處理放置 Client
- 兩端共同操作 Timer 互傳資料
- 共用 IP 者,仍然無法在遊戲中當 Server
- 由於沒有特殊線路,Server 端只提供遊戲的兩端互連的服務
- 將原本的 Client Applet 改成一般 Application


待補
1. 進場動畫
2. 退場訊息
3. 指定對戰的操作程序

manifest.mf

Main-Class: Client/MClient


包成 jar 檔的 command, 所有圖片放置在 Client 下(與 *.class 一起)

jar cvfm GameVer4.jar manifest.mf Client\*.*


代碼沒有 OO 精神,請見諒。

package Client;

import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import java.io.*;

import java.util.*;
import java.util.Timer;
import java.lang.Thread;

import javax.swing.*;
import javax.swing.border.*;

import java.awt.*;
import java.awt.event.*;

public class ControlPanel extends JPanel {
    private JTextField inputPort;
    private JTextField inputHost;
    private JTextField inputName;
    private JToggleButton inputSwitch;
    private JButton inputRandom;
    private JButton inputAssign;
    private JPanel northPanel;

    private JTextArea contentArea;
    private JList userList;
    private DefaultListModel userListModel;
    private JPanel centerPanel;

    private JTextField inputMsg;
    private JButton sendBtn;
    private JPanel southPanel;

    private JPanel chatPanel;
    private JPanel gamePanel;
    private GamePanel gameShowPanel;

    private boolean clientRunning = false;
    private Socket clientSocket;
    private PrintWriter clientWriter;
    private BufferedReader clientReader;

    private ClientThread clientThread;

    GameServer gameServer;
    GameClient gameClient;

    public ControlPanel() {
        gameServer = new GameServer();
        createNorthPanel();
        createCenterPanel();
        createSouthPanel();
        createGamePanel();
        chatPanel = new JPanel();
        chatPanel.setLayout(new BorderLayout());
        chatPanel.add(northPanel, BorderLayout.NORTH);
        chatPanel.add(centerPanel, BorderLayout.CENTER);
        chatPanel.add(southPanel, BorderLayout.SOUTH);

        GridBagConstraints GBC;
        this.setLayout(new GridBagLayout());
        GBC = new GridBagConstraints();
        GBC.insets = new Insets(10, 10, 10, 10);
        GBC.fill = GridBagConstraints.BOTH;
        GBC.anchor = GridBagConstraints.NORTHEAST;
        GBC.gridx = 0;
        GBC.gridy = 0;
        GBC.gridwidth = 1;
        GBC.gridheight = 1;
        GBC.weightx = 300;
        GBC.weighty = 300;
        this.add(gamePanel, GBC);
        GBC = new GridBagConstraints();
        GBC.insets = new Insets(10, 10, 10, 10);
        GBC.fill = GridBagConstraints.BOTH;
        GBC.anchor = GridBagConstraints.NORTHEAST;
        GBC.gridx = 0;
        GBC.gridy = 1;
        GBC.gridwidth = 1;
        GBC.gridheight = 1;
        GBC.weightx = 300;
        GBC.weighty = 300;
        this.add(chatPanel, GBC);
        gamePanel.setBackground(Color.BLACK);
        gamePanel.setVisible(false);
    }

    private void createGamePanel() {
        gamePanel = new JPanel();
        gamePanel.setLayout(new BorderLayout());
        JPanel tmp = new JPanel();
        JButton exit = new JButton("Exit");
        tmp.setLayout(new GridLayout(1, 1));
        tmp.add(exit);
        exit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                clientExitGame();
            }
        });
        gameShowPanel = new GamePanel();
        gamePanel.add(gameShowPanel, BorderLayout.CENTER);
        gamePanel.add(tmp, BorderLayout.SOUTH);
    }

    private void createNorthPanel() {
        Font displayFont = new Font("Serif", Font.BOLD, 18);
        Font displayFontII = new Font("Serif", Font.BOLD, 12);
        northPanel = new JPanel();
        northPanel.setBorder(new TitledBorder("Setting"));
        northPanel.setLayout(new GridLayout(1, 9));

        inputHost = new JTextField("140.115.205.194");
        inputPort = new JTextField("4096");
        inputName = new JTextField("GUEST");
        inputSwitch = new JToggleButton("OFF");
        inputRandom = new JButton("Random");
        inputAssign = new JButton("Assign");

        inputHost.setFont(displayFont);
        inputPort.setFont(displayFont);
        inputName.setFont(displayFont);
        inputSwitch.setFont(displayFont);
        inputRandom.setFont(displayFontII);
        inputAssign.setFont(displayFontII);
        inputSwitch.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    if (openSocket()) {
                        inputSwitch.setText("ON");
                    } else if (!clientRunning) {
                        inputSwitch.setSelected(false);
                    }
                } else if (e.getStateChange() == ItemEvent.DESELECTED) {
                    if (closeSocket()) {
                        inputSwitch.setText("OFF");
                    } else if (clientRunning) {
                        inputSwitch.setSelected(true);
                    }
                }
            }
        });
        inputRandom.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                clientQueryGame("");
            }
        });

        JLabel showlabel;
        showlabel = new JLabel("Host");
        showlabel.setFont(displayFont);
        northPanel.add(showlabel);
        northPanel.add(inputHost);
        showlabel = new JLabel("Port Number");
        showlabel.setFont(displayFont);
        northPanel.add(showlabel);
        northPanel.add(inputPort);
        showlabel = new JLabel("Your Name");
        showlabel.setFont(displayFont);
        northPanel.add(showlabel);
        northPanel.add(inputName);
        northPanel.add(inputSwitch);
        northPanel.add(inputRandom);
        northPanel.add(inputAssign);
    }

    private void createCenterPanel() {
        Font displayFont = new Font("Serif", Font.BOLD, 18);
        Font displayFontII = new Font("Serif", Font.BOLD, 24);
        centerPanel = new JPanel();
        centerPanel.setBorder(new TitledBorder("Server Information"));
        userListModel = new DefaultListModel();

        userList = new JList(userListModel);
        contentArea = new JTextArea();

        userList.setBackground(Color.BLACK);
        userList.setFont(displayFont);
        userList.setForeground(Color.GREEN);
        contentArea.setBackground(Color.BLACK);
        contentArea.setForeground(Color.ORANGE);
        contentArea.setFont(displayFontII);

        JScrollPane leftPane = new JScrollPane(userList);
        JScrollPane rightPane = new JScrollPane(contentArea);
        JSplitPane splitPane1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                leftPane, rightPane);
        splitPane1.setDividerLocation(100);
        leftPane.setBorder(new TitledBorder("User List"));
        rightPane.setBorder(new TitledBorder("Room"));
        rightPane.getVerticalScrollBar().addAdjustmentListener(
                new AdjustmentListener() {
                    boolean locked = true;
                    JScrollBar sb;

                    private AdjustmentListener init(JScrollBar sb) {
                        this.sb = sb;
                        return this;
                    }

                    public void adjustmentValueChanged(AdjustmentEvent e) {
                        if (sb.getMaximum() - sb.getValue() - sb.getHeight() > 200)
                            locked = false;
                        else
                            locked = true;
                        /*
                         * System.out.println(sb.getValue() + sb.getHeight() +
                         * ", " + sb.getMaximum() + locked);
                         */
                        if (locked == true) {
                            sb.setValue(sb.getMaximum());
                        }
                    }
                }.init(rightPane.getVerticalScrollBar()));
        centerPanel.setLayout(new BorderLayout());
        centerPanel.add(splitPane1, BorderLayout.CENTER);
    }

    private void createSouthPanel() {
        Font displayFont = new Font("Serif", Font.BOLD, 18);
        Font displayFontII = new Font("Serif", Font.BOLD, 24);
        southPanel = new JPanel();
        southPanel.setBorder(new TitledBorder("Input Message ..."));

        inputMsg = new JTextField();
        sendBtn = new JButton("SEND");

        inputMsg.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                clientTalk();// touch [Enter] key.
                inputMsg.setText("");
            }
        });
        sendBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                clientTalk();
                inputMsg.setText("");
            }
        });

        southPanel.setLayout(new BorderLayout());
        southPanel.add(inputMsg, BorderLayout.CENTER);
        southPanel.add(sendBtn, BorderLayout.EAST);
    }

    private boolean openSocket() {
        if (clientRunning)
            return false;
        try {
            int port;
            String host, name;
            port = Integer.parseInt(inputPort.getText());
            host = inputHost.getText();
            name = inputName.getText();
            if (name.length() == 0)
                return false;
            clientSocket = new Socket(host, port);
            clientWriter = new PrintWriter(new OutputStreamWriter(
                    clientSocket.getOutputStream(), "UTF-8"));
            clientReader = new BufferedReader(new InputStreamReader(
                    clientSocket.getInputStream(), "UTF-8"));
            clientCmdTalk(name + "@" + gameServer.gameServerPort);
            clientThread = new ClientThread();
            clientThread.start();
            clientRunning = true;
            inputPort.setEnabled(false);
            inputHost.setEnabled(false);
            inputName.setEnabled(false);
            return true;
        } catch (Exception ee) {
            showServerErr(ee.getMessage());
        }
        return false;
    }

    public boolean closeSocket() {
        try {
            clientCmdTalk("CLOSE");
            clientRunning = false;
            inputPort.setEnabled(true);
            inputHost.setEnabled(true);
            inputName.setEnabled(true);
            clientSocket.close();
            userListModel.clear();
            clientThread.stop();
            contentArea.append("You have left the room.\r\n");
            return true;
        } catch (Exception ee) {
            showServerErr(ee.getMessage());
        }
        return false;
    }

    private void showServerErr(String err) {
        contentArea.append("Err[" + err + "]\r\n");
    }

    private void clientQueryGame(String player) {
        if (player.length() == 0)
            clientCmdTalk("GR");
        gamePanel.setVisible(true);
        chatPanel.setVisible(false);
    }

    private void clientStartGame(String role) {
        gameShowPanel.initGame(role);
    }

    void clientExitGame() {
        clientCmdTalk("GE");
        if (gameClient != null) {
            try {
                gameClient.closeGameSocket();
            } catch (Exception e) {

            }
        }
        // System.out.println("clientExitGame");
        gameServer.gameServerCmdTalk("CLOSE");
        // System.out.println(inputName.getText() + "clientExitGame");
        gamePanel.setVisible(false);
        chatPanel.setVisible(true);
        repaint();
    }

    private void clientCmdTalk(String str) {
        if (clientWriter != null) {
            clientWriter.println(str);
            clientWriter.flush();
        }
    }

    private void clientTalk() {
        if (clientWriter != null) {
            // System.out.println("SEND" + inputMsg.getText());
            clientWriter.println("T@" + inputMsg.getText());
            clientWriter.flush();
        }
    }

    class ClientThread extends Thread { // listen server command
        public ClientThread() {
        }

        public void run() {
            String msg;
            while (clientRunning) {
                try {
                    msg = clientReader.readLine();
                    if (msg == null || msg.length() == 0)
                        continue;
                    // System.out.println("client receive from server, " + msg);
                    StringTokenizer st = new StringTokenizer(msg, "@");
                    msg = st.nextToken();
                    if (msg.equals("CLOSE")) {
                        // System.out.println("do closing");
                        closeSocket();
                        inputSwitch.setSelected(false);
                        inputSwitch.setText("OFF");
                    } else if (msg.equals("S")) {
                        contentArea
                                .append("System> " + st.nextToken() + "\r\n");
                    } else if (msg.equals("M")) {
                        msg = st.nextToken();
                        while (st.hasMoreTokens())
                            msg += "@" + st.nextToken();
                        contentArea.append(msg + "\r\n");
                    } else if (msg.equals("A")) {
                        userListModel.addElement(st.nextToken());
                    } else if (msg.equals("D")) {
                        userListModel.removeElement(st.nextToken());
                    } else if (msg.equals("E")) {
                        contentArea
                                .append("System> " + st.nextToken() + "\r\n");
                        // System.out.println("do closing");
                        closeSocket();
                        inputSwitch.setSelected(false);
                        inputSwitch.setText("OFF");
                    } else if (msg.equals("GLS")) {
                        int port = Integer.parseInt(st.nextToken());
                        String ip = st.nextToken();
                        // System.out.println(inputName.getText() + ", GLS, "
                        // + port + "," + ip);
                        gameClient = new GameClient(port, ip);
                    }
                } catch (Exception e) {
                    showServerErr("ClientThread" + e.getMessage());
                }
            }
        }

    }

    class GameClient {// be a client to link gameserver
        private Socket gameClientSocket;
        private PrintWriter gameClientWriter;
        private BufferedReader gameClientReader;
        private GameClientThread gameClientThread;
        private boolean gameClientRunning;

        private Timer gameTimer;
        Point Gpos;
        Point Rpos;
        int GTeamSpeed;
        int GTeamDir, GnextDir;
        int inverseDir[] = { 2, 3, 0, 1 };

        public GameClient(int port, String hostIP) {
            try {
                gameClientSocket = new Socket(hostIP, port);
                gameClientWriter = new PrintWriter(new OutputStreamWriter(
                        gameClientSocket.getOutputStream(), "UTF-8"));
                gameClientReader = new BufferedReader(new InputStreamReader(
                        gameClientSocket.getInputStream(), "UTF-8"));
                gameClientWriter.println(inputName.getText());
                gameClientWriter.flush();
                gameClientThread = new GameClientThread();
                gameClientThread.start();
                gameClientRunning = true;
                gameTimer = new Timer();
                gameTimer.schedule(new GameProcess(), 5000, 50);
            } catch (Exception ee) {
                showServerErr(ee.getMessage());
            }
        }

        public boolean closeGameSocket() {
            try {
                // System.out.println("closeGameSocket1");
                gameClientCmdTalk("CLOSE");
                gameClientRunning = false;
                gameClientSocket.close();
                if (gameTimer != null)
                    gameTimer.cancel();
                // System.out.println("closeGameSocket2");
                contentArea.append("You have left Game.\r\n");
                // System.out.println("closeGameSocket3");
                return true;
            } catch (Exception ee) {
                showServerErr(ee.getMessage());
            }
            return false;
        }

        private void gameClientCmdTalk(String str) {
            if (gameClientWriter != null) {
                gameClientWriter.println(str);
                gameClientWriter.flush();
            }
        }

        void processSnakeDir(int dir, int team) {
            if (team == 1) {
                if (dir != inverseDir[GTeamDir])
                    GnextDir = dir;
            }
        }

        class GameClientThread extends Thread {// listen from gameserver
            public GameClientThread() {
                // System.out.println("listen from gameserver");
            }

            public void run() {
                String msg;
                while (gameClientRunning) {
                    try {
                        msg = gameClientReader.readLine();
                        if (msg == null || msg.length() == 0)
                            continue;
                        // System.out
                        // .println("gameclient receive from gameserver, "
                        // + msg);
                        StringTokenizer st = new StringTokenizer(msg, "@");
                        msg = st.nextToken();
                        if (msg.equals("CLOSE")) {
                            // System.out.println("do closing");
                            clientExitGame();
                        } else if (msg.equals("GOK")) {
                            clientStartGame("Client");
                            int width = gameShowPanel.board.length;
                            int height = gameShowPanel.board[0].length;
                            Gpos = new Point(10, height / 2);
                            Rpos = new Point(width - 11, height / 2);
                            GTeamSpeed = 3;
                            GTeamDir = 1;
                            GnextDir = 1;
                            gameShowPanel.moveSnake(10, height / 2, 1);
                            gameShowPanel.moveSnake(width - 11, height / 2, 2);
                        } else if (msg.equals("M")) {
                            int team = Integer.parseInt(st.nextToken());
                            int x = Integer.parseInt(st.nextToken());
                            int y = Integer.parseInt(st.nextToken());
                            gameShowPanel.moveSnake(x, y, team);
                        } else if (msg.equals("E")) {
                            int x = Integer.parseInt(st.nextToken());
                            int y = Integer.parseInt(st.nextToken());
                            gameShowPanel.eraseBoard(x, y);
                        } else if (msg.equals("P")) {
                            int x = Integer.parseInt(st.nextToken());
                            int y = Integer.parseInt(st.nextToken());
                            int p = Integer.parseInt(st.nextToken());
                            gameShowPanel.setProps(x, y, (byte) p);
                        } else if (msg.equals("EF")) {
                            int x = Integer.parseInt(st.nextToken());
                            int y = Integer.parseInt(st.nextToken());
                            int dir = Integer.parseInt(st.nextToken());
                            gameShowPanel.getFireCmd(x, y, dir);
                        } else if (msg.equals("ES")) {
                            int x = Integer.parseInt(st.nextToken());
                            int y = Integer.parseInt(st.nextToken());
                            int dir = Integer.parseInt(st.nextToken());
                            gameShowPanel.getSunCmd(x, y, dir);
                        } else if (msg.equals("ER")) {
                            int x = Integer.parseInt(st.nextToken());
                            int y = Integer.parseInt(st.nextToken());
                            int dir = Integer.parseInt(st.nextToken());
                            int cnt = Integer.parseInt(st.nextToken());
                            gameShowPanel.eraseRandom(x, y, dir, cnt);
                        }
                    } catch (Exception e) {
                        showServerErr("GameClientThread" + e.getMessage());
                    }
                }
            }
        }

        class GameProcess extends TimerTask {
            private int timeCounter = 0;
            int dx[] = { 0, 1, 0, -1 };
            int dy[] = { -1, 0, 1, 0 };
            int mdx[] = { 0, -1, 0, 1 };
            int mdy[] = { -1, 0, 1, 0 };

            public void run() {
                timeCounter++;
                if (timeCounter % 15 == 0) {
                    String cmd = gameShowPanel.eraseRandom();
                    gameClientCmdTalk(cmd);
                }
                int Gprops = 0, Rprops = 0;
                if (timeCounter % (6 - GTeamSpeed) == 0) {
                    GnextDir = gameShowPanel.autoGuided(1, GTeamDir, GnextDir);
                    GTeamDir = GnextDir;
                    Gpos.x = Gpos.x + dx[GTeamDir];
                    Gpos.y = Gpos.y + dy[GTeamDir];
                    Rpos.x = Rpos.x + mdx[GTeamDir];
                    Rpos.y = Rpos.y + mdy[GTeamDir];
                    Gprops = gameShowPanel.moveSnake(Gpos.x, Gpos.y, 1);
                    gameClientCmdTalk("M@2@" + Rpos.x + "@" + Rpos.y);
                }
                if (Gprops < 0) {
                    if (Gprops == -1) {
                        String cmd = gameShowPanel.getFireCmd(Gpos.x, Gpos.y,
                                GTeamDir);
                        System.out.println("Fire" + cmd);
                        gameClientCmdTalk(cmd);
                    }
                    if (Gprops == -2) {
                        String cmd = gameShowPanel.getSunCmd(Gpos.x, Gpos.y,
                                GTeamDir);
                        gameClientCmdTalk(cmd);
                    }
                    if (Gprops == -3) {
                        if (GTeamSpeed > 1)
                            GTeamSpeed--;
                    }
                    if (Gprops == -4) {
                        if (GTeamSpeed < 5)
                            GTeamSpeed++;
                    }
                }
                // System.out.println("GameProcess");
            }
        }
    }

    class GameServer {
        private boolean gameServerRunning = false;
        private ServerSocket gameServerSocket;
        private GameServerThread gameServerThread;
        private GameClientThread gameClientThread;
        private int gameServerPort;
        /* <Game Part Information> */
        private Timer gameTimer;
        Point Gpos;
        Point Rpos;
        int GTeamSpeed;
        int GTeamDir, GnextDir;
        int inverseDir[] = { 2, 3, 0, 1 };

        /* </Game Part Information> */

        public GameServer() {
            while (!openServer())
                ;
        }

        private boolean openServer() {
            if (gameServerRunning)
                return false;
            try {
                int port, limitcap;
                port = (int) (Math.random() * 60000) + 1023;
                limitcap = 1;
                gameServerSocket = new ServerSocket(port);
                gameServerThread = new GameServerThread(gameServerSocket,
                        limitcap);
                gameServerThread.start();
                gameServerRunning = true;
                gameServerPort = port;
                return true;
            } catch (java.net.BindException be) {
                showServerErr(be.getMessage());
            } catch (Exception ee) {
                showServerErr(ee.getMessage());
            }
            return false;
        }

        public boolean closeServer() {
            try {
                gameServerCmdTalk("CLOSE");
                gameServerThread.stop();
                gameServerSocket.close();
                gameServerRunning = false;
                return true;
            } catch (Exception ee) {
                showServerErr(ee.getMessage());
            }
            return false;
        }

        void gameServerCmdTalk(String str) {
            if (gameClientThread != null) {
                // System.out.println("gameServerCmd, " + str);
                gameClientThread.getWriter().println(str);
                gameClientThread.getWriter().flush();
            }
        }

        void processSnakeDir(int dir, int team) {
            if (team == 1) {
                if (dir != inverseDir[GTeamDir])
                    GnextDir = dir;
            }
        }

        class GameServerThread extends Thread {
            private ServerSocket serverSocket;
            private int limitCap;

            public GameServerThread(ServerSocket serverSocket, int limitCap) {
                this.serverSocket = serverSocket;
                this.limitCap = limitCap;
            }

            public void run() {
                Socket socket;
                BufferedReader reader;
                PrintWriter writer;
                ClientThread clientThread;
                User user;
                while (true) {
                    try {
                        socket = gameServerSocket.accept();
                        reader = new BufferedReader(new InputStreamReader(
                                socket.getInputStream()));
                        writer = new PrintWriter(socket.getOutputStream());
                        String userName = reader.readLine();
                        user = new User(userName, socket.getInetAddress()
                                .getHostAddress().toString());
                        // System.out.println("GameServerThread, " + userName);
                        clientStartGame("Server");
                        gameClientThread = new GameClientThread(socket, user);
                        gameClientThread.start();
                        gameTimer = new Timer();
                        gameTimer.schedule(new GameProcess(), 5000, 50);
                    } catch (Exception ee) {
                        // System.out.println("GameServerThread Err "
                        // + ee.getMessage());
                    }
                }
            }
        }

        class GameClientThread extends Thread {// listen from gameclient
            private Socket gameSocket;
            private User user;
            private BufferedReader reader;
            private PrintWriter writer;

            public GameClientThread(Socket socket, User user) {
                try {
                    this.gameSocket = socket;
                    this.user = user;
                    this.reader = new BufferedReader(new InputStreamReader(
                            gameSocket.getInputStream(), "UTF-8"));
                    this.writer = new PrintWriter(new OutputStreamWriter(
                            gameSocket.getOutputStream(), "UTF-8"));
                    // System.out.println("send GOK command");
                    writer.println("GOK");
                    writer.flush();
                    int width = gameShowPanel.board.length;
                    int height = gameShowPanel.board[0].length;
                    Gpos = new Point(10, height / 2);
                    Rpos = new Point(width - 11, height / 2);
                    GTeamSpeed = 3;
                    GTeamDir = 1;
                    GnextDir = 1;
                    gameShowPanel.moveSnake(10, height / 2, 1);
                    gameShowPanel.moveSnake(width - 11, height / 2, 2);
                    writer.flush();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            public void closeGameSocket() {
                try {
                    clientExitGame();
                    gameTimer.cancel();
                    // System.out.println("game socket close");
                    gameSocket.close();
                    this.stop();
                } catch (Exception e) {
                }
            }

            public void run() {
                String msg;
                while (true) {
                    try {
                        msg = reader.readLine();
                        dispatcherMessage(msg);
                    } catch (Exception e) {

                    }
                }
            }

            public void dispatcherMessage(String msg) {
                if (msg == null || msg.length() == 0)
                    return;
                /*
                 * System.out.println(inputName.getText() +
                 * "receive game client send, " + msg);
                 */
                StringTokenizer st = new StringTokenizer(msg, "@");
                msg = st.nextToken();
                if (msg.equals("CLOSE")) {
                    closeGameSocket();
                } else if (msg.equals("D")) {
                    int team = Integer.parseInt(st.nextToken());
                    int dir = Integer.parseInt(st.nextToken());
                    gameServer.processSnakeDir(dir, team);
                } else if (msg.equals("M")) {
                    int team = Integer.parseInt(st.nextToken());
                    int x = Integer.parseInt(st.nextToken());
                    int y = Integer.parseInt(st.nextToken());
                    gameShowPanel.moveSnake(x, y, team);
                } else if (msg.equals("E")) {
                    int x = Integer.parseInt(st.nextToken());
                    int y = Integer.parseInt(st.nextToken());
                    gameShowPanel.eraseBoard(x, y);
                } else if (msg.equals("P")) {
                    int x = Integer.parseInt(st.nextToken());
                    int y = Integer.parseInt(st.nextToken());
                    int p = Integer.parseInt(st.nextToken());
                    gameShowPanel.setProps(x, y, (byte) p);
                } else if (msg.equals("EF")) {
                    int x = Integer.parseInt(st.nextToken());
                    int y = Integer.parseInt(st.nextToken());
                    int dir = Integer.parseInt(st.nextToken());
                    gameShowPanel.getFireCmd(x, y, dir);
                } else if (msg.equals("ES")) {
                    int x = Integer.parseInt(st.nextToken());
                    int y = Integer.parseInt(st.nextToken());
                    int dir = Integer.parseInt(st.nextToken());
                    gameShowPanel.getSunCmd(x, y, dir);
                } else if (msg.equals("ER")) {
                    int x = Integer.parseInt(st.nextToken());
                    int y = Integer.parseInt(st.nextToken());
                    int dir = Integer.parseInt(st.nextToken());
                    int cnt = Integer.parseInt(st.nextToken());
                    gameShowPanel.eraseRandom(x, y, dir, cnt);
                }
            }

            public BufferedReader getReader() {
                return reader;
            }

            public PrintWriter getWriter() {
                return writer;
            }
        }

        class GameProcess extends TimerTask {
            private int timeCounter = 0;
            int dx[] = { 0, 1, 0, -1 };
            int dy[] = { -1, 0, 1, 0 };
            int mdx[] = { 0, -1, 0, 1 };
            int mdy[] = { -1, 0, 1, 0 };

            public void run() {
                timeCounter++;
                if (timeCounter % 15 == 0) {
                    String cmd = gameShowPanel.eraseRandom();
                    gameServerCmdTalk(cmd);
                }
                int Gprops = 0, Rprops = 0;
                if (timeCounter % (6 - GTeamSpeed) == 0) {
                    GnextDir = gameShowPanel.autoGuided(1, GTeamDir, GnextDir);
                    GTeamDir = GnextDir;
                    Gpos.x = Gpos.x + dx[GTeamDir];
                    Gpos.y = Gpos.y + dy[GTeamDir];
                    Rpos.x = Rpos.x + mdx[GTeamDir];
                    Rpos.y = Rpos.y + mdy[GTeamDir];
                    Gprops = gameShowPanel.moveSnake(Gpos.x, Gpos.y, 1);
                    gameServerCmdTalk("M@2@" + Rpos.x + "@" + Rpos.y);
                }
                if (Gprops < 0) {
                    if (Gprops == -1) {
                        String cmd = gameShowPanel.getFireCmd(Gpos.x, Gpos.y,
                                GTeamDir);
                        //System.out.println("Fire" + cmd);
                        gameServerCmdTalk(cmd);
                    }
                    if (Gprops == -2) {
                        String cmd = gameShowPanel.getSunCmd(Gpos.x, Gpos.y,
                                GTeamDir);
                        gameServerCmdTalk(cmd);
                    }
                    if (Gprops == -3) {
                        if (GTeamSpeed > 1)
                            GTeamSpeed--;
                    }
                    if (Gprops == -4) {
                        if (GTeamSpeed < 5)
                            GTeamSpeed++;
                    }
                }
                if (timeCounter % 150 == 0) {
                    String cmd = gameShowPanel.addProps();
                    gameServerCmdTalk(cmd);
                }
                // System.out.println("GameProcess");
            }
        }
    }
}




package Client;

import java.util.*;
import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.net.URL;

public class GamePanel extends JPanel implements KeyEventDispatcher {
    private Hashtable imgTable = new Hashtable();
    private String role;
    public byte[][] board;
    Point G;
    Point R;
    int dx[] = { 0, 1, 0, -1 };
    int dy[] = { -1, 0, 1, 0 };

    public void initGame(String role) {
        System.out.println("initGame " + this.getWidth() + "nnm,,"
                + this.getHeight());
        board = new byte[774 / 20][569 / 20];
        this.role = role;
        repaint();
    }

    private boolean hasCoverHead(int x, int y) {
        if (x == G.x && y == G.y)
            return true;
        if (x == R.x && y == R.y)
            return true;
        return false;
    }

    public boolean validMove(int x, int y) {
        if (x < 0 || y < 0 || x >= board.length || y >= board[0].length)
            return false;
        return board[x][y] <= 0;
    }

    public int autoGuided(int team, int nowDir, int nextDir) {
        int x, y, tx, ty;
        if (team == 1) {
            x = G.x;
            y = G.y;
        } else {
            x = R.x;
            y = R.y;
        }
        tx = x + dx[nextDir];
        ty = y + dy[nextDir];
        if (validMove(tx, ty))
            return nextDir;
        for (int i = nowDir, j = 0; j < 4; j++, i = (i + 1) % 4) {
            tx = x + dx[i];
            ty = y + dy[i];
            if (validMove(tx, ty))
                return i;
        }
        return nextDir;
    }

    public void eraseBoard(int x, int y) {
        board[x][y] = 0;
    }

    public void setProps(int x, int y, byte c) {
        board[x][y] = c;
    }

    public void eraseRandom(int x, int y, int dir, int cnt) {
        if (dir == 1) {
            while (x < board.length && cnt > 0) {
                board[x][y] = 0;
                x--;
                cnt--;
            }
        } else {
            while (y < board[0].length && cnt > 0) {
                board[x][y] = 0;
                y++;
                cnt--;
            }
        }
    }

    public String eraseRandom() {
        int x = (int) (Math.random() * board.length);
        int y = (int) (Math.random() * board[0].length);
        int cnt = 0;
        String ret;
        if (Math.random() > 0.5) {
            ret = "ER@" + (board.length - x - 1) + "@" + y + "@1@";
            while (x < board.length && !hasCoverHead(x, y) && cnt < 5) {
                // ret += "E@" + x + "@" + y + "\r\n";
                board[x][y] = 0;
                x++;
                cnt++;
            }
            if (cnt == 0)
                return "";
            else
                return ret + cnt + "\n";
        } else {
            ret = "ER@" + (board.length - x - 1) + "@" + y + "@2@";
            while (y < board[0].length && !hasCoverHead(x, y) && cnt < 5) {
                // ret += "E@" + x + "@" + y + "\r\n";
                board[x][y] = 0;
                y++;
                cnt++;
            }
            if (cnt == 0)
                return "";
            else
                return ret + cnt + "\n";
        }
    }

    public String addProps() {
        String ret = "";
        double p;
        for (int i = 0; i < 3; i++) {
            int tryTime = 30, x, y;
            while (tryTime >= 0) {
                x = (int) (Math.random() * board.length);
                y = (int) (Math.random() * board[0].length);
                tryTime--;
                if (board[x][y] == 0) {
                    p = Math.random();
                    if (p < 0.35) {// fire
                        board[x][y] = -1;
                        ret += "P@" + (board.length - x - 1) + "@" + y + "@-1"
                                + "\r\n";
                    } else if (p < 0.70) {// sun
                        board[x][y] = -2;
                        ret += "P@" + (board.length - x - 1) + "@" + y + "@-2"
                                + "\r\n";
                    } else if (p < 0.85) {// ice
                        board[x][y] = -3;
                        ret += "P@" + (board.length - x - 1) + "@" + y + "@-3"
                                + "\r\n";
                    } else {// water
                        board[x][y] = -4;
                        ret += "P@" + (board.length - x - 1) + "@" + y + "@-4"
                                + "\r\n";
                    }
                    break;
                }
            }
        }
        return ret;
    }

    public int moveSnake(int x, int y, int team) {
        if (!validMove(x, y)) {
            if (role.equals("Server")) {
                ((ControlPanel) (this.getParent().getParent()))
                        .clientExitGame();
            }
            return 1;
        }
        int ret = board[x][y];
        board[x][y] = 1;
        if (team == 1) {
            G = new Point(x, y);
        } else {
            R = new Point(x, y);
        }
        repaint();
        return ret;
    }

    public String getFireCmd(int x, int y, int dir) {
        String ret = "EF@" + (board.length - x - 1) + "@" + y + "@" + dir
                + "\n";
        for (int i = 0; i < 8; i++) {
            x += dx[dir];
            y += dy[dir];
            if (x < 0 || y < 0 || x >= board.length || y >= board[0].length)
                return ret;
            board[x][y] = 0;
        }
        return ret;
    }

    public String getSunCmd(int x, int y, int dir) {
        String ret = "ES@" + (board.length - x - 1) + "@" + y + "@" + dir
                + "\n";
        for (int i = -2; i < 2; i++) {
            for (int j = -2; j < 2; j++) {
                int tx = x + i;
                int ty = y + j;
                if (tx < 0 || ty < 0 || tx >= board.length
                        || ty >= board[0].length)
                    continue;
                board[tx][ty] = 0;
            }
        }
        return ret;
    }

    public GamePanel() {
        BufferedImage img = null;
        String fileName[] = { "background.jpg", "sbody.png", "srhead.png",
                "sghead.png", "Efire.png", "Esun.png", "Eice.png",
                "Ewater.png", "counter.gif", "TESTGIF.gif" };
        String fileIdx[] = { "background", "sbody", "srhead", "sghead",
                "Efire", "Esun", "Eice", "Ewater", "counter", "TESTGIF" };
        try {
            for (int i = 0; i < fileName.length; i++) {
                // img = ImageIO.read(new File(fileName[i]));
                img = ImageIO.read(this.getClass().getResource(fileName[i]));
                imgTable.put(fileIdx[i], new ImageIcon(img));
            }
        } catch (Exception e) {
            System.out.println("Err" + e.getMessage());
        }
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
                .addKeyEventDispatcher(this);
    }

    /*
     * @Override public void paint(Graphics g) { super.paint(g); ImageIcon
     * background = (ImageIcon) imgTable.get("background"); ImageIcon sbody =
     * (ImageIcon) imgTable.get("sbody"); ImageIcon sghead = (ImageIcon)
     * imgTable.get("sghead"); ImageIcon srhead = (ImageIcon)
     * imgTable.get("srhead"); ImageIcon efire = (ImageIcon)
     * imgTable.get("Efire"); ImageIcon esun = (ImageIcon) imgTable.get("Esun");
     * ImageIcon eice = (ImageIcon) imgTable.get("Eice"); ImageIcon ewater =
     * (ImageIcon) imgTable.get("Ewater"); ImageIcon OP = (ImageIcon)
     * imgTable.get("counter");
     *
     * g.drawImage(background.getImage(), 0, 0, this.getWidth(),
     * this.getHeight(), this); if (board != null) { for (int i = 0; i <
     * board.length; i++) { for (int j = 0; j < board[i].length; j++) { if
     * (board[i][j] == 0) continue; if (board[i][j] == 1)
     * g.drawImage(sbody.getImage(), i * 20, j * 20, 20, 20, this); if
     * (board[i][j] == -1) g.drawImage(efire.getImage(), i * 20, j * 20, 20, 20,
     * this); if (board[i][j] == -2) g.drawImage(esun.getImage(), i * 20, j *
     * 20, 20, 20, this); if (board[i][j] == -3) g.drawImage(eice.getImage(), i
     * * 20, j * 20, 20, 20, this); if (board[i][j] == -4)
     * g.drawImage(ewater.getImage(), i * 20, j * 20, 20, 20, this); } } if (G
     * != null) g.drawImage(sghead.getImage(), G.x * 20 - 15, G.y * 20 - 15, 50,
     * 50, this); if (R != null) g.drawImage(srhead.getImage(), R.x * 20 - 15,
     * R.y * 20 - 15, 50, 50, this); } }
     */
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        ImageIcon background = (ImageIcon) imgTable.get("background");
        ImageIcon sbody = (ImageIcon) imgTable.get("sbody");
        ImageIcon sghead = (ImageIcon) imgTable.get("sghead");
        ImageIcon srhead = (ImageIcon) imgTable.get("srhead");
        ImageIcon efire = (ImageIcon) imgTable.get("Efire");
        ImageIcon esun = (ImageIcon) imgTable.get("Esun");
        ImageIcon eice = (ImageIcon) imgTable.get("Eice");
        ImageIcon ewater = (ImageIcon) imgTable.get("Ewater");
        ImageIcon OP = (ImageIcon) imgTable.get("counter");
        // System.out.println(this.getWidth() + "m,," + this.getHeight());
        g.drawImage(background.getImage(), 0, 0, this.getWidth(),
                this.getHeight(), this);
        if (board != null) {
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board[i].length; j++) {
                    if (board[i][j] == 0)
                        continue;
                    if (board[i][j] == 1)
                        g.drawImage(sbody.getImage(), i * 20, j * 20, 20, 20,
                                this);
                    if (board[i][j] == -1)
                        g.drawImage(efire.getImage(), i * 20, j * 20, 20, 20,
                                this);
                    if (board[i][j] == -2)
                        g.drawImage(esun.getImage(), i * 20, j * 20, 20, 20,
                                this);
                    if (board[i][j] == -3)
                        g.drawImage(eice.getImage(), i * 20, j * 20, 20, 20,
                                this);
                    if (board[i][j] == -4)
                        g.drawImage(ewater.getImage(), i * 20, j * 20, 20, 20,
                                this);
                }
            }
            if (G != null)
                g.drawImage(sghead.getImage(), G.x * 20 - 15, G.y * 20 - 15,
                        50, 50, this);
            if (R != null)
                g.drawImage(srhead.getImage(), R.x * 20 - 15, R.y * 20 - 15,
                        50, 50, this);
        }
    }

    public boolean dispatchKeyEvent(KeyEvent e) {
        if (e.getID() == KeyEvent.KEY_RELEASED)
            return false;
        int dir;
        switch (e.getKeyCode()) {
        case KeyEvent.VK_DOWN:
            dir = 2;
            System.out.println("DOWN");
            break;
        case KeyEvent.VK_UP:
            dir = 0;
            System.out.println("UP");
            break;
        case KeyEvent.VK_RIGHT:
            dir = 1;
            System.out.println("RIGHT");
            break;
        case KeyEvent.VK_LEFT:
            dir = 3;
            System.out.println("LEFT");
            break;
        default:
            return false;
        }
        /*
         * if (parent.txtMsg.getText().equals("")) parent.sendGame();
         */
        if (role.equals("Server")) {
            ((ControlPanel) (this.getParent().getParent())).gameServer
                    .processSnakeDir(dir, 1);
        } else {
            ((ControlPanel) (this.getParent().getParent())).gameClient
                    .processSnakeDir(dir, 1);
        }
        return false;
    }
}

package Client;

import java.io.*;

import java.lang.Thread;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class MClient extends JFrame {
    private ControlPanel controlPanel;

    public MClient() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("MClient");
        this.setSize(800, 650);
        this.setResizable(false);
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                controlPanel.closeSocket();
                if (controlPanel.gameServer != null)
                    controlPanel.gameServer.closeServer();
                if (controlPanel.gameClient != null)
                    controlPanel.gameClient.closeGameSocket();
            }
        });
        controlPanel = new ControlPanel();
        this.add(controlPanel);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        new MClient();
    }
}

package Client;

public class User {
    private String name;
    private String ip;

    public User(String name, String ip) {
        this.name = name;
        this.ip = ip;
    }

    public String getUserName() {
        return name;
    }

    public String getIP() {
        return ip;
    }

    public void setUserName(String name) {
        this.name = name;
    }

    public void setIP(String ip) {
        this.ip = ip;
    }
}

package Server;

import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import java.io.*;

import java.util.*;

import java.lang.Thread;

import javax.swing.*;
import javax.swing.border.*;

import java.awt.*;
import java.awt.event.*;

public class ControlPanel extends JPanel {
    private JTextField inputPort;
    private JTextField inputLimitCap;
    private JToggleButton inputSwitch;
    private JPanel northPanel;

    private JTextArea contentArea;
    private JList userList;
    private DefaultListModel userListModel;
    private JList gameList;
    private DefaultListModel gameListModel;
    private JPanel centerPanel;

    private JTextField inputMsg;
    private JButton sendBtn;
    private JPanel southPanel;

    private boolean serverRunning = false;
    private ServerSocket serverSocket;
    private ServerThread serverThread;
    private ArrayList<ClientThread> clientList;

    private void createNorthPanel() {
        Font displayFont = new Font("Serif", Font.BOLD, 18);
        northPanel = new JPanel();
        northPanel.setBorder(new TitledBorder("Setting"));
        northPanel.setLayout(new GridLayout(1, 5));

        inputLimitCap = new JTextField("10");
        inputPort = new JTextField("4096");
        inputSwitch = new JToggleButton("OFF");

        inputLimitCap.setFont(displayFont);
        inputPort.setFont(displayFont);
        inputSwitch.setFont(displayFont);
        inputSwitch.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    if (openServer()) {
                        inputSwitch.setText("ON");
                        inputPort.setEnabled(false);
                        inputLimitCap.setEnabled(false);
                    } else if (!serverRunning) {
                        inputSwitch.setSelected(false);
                    }
                } else if (e.getStateChange() == ItemEvent.DESELECTED) {
                    if (closeServer()) {
                        inputSwitch.setText("OFF");
                        inputPort.setEnabled(true);
                        inputLimitCap.setEnabled(true);
                    } else if (serverRunning) {
                        inputSwitch.setSelected(true);
                    }
                }
            }
        });

        JLabel showlabel;
        showlabel = new JLabel("Limit Capacity");
        showlabel.setFont(displayFont);
        northPanel.add(showlabel);
        northPanel.add(inputLimitCap);
        showlabel = new JLabel("Port Number");
        showlabel.setFont(displayFont);
        northPanel.add(showlabel);
        northPanel.add(inputPort);
        northPanel.add(inputSwitch);
    }

    private void createCenterPanel() {
        Font displayFont = new Font("Serif", Font.BOLD, 18);
        Font displayFontII = new Font("Serif", Font.BOLD, 24);
        centerPanel = new JPanel();
        centerPanel.setBorder(new TitledBorder("Server Information"));
        userListModel = new DefaultListModel();
        gameListModel = new DefaultListModel();

        userList = new JList(userListModel);
        gameList = new JList(gameListModel);
        contentArea = new JTextArea();

        userList.setBackground(Color.BLACK);
        userList.setForeground(Color.GREEN);
        userList.setFont(displayFont);
        gameList.setBackground(Color.BLACK);
        gameList.setForeground(Color.GREEN);
        gameList.setFont(displayFont);
        contentArea.setBackground(Color.BLACK);
        contentArea.setForeground(Color.ORANGE);
        contentArea.setFont(displayFontII);

        JScrollPane leftPane = new JScrollPane(userList);
        JScrollPane centerPane = new JScrollPane(gameList);
        JScrollPane rightPane = new JScrollPane(contentArea);
        JSplitPane splitPane1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                leftPane, centerPane);
        splitPane1.setDividerLocation(100);
        JSplitPane splitPane2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                splitPane1, rightPane);
        splitPane2.setDividerLocation(250);

        leftPane.setBorder(new TitledBorder("User List"));
        centerPane.setBorder(new TitledBorder("Game List"));
        rightPane.setBorder(new TitledBorder("Room"));

        rightPane.getVerticalScrollBar().addAdjustmentListener(
                new AdjustmentListener() {
                    boolean locked = true;
                    JScrollBar sb;

                    private AdjustmentListener init(JScrollBar sb) {
                        this.sb = sb;
                        return this;
                    }

                    public void adjustmentValueChanged(AdjustmentEvent e) {
                        if (sb.getMaximum() - sb.getValue() - sb.getHeight() > 200)
                            locked = false;
                        else
                            locked = true;
                        System.out.println(sb.getValue() + sb.getHeight()
                                + ", " + sb.getMaximum() + locked);
                        if (locked == true) {
                            sb.setValue(sb.getMaximum());
                        }
                    }
                }.init(rightPane.getVerticalScrollBar()));
        centerPanel.setLayout(new BorderLayout());
        centerPanel.add(splitPane2, BorderLayout.CENTER);
    }

    private void createSouthPanel() {
        Font displayFont = new Font("Serif", Font.BOLD, 18);
        Font displayFontII = new Font("Serif", Font.BOLD, 24);
        southPanel = new JPanel();
        southPanel.setBorder(new TitledBorder("Server Broadcasting"));

        inputMsg = new JTextField();
        sendBtn = new JButton("SEND");

        inputMsg.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                serverBroadcasting();// touch [Enter] key.
            }
        });
        sendBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                serverBroadcasting();
            }
        });

        southPanel.setLayout(new BorderLayout());
        southPanel.add(inputMsg, BorderLayout.CENTER);
        southPanel.add(sendBtn, BorderLayout.EAST);
    }

    private boolean openServer() {
        if (serverRunning)
            return false;
        try {
            int port, limitcap;
            port = Integer.parseInt(this.inputPort.getText());
            limitcap = Integer.parseInt(this.inputLimitCap.getText());
            serverSocket = new ServerSocket(port);
            serverThread = new ServerThread(serverSocket, limitcap);
            serverThread.start();
            clientList = new ArrayList<ClientThread>();
            serverRunning = true;
            return true;
        } catch (java.net.BindException be) {
            showServerErr(be.getMessage());
        } catch (Exception ee) {
            showServerErr(ee.getMessage());
        }
        return false;
    }

    private boolean closeServer() {
        try {
            serverCmdBroadcasting("CLOSE@" + "\r\n");
            serverThread.stop();
            serverSocket.close();
            serverRunning = false;
            userListModel.clear();
            gameListModel.clear();
            for (int i = 0; i < clientList.size(); i++)
                clientList.get(i).stop();
            clientList.clear();
            return true;
        } catch (Exception ee) {
            showServerErr(ee.getMessage());
        }
        return false;
    }

    private void showServerErr(String err) {
        contentArea.append("ServerErr[" + err + "]\r\n");
    }

    private void serverCmdBroadcasting(String str) {
        for (int i = clientList.size() - 1; i >= 0; i--) {
            clientList.get(i).getWriter().println(str);
            clientList.get(i).getWriter().flush();
        }
        contentArea.append("Server Command> " + str);
        inputMsg.setText("");
    }

    private void serverBroadcasting() {
        if (clientList != null) {
            for (int i = clientList.size() - 1; i >= 0; i--) {
                clientList.get(i).getWriter()
                        .println("S@" + inputMsg.getText() + "\r\n");
                clientList.get(i).getWriter().flush();
            }
        }
        contentArea.append("Server> " + inputMsg.getText() + "\r\n");
        inputMsg.setText("");
    }

    private void checkGameQueue() {
        if (gameListModel.size() > 1) {
            int playeri = -1, playerj = -1;
            String player1 = (String) gameListModel.get(0);
            gameListModel.remove(0);
            String player2 = (String) gameListModel.get(0);
            gameListModel.remove(0);
            for (int i = 0; i < clientList.size(); i++) {
                if (clientList.get(i).user.getUserName().equals(player1)) {
                    playeri = i;
                }
                if (clientList.get(i).user.getUserName().equals(player2)) {
                    playerj = i;
                }
            }
            if (playeri < 0 || playerj < 0) {
                System.out.println("checkGameQueue Err 254");
                return;
            }
            System.out.println("GLS@" + clientList.get(playeri).gameServerPort
                    + "@" + clientList.get(playerj).user.getIP());
            System.out.println("GameServer, " + clientList.get(playeri).user.getUserName());
            System.out.println("GameClient, " + clientList.get(playerj).user.getUserName());
            clientList
                    .get(playerj)
                    .getWriter()
                    .println(
                            "GLS@" + clientList.get(playeri).gameServerPort
                                    + "@"
                                    + clientList.get(playeri).user.getIP());
            clientList.get(playerj).getWriter().flush();
        }
    }

    public ControlPanel() {
        createNorthPanel();
        createCenterPanel();
        createSouthPanel();
        this.setLayout(new BorderLayout());
        this.add(northPanel, BorderLayout.NORTH);
        this.add(centerPanel, BorderLayout.CENTER);
        this.add(southPanel, BorderLayout.SOUTH);
    }

    class ServerThread extends Thread {
        private ServerSocket serverSocket;
        private int limitCap;

        public ServerThread(ServerSocket serverSocket, int limitCap) {
            this.serverSocket = serverSocket;
            this.limitCap = limitCap;
        }

        public void run() {
            Socket socket;
            BufferedReader reader;
            PrintWriter writer;
            ClientThread clientThread;
            User user;
            while (true) {
                try {
                    socket = serverSocket.accept();
                    reader = new BufferedReader(new InputStreamReader(
                            socket.getInputStream()));
                    writer = new PrintWriter(socket.getOutputStream());
                    String msg = reader.readLine();
                    StringTokenizer st = new StringTokenizer(msg, "@");
                    String userName = st.nextToken();
                    int gameServerPort = Integer.parseInt(st.nextToken());
                    if (userListModel.size() == limitCap) {
                        writer.println("E@Server busy.");
                        writer.flush();
                        socket.close();
                        continue;
                    }
                    boolean sameNameFlag = false;
                    for (int i = 0; i < userListModel.size(); i++) {
                        if (userListModel.get(i).toString().equals(userName)) {
                            sameNameFlag = true;
                        }
                    }
                    if (sameNameFlag) {
                        writer.println("E@Same Name User");
                        writer.flush();
                        socket.close();
                        continue;
                    }
                    userListModel.addElement(userName);
                    user = new User(userName, socket.getInetAddress()
                            .getHostAddress().toString());
                    clientThread = new ClientThread(socket, user,
                            gameServerPort);
                    clientThread.start();
                    clientList.add(clientThread);
                    inputMsg.setText(userName + " has entered the room.");
                    serverBroadcasting();
                    serverCmdBroadcasting("A@" + user.getUserName() + "\r\n");
                    System.out.println(userName + gameServerPort);
                    System.out.println("ServerThread socket accept");
                    System.out.println(socket.getPort());
                    System.out
                            .println(socket.getInetAddress().getHostAddress());
                } catch (Exception ee) {
                    System.out.println("ServerThread Err " + ee.getMessage());
                }
            }
        }
    }

    class ClientThread extends Thread {// receive message to client
        private Socket socket;
        private User user;
        private BufferedReader reader;
        private PrintWriter writer;
        private int gameServerPort;

        public ClientThread(Socket socket, User user, int gameServerPort) {
            try {
                this.socket = socket;
                this.user = user;
                this.gameServerPort = gameServerPort;
                this.reader = new BufferedReader(new InputStreamReader(
                        socket.getInputStream(), "UTF-8"));
                this.writer = new PrintWriter(new OutputStreamWriter(
                        socket.getOutputStream(), "UTF-8"));
                for (int i = clientList.size() - 1; i >= 0; i--)
                    writer.println("A@" + clientList.get(i).user.getUserName());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void closeSocket() {
            try {
                String msg = user.getUserName() + " has left the room.\r\n";
                inputMsg.setText(msg);
                serverBroadcasting();
                serverCmdBroadcasting("D@" + user.getUserName());

                userListModel.removeElement(user.getUserName());
                for (int i = 0; i < clientList.size(); i++) {
                    if (clientList.get(i).user.getUserName().equals(
                            user.getUserName())) {
                        clientList.remove(i);
                        break;
                    }

                }
                socket.close();
                this.stop();
            } catch (Exception e) {
            }
        }

        public void run() {
            String msg;
            while (true) {
                try {
                    msg = reader.readLine();
                    dispatcherMessage(msg);
                } catch (Exception e) {

                }
            }
        }

        public void dispatcherMessage(String msg) {
            if (msg == null || msg.length() == 0)
                return;
            StringTokenizer st = new StringTokenizer(msg, "@");
            msg = st.nextToken();
            if (msg.equals("T")) {
                String sentence = st.nextToken();
                while (st.hasMoreTokens()) {
                    sentence += "@" + st.nextToken();
                }
                sentence = this.user.getUserName() + "> " + sentence + "\r\n";
                contentArea.append(sentence);
                serverCmdBroadcasting("M@" + sentence);
            } else if (msg.equals("GR")) {// 請求隨機對手
                gameListModel.addElement(this.user.getUserName());
                checkGameQueue();
            } else if (msg.equals("GE")) {// 放棄遊戲
                gameListModel.removeElement(this.user.getUserName());
            } else if (msg.equals("CLOSE")) {
                closeSocket();
            }
        }

        public BufferedReader getReader() {
            return reader;
        }

        public PrintWriter getWriter() {
            return writer;
        }
    }
}

package Server;

import java.io.*;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class MServer extends JFrame {
    public MServer() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("MServer");
        this.setSize(800, 650);
        this.setResizable(false);
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                // practice closing all socket.
            }
        });
        this.add(new ControlPanel());
        this.setVisible(true);
    }
    public static void main(String[] args) {
        new MServer();
    }
}

package Server;

public class User {
    private String name;
    private String ip;

    public User(String name, String ip) {
        this.name = name;
        this.ip = ip;
    }

    public String getUserName() {
        return name;
    }

    public String getIP() {
        return ip;
    }

    public void setUserName(String name) {
        this.name = name;
    }

    public void setIP(String ip) {
        this.ip = ip;
    }
}