package com;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import java.util.Random;
import java.lang.*;
import javax.swing.border.*;
import java.applet.*;
import java.net.*;
import java.io.*;

public class GameTest {
  public GameTest() {

  }

  public static void main(String[] args) throws Exception {

    /*com.incors.plaf.alloy.AlloyLookAndFeel.setProperty("alloy.licenseCode", "yourLicenseCode");
     try {
     javax.swing.LookAndFeel alloyLnF = new com.incors.plaf.alloy.AlloyLookAndFeel();
     javax.swing.UIManager.setLookAndFeel(alloyLnF);
     } catch (javax.swing.UnsupportedLookAndFeelException ex) {
// You may handle the exception here
     }*/

    BabyFrame frame = new BabyFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.show();
    AudioClip sound_play;
    sound_play = Applet.newAudioClip(new URL("file:" +
                                             System.getProperty("user.dir") +
                                             "/" + "ycg.mid"));
    sound_play.loop();
  }
}

class AddrConfig
    extends JFrame {
  public boolean is_serverFlag;
  public JLabel jl_IP, jl_PORT;
  public JTextField jtf_IP, jtf_PORT;
  public JButton jb;
  public JPanel jp_IP, jp_PORT;
  public NetFrame netframe_server = null, netframe_client = null;

  public AddrConfig(boolean is_server) {
    this.is_serverFlag = is_server;
    Container c = this.getContentPane();

    this.setLocation(10, 10);
    if (is_serverFlag) {
      this.setTitle("服务器端地址配置");
      this.setSize(300, 70);
    }
    else {
      this.setTitle("客户端地址配置");
      this.setSize(300, 100);
    }
    jl_IP = new JLabel("IP:");
    jtf_IP = new JTextField(20);
    jtf_IP.setText("192.168.51.77");
    jp_IP = new JPanel();
    jp_IP.add(jl_IP);
    jp_IP.add(jtf_IP);

    jl_PORT = new JLabel("PORT:");
    jtf_PORT = new JTextField(5);
    jtf_PORT.setText("9999");
    jp_PORT = new JPanel();
    jp_PORT.add(jl_PORT);
    jp_PORT.add(jtf_PORT);

    jb = new JButton("Go");
    jb.addActionListener(new MyActionListener(this));
    jp_PORT.add(jb);
    if (!is_serverFlag) {
      c.setLayout(new GridLayout(2, 1));
    }
    else {
      c.setLayout(new GridLayout(1, 1));
    }
    if (!is_serverFlag) {
      c.add(jp_IP);
    }
    c.add(jp_PORT);
    this.setResizable(false);
    this.setVisible(true);
  }

  class MyActionListener
      implements ActionListener {
    public AddrConfig addrconfig;
    public MyActionListener(AddrConfig add) {
      this.addrconfig = add;
    }

    public void actionPerformed(ActionEvent e) {
      if (e.getSource() == addrconfig.jb) {
        if (addrconfig.is_serverFlag) {
//if (netframe_server == null) {
          netframe_server = new NetFrame(Integer.parseInt(addrconfig.jtf_PORT.
              getText()));
          netframe_server.show();
//}
//netframe_server.show();
        }
        else {
//if (netframe_client == null) {
          netframe_client = new NetFrame(addrconfig.jtf_IP.getText(),
                                         Integer.
                                         parseInt(addrconfig.jtf_PORT.getText()));
          netframe_client.show();
//}
//netframe_client.show();
        }
      }
    }
  }
}

class BabyFrame
    extends JFrame
    implements ActionListener {

  public static final int WIDTH = 300;
  public static final int HEIGHT = 400;
  public JMenuBar menubar;
  public JMenu fileMenu;
  public JMenuItem newSingleGameMenuItem, newLocalMultiGameMenuItem;
  public JMenu newNetMultiGameMenu;
  public JMenuItem newNetMultiGameMenuItem_server,
      newNetMultiGameMenuItem_client;
  public JMenuItem exitMenuItem;
  public JMenuItem pauseGameMenuItem;
  public JMenu optionMenu;

  public JCheckBoxMenuItem Border_Item;
  public JMenu aboutMenu;
  public JMenuItem mailMeMenuItem;
  public JMenuItem aboutMenuItem;

//public BabyPanel panel;
//public BabyDialog panel_Dialog;
  public AboutDialog about_Dialog;
  public JButton jb_server, jb_client;
  public JPanel jp;
  public AddrConfig addrconfig_server = null, addrconfig_client = null;
  public MultiFrame multiframe = null;
  public SingleFrame singleframe = null;

  public BabyFrame() {
    Container contentPane = getContentPane();
//panel_Dialog = new BabyDialog(panel);
//about_Dialog = new AboutDialog(panel);

    setTitle("贪食蛇sss");
    setSize(WIDTH, HEIGHT);
    setResizable(false);
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    setLocation( (int) (screenSize.getWidth() / 2 - WIDTH / 2),
                (int) (screenSize.getHeight() / 2 - HEIGHT / 2));
    menubar = new JMenuBar();
    fileMenu = new JMenu("File");
    fileMenu.setMnemonic('F');

    newSingleGameMenuItem = new JMenuItem("New SingleGame...", 'S');
    newSingleGameMenuItem.addActionListener(this);
    newLocalMultiGameMenuItem = new JMenuItem("new Multi-Local-Game...", 'M');
    newLocalMultiGameMenuItem.addActionListener(this);

    newNetMultiGameMenu = new JMenu("Net MultiGame");
    newNetMultiGameMenuItem_server = new JMenuItem("As Server...", 'S');
    newNetMultiGameMenuItem_server.addActionListener(this);
    newNetMultiGameMenuItem_client = new JMenuItem("As Client...", 'C');
    newNetMultiGameMenuItem_client.addActionListener(this);

    newNetMultiGameMenu.add(newNetMultiGameMenuItem_server);
    newNetMultiGameMenu.add(newNetMultiGameMenuItem_client);

    fileMenu.add(newSingleGameMenuItem);
    fileMenu.add(newLocalMultiGameMenuItem);
    fileMenu.add(newNetMultiGameMenu);

    pauseGameMenuItem = new JMenuItem("Pause", 'P');
    pauseGameMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
//panel.runFlag = !panel.runFlag;
      }
    });

    exitMenuItem = new JMenuItem("Exit", 'X');
    exitMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        System.exit(0);
      }
    });
    fileMenu.add(pauseGameMenuItem);
    fileMenu.add(exitMenuItem);

    optionMenu = new JMenu("Option");
    optionMenu.setMnemonic('O');

    Border_Item = new JCheckBoxMenuItem("Snake-Border");
    Border_Item.addActionListener(this);

    optionMenu.add(Border_Item);

    aboutMenu = new JMenu("About");
    aboutMenu.setMnemonic('A');
    aboutMenuItem = new JMenuItem("About", 'A');
    aboutMenuItem.addActionListener(this);

    aboutMenu.add(aboutMenuItem);
    menubar.add(fileMenu);
    menubar.add(optionMenu);
    menubar.add(aboutMenu);
    this.setJMenuBar(menubar);

  }

  public void actionPerformed(ActionEvent ae) {
    if (ae.getSource() == newNetMultiGameMenuItem_server) {
      if (addrconfig_server == null) {
        addrconfig_server = new AddrConfig(true);
      }
      addrconfig_server.show();
//this.setVisible(false);
    }
    else
    if (ae.getSource() == newNetMultiGameMenuItem_client) {
      if (addrconfig_client == null) {
        addrconfig_client = new AddrConfig(false);
      }
      addrconfig_client.show();
    }

    else
    if (ae.getSource() == newLocalMultiGameMenuItem) {
      if (multiframe == null) {
        multiframe = new MultiFrame();
      }
      multiframe.show();
    }
    else
    if (ae.getSource() == newSingleGameMenuItem) {
      if (singleframe == null) {
        singleframe = new SingleFrame();
        singleframe.show();
      }
      singleframe.show();
    }
  }

}

class NetFrame
    extends JFrame {
  public static final int WIDTH = 700;
  public static final int HEIGHT = 400;
  public BabyFrame babyframe;
  public boolean is_serverFlag;
  public NetMultiBabyPanel panel;
  public String IP;
  public int PORT;

  public JMenuBar menubar;
  public JMenu fileMenu;
  public JMenuItem newGameMenuItem;
  public JMenuItem exitMenuItem;
  public JMenuItem pauseGameMenuItem;

  public NetFrame(String ip, int port) {
    this.is_serverFlag = false;
    this.IP = ip;
    this.PORT = port;
//this.babyframe = babyframe1;
//this.babyframe = babyframe;
//Container c = this.getContentPane();
    panel = new NetMultiBabyPanel(IP, PORT);

    this.setSize(700, 400);
    this.setTitle("贪食蛇======网络版客户端");
    this.setResizable(false);
    panel.thread.start();
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    setLocation( (int) (screenSize.getWidth() / 2 - WIDTH / 2),
                (int) (screenSize.getHeight() / 2 - HEIGHT / 2));

    menubar = new JMenuBar();

    fileMenu = new JMenu("File");
    fileMenu.setMnemonic('F');

    newGameMenuItem = new JMenuItem("New", 'N');
    newGameMenuItem.addActionListener(new MyActionListener(this));
    pauseGameMenuItem = new JMenuItem("Pause", 'P');
    pauseGameMenuItem.addActionListener(new MyActionListener(this));

    exitMenuItem = new JMenuItem("Exit", 'X');
    exitMenuItem.addActionListener(new MyActionListener(this));

    fileMenu.add(newGameMenuItem);
    fileMenu.add(pauseGameMenuItem);
    fileMenu.add(exitMenuItem);
    menubar.add(fileMenu);
    setJMenuBar(menubar);
    Container c = this.getContentPane();
    c.add(panel);

    this.addWindowListener(new WindowAdapter() {
//close window event
      public void windowClosing(WindowEvent event) {
//babyframe.
        setVisible(false);
        try {
          panel.thread.stop();
          panel.socket.close();
        }
        catch (IOException e) {}
      } //end of window event
    }
    );
  }

////////////////////////////////////////////////////////////
  public NetFrame(int port) {
    this.is_serverFlag = true;
    this.PORT = port;
    panel = new NetMultiBabyPanel(PORT);
    this.setSize(700, 400);
    this.setTitle("贪食蛇======网络版服务器端");
    this.setResizable(false);

    panel.thread.start();
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    setLocation( (int) (screenSize.getWidth() / 2 - WIDTH / 2),
                (int) (screenSize.getHeight() / 2 - HEIGHT / 2));

    menubar = new JMenuBar();

    fileMenu = new JMenu("File");
    fileMenu.setMnemonic('F');

    newGameMenuItem = new JMenuItem("New", 'N');
    newGameMenuItem.addActionListener(new MyActionListener(this));
    pauseGameMenuItem = new JMenuItem("Pause", 'P');
    pauseGameMenuItem.addActionListener(new MyActionListener(this));

    exitMenuItem = new JMenuItem("Exit", 'X');
    exitMenuItem.addActionListener(new MyActionListener(this));

    fileMenu.add(newGameMenuItem);
    fileMenu.add(pauseGameMenuItem);
    fileMenu.add(exitMenuItem);
    menubar.add(fileMenu);
    setJMenuBar(menubar);
    Container c = this.getContentPane();
    c.add(panel);

    this.addWindowListener(new WindowAdapter() {
//close window event
      public void windowClosing(WindowEvent event) {
//babyframe.

//babyframe.setVisible(true);
        setVisible(false);
        try {
          panel.thread.stop();
          panel.serversocket.close();
//panel.socket_on_server.close();
          if (! (panel.socket_on_server == null)) {
            panel.socket_on_server.close();

          }
        }
        catch (IOException e) {}
      }

    } //end of window event

    );
  }

  private class MyActionListener
      implements ActionListener {
    public NetFrame netframe;
    public MyActionListener(NetFrame nf) {
      this.netframe = nf;
    }

    public void actionPerformed(ActionEvent event) {
      if (event.getSource() == newGameMenuItem) {
        if (netframe.panel.is_serverFlag) {
          netframe.panel.user1.newGame();
          netframe.panel.out.println(KeyEvent.VK_R);
        }
        else {
          netframe.panel.user2.newGame();
          netframe.panel.out.println(KeyEvent.VK_2);
        }
      }
      else
      if (event.getSource() == pauseGameMenuItem) {
        if (netframe.panel.is_serverFlag) {
          netframe.panel.user1.runFlag = !netframe.panel.user1.runFlag;
          netframe.panel.out.println(KeyEvent.VK_SPACE);
        }
        else {
          netframe.panel.user2.runFlag = !netframe.panel.user2.runFlag;
          netframe.panel.out.println(KeyEvent.VK_1);
        }
      }
      else
      if (event.getSource() == exitMenuItem) {
        netframe.dispose();
      }
    }
  }
}

class SingleFrame
    extends JFrame {
  MultiBabyPanel multibabypanel;
  public static final int WIDTH = 400;
  public static final int HEIGHT = 400;
  public JMenuBar menubar;
  public JMenu fileMenu;
  public JMenuItem newGameMenuItem;
  public JMenuItem exitMenuItem;
  public JMenuItem pauseGameMenuItem;

  public SingleFrame() {

    Container c = this.getContentPane();
    multibabypanel = new MultiBabyPanel(1);

//babyframe.setVisible(false);
//this.setVisible(true);
    this.setSize(330, 400);
    this.setTitle("贪食蛇=======本机单打");
    this.setResizable(false);
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    setLocation( (int) (screenSize.getWidth() / 2 - WIDTH / 2),
                (int) (screenSize.getHeight() / 2 - HEIGHT / 2));

    menubar = new JMenuBar();

    fileMenu = new JMenu("File");
    fileMenu.setMnemonic('F');

    newGameMenuItem = new JMenuItem("New", 'N');
    newGameMenuItem.addActionListener(new MyActionListener(this));
    pauseGameMenuItem = new JMenuItem("Pause", 'P');
    pauseGameMenuItem.addActionListener(new MyActionListener(this));

    exitMenuItem = new JMenuItem("Exit", 'X');
    exitMenuItem.addActionListener(new MyActionListener(this));

    fileMenu.add(newGameMenuItem);
    fileMenu.add(pauseGameMenuItem);
    fileMenu.add(exitMenuItem);
    menubar.add(fileMenu);
    setJMenuBar(menubar);
    c.add(multibabypanel);
  }

  private class MyActionListener
      implements ActionListener {
    public SingleFrame singleframe;
    public MyActionListener(SingleFrame sf) {
      this.singleframe = sf;
    }

    public void actionPerformed(ActionEvent event) {
      if (event.getSource() == newGameMenuItem) {
        singleframe.multibabypanel.user1.newGame();
      }
      else
      if (event.getSource() == pauseGameMenuItem) {
        singleframe.multibabypanel.user1.runFlag = !singleframe.multibabypanel.
            user1.runFlag;
      }
      else
      if (event.getSource() == exitMenuItem) {
        singleframe.dispose();
      }
    }
  }
}

//////////////////////////////////////////////////////////////

class MultiFrame
    extends JFrame {
  MultiBabyPanel multibabypanel;
  public static final int WIDTH = 700;
  public static final int HEIGHT = 400;

  public JMenuBar menubar;
  public JMenu fileMenu;
  public JMenuItem newGameMenuItem;
  public JMenuItem exitMenuItem;
  public JMenuItem pauseGameMenuItem;
  public MultiFrame() {

//Container c = this.getContentPane();
    multibabypanel = new MultiBabyPanel(2);
//c.add(multibabypanel);
//babyframe.setVisible(false);
//this.setVisible(true);
    this.setSize(700, 400);
    this.setTitle("贪食蛇=======本机双打");
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    setLocation( (int) (screenSize.getWidth() / 2 - WIDTH / 2),
                (int) (screenSize.getHeight() / 2 - HEIGHT / 2));
    this.setResizable(false);
    menubar = new JMenuBar();

    fileMenu = new JMenu("File");
    fileMenu.setMnemonic('F');

    newGameMenuItem = new JMenuItem("New", 'N');
    newGameMenuItem.addActionListener(new MyActionListener(this));
    pauseGameMenuItem = new JMenuItem("Pause", 'P');
    pauseGameMenuItem.addActionListener(new MyActionListener(this));

    exitMenuItem = new JMenuItem("Exit", 'X');
    exitMenuItem.addActionListener(new MyActionListener(this));

    fileMenu.add(newGameMenuItem);
    fileMenu.add(pauseGameMenuItem);
    fileMenu.add(exitMenuItem);
    menubar.add(fileMenu);
    setJMenuBar(menubar);
    Container c = this.getContentPane();
    c.add(multibabypanel);
  }

  private class MyActionListener
      implements ActionListener {
    public MultiFrame multiframe;
    public MyActionListener(MultiFrame mf) {
      this.multiframe = mf;
    }

    public void actionPerformed(ActionEvent event) {
      if (event.getSource() == newGameMenuItem) {
        multiframe.multibabypanel.user1.newGame();
        multiframe.multibabypanel.user2.newGame();
      }
      else
      if (event.getSource() == pauseGameMenuItem) {
        multiframe.multibabypanel.user1.runFlag = !multiframe.multibabypanel.
            user1.runFlag;
        multiframe.multibabypanel.user2.runFlag = !multiframe.multibabypanel.
            user2.runFlag;
      }
      else
      if (event.getSource() == exitMenuItem) {
        multiframe.dispose();
      }
    }
  }
}

class MultiBabyPanel
    extends JPanel
    implements Runnable {

  User user1, user2;
  public Thread thread;
  public int userNum;
  public Random random;
  public int color_choose = 0;

  public MultiBabyPanel(int userNum) {
    random = new Random(100);
    this.userNum = userNum;
    user1 = new User(KeyEvent.VK_UP, KeyEvent.VK_DOWN, KeyEvent.VK_LEFT,
                     KeyEvent.VK_RIGHT, KeyEvent.VK_SPACE, KeyEvent.VK_R, 280,
                     280, 0, 0);
    myKeyListenerUser1 keyListener_user1 = new myKeyListenerUser1();
    addKeyListener(keyListener_user1);
    if (userNum == 2) {
      System.out.println("User2 inited....");
      user2 = new User(KeyEvent.VK_W, KeyEvent.VK_S, KeyEvent.VK_A,
                       KeyEvent.VK_D, KeyEvent.VK_1, KeyEvent.VK_2, 640, 280,
                       360, 0);
      myKeyListenerUser2 keyListener_user2 = new myKeyListenerUser2();
      addKeyListener(keyListener_user2);
    }

    thread = new Thread(this);
    thread.start();

  }

  public boolean isFocusTraversable() {
    return true;
  }

  public void run() {
    while (true) {
      user1.goOne();
      if (userNum == 2) {
        user2.goOne();
      }
      try {
        thread.sleep(5);
      }
      catch (InterruptedException e) {}
      repaint();
    }
  }

  private class myKeyListenerUser1
      implements KeyListener {
    public void myKeyListenr() {}

    public void keyPressed(KeyEvent ke) {
      user1.doMessage(ke.getKeyCode());
    }

    public void keyReleased(KeyEvent ke) {}

    public void keyTyped(KeyEvent ke) {}
  }

///////////////keyListener for user2////////////////////////////////
  private class myKeyListenerUser2
      implements KeyListener {
    public void myKeyListenr() {}

    public void keyPressed(KeyEvent ke) {
      user2.doMessage(ke.getKeyCode());
    }

    public void keyReleased(KeyEvent ke) {}

    public void keyTyped(KeyEvent ke) {}
  }

  public void paintComponent(Graphics g) {
    super.paintComponent(g);

    g.setColor(Color.black);

    if (userNum == 2) {
      g.fill3DRect(user2.panelx + 10, user2.panely + 10, 300, 300, false);
      g.setColor(Color.white);
      g.fill3DRect(user2.panelx + 20, user2.panely + 20, 280, 280, true);
      g.setColor(Color.BLACK);
      g.drawRect(user2.panelx + 10, user2.panely + 320, 70, 19);
      g.fillRect(user2.panelx + 12, user2.panely + 322, 67, 16);
      g.setColor(Color.WHITE);
      g.drawString("Score : " + (user2.babyCount - 6), user2.panelx + 17,
                   user2.panely + 334);
      g.setColor(Color.BLACK);
      g.drawRect(user2.panelx + 241, user2.panely + 320, 70, 19);
      g.fillRect(user2.panelx + 243, user2.panely + 322, 67, 16);
      g.setColor(Color.WHITE);
      g.drawString("Level : " + (10 - user2.sleepTime), user2.panelx + 252,
                   user2.panely + 334);
    }

    g.setColor(Color.black);
    g.fill3DRect(user1.panelx + 10, user1.panely + 10, 300, 300, false);
    g.setColor(Color.white);
    g.fill3DRect(user1.panelx + 20, user1.panely + 20, 280, 280, true);
    g.setColor(Color.BLACK);
    g.drawRect(user1.panelx + 10, user1.panely + 320, 70, 19);
    g.fillRect(user1.panelx + 12, user1.panely + 322, 67, 16);
    g.setColor(Color.WHITE);
    g.drawString("Score : " + (user1.babyCount - 6), user1.panelx + 17,
                 user1.panely + 334);
    g.setColor(Color.BLACK);
    g.drawRect(user1.panelx + 241, user1.panely + 320, 70, 19);
    g.fillRect(user1.panelx + 243, user1.panely + 322, 67, 16);
    g.setColor(Color.WHITE);
    g.drawString("Level : " + (10 - user1.sleepTime), user1.panelx + 252,
                 user1.panely + 334);

///////////////////////////if user2 exist then draw user2//////////////////
    if (userNum == 2) {
//显示图像
      for (int i = 0; i < user2.Baby.size(); i++) {

//得到图像位置
        int x = (int) ( (Point) user2.Baby.get(i)).getX();
        int y = (int) ( (Point) user2.Baby.get(i)).getY();
//g.drawRect(x+1,y +1,18,18);
        g.setColor( (Color) user2.BabyColor.get(i));
        g.fill3DRect(x + 1, y + 1, 18, 18, true);
      }
      g.setColor(Color.MAGENTA);
      g.fill3DRect(user2.posx + 1, user2.posy + 1, 18, 18, true);
      g.setColor(Color.red);
      if ( (user2.runFlag == false) & (user2.gameFlag == true)) {
        g.drawString("PAUSE...", user2.panelx + 130, user2.panely + 130);
      }
      if (user2.gameFlag == false) {
        g.drawString("Game Over!", user2.panelx + 130, user2.panely + 130);
      }
    }

//////////////////////draw user1/////////////////////////////////

//显示图像
    for (int i = 0; i < user1.Baby.size(); i++) {

//得到图像位置
      int x = (int) ( (Point) user1.Baby.get(i)).getX();
      int y = (int) ( (Point) user1.Baby.get(i)).getY();
//g.drawRect(x+1,y +1,18,18);
      g.setColor( (Color) user1.BabyColor.get(i));
      g.fill3DRect(x + 1, y + 1, 18, 18, true);
    }
    g.setColor(Color.MAGENTA);
    g.fill3DRect(user1.posx + 1, user1.posy + 1, 18, 18, true);
    g.setColor(Color.black);
    if ( (user1.runFlag == false) & (user1.gameFlag == true)) {
      g.drawString("PAUSE...", user1.panelx + 130, user1.panely + 130);
    }
    if (user1.gameFlag == false) {
      g.drawString("Game Over!", user1.panelx + 130, user1.panely + 130);
    }
  }
}

//////////////////////////////////////////////////////////////

class NetMultiBabyPanel
    extends JPanel
    implements Runnable {

  public User user1, user2;
  public Thread thread;
  boolean is_serverFlag;
  public BufferedReader in;
  public PrintWriter out;
  public String message_temp;
  public int message;
  public ServerSocket serversocket;
  public Socket socket, socket_on_server;
  public InetAddress a;
  public int PORT = 9999;
  public String IP;
  public boolean isConected;

  public NetMultiBabyPanel(String ip, int port) {
    this.is_serverFlag = false;
    isConected = false;
    this.IP = ip;
    this.PORT = port;

    user1 = new User(KeyEvent.VK_UP, KeyEvent.VK_DOWN, KeyEvent.VK_LEFT,
                     KeyEvent.VK_RIGHT, KeyEvent.VK_SPACE, KeyEvent.VK_R, 280,
                     280, 0, 0);
    user2 = new User(KeyEvent.VK_W, KeyEvent.VK_S, KeyEvent.VK_A, KeyEvent.VK_D,
                     KeyEvent.VK_1, KeyEvent.VK_2, 640, 280, 360, 0);

    myKeyListenerUser1 keyListenerUser1 = new myKeyListenerUser1();
    myKeyListenerUser2 keyListenerUser2 = new myKeyListenerUser2();

    try {
      InetAddress a = InetAddress.getByName(IP);
      socket = new Socket(a, PORT);
      in =
          new BufferedReader(new InputStreamReader(socket.getInputStream()));
      out =
          new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.
          getOutputStream())));
    }
    catch (IOException e) {}

    addKeyListener(keyListenerUser2);
    System.out.println("keyListenerUser2");

    System.out.println("addListener");
    thread = new Thread(this);
  }

///////////////////////////////////////////////////////////////////////////////

  public NetMultiBabyPanel(int port) {
    this.PORT = port;
    this.is_serverFlag = true;
    isConected = false;

    user1 = new User(KeyEvent.VK_UP, KeyEvent.VK_DOWN, KeyEvent.VK_LEFT,
                     KeyEvent.VK_RIGHT, KeyEvent.VK_SPACE, KeyEvent.VK_R, 280,
                     280, 0, 0);
    user2 = new User(KeyEvent.VK_W, KeyEvent.VK_S, KeyEvent.VK_A, KeyEvent.VK_D,
                     KeyEvent.VK_1, KeyEvent.VK_2, 640, 280, 360, 0);

    myKeyListenerUser1 keyListenerUser1 = new myKeyListenerUser1();
    myKeyListenerUser2 keyListenerUser2 = new myKeyListenerUser2();

    try {
      serversocket = new ServerSocket(PORT);
    }
    catch (IOException e) {}
    System.out.println("Server inited!");
    new MyThread().start();

    addKeyListener(keyListenerUser1);
    System.out.println("keyListenerUser1");
    thread = new Thread(this);
  }

  class MyThread
      extends Thread {
    MyThread() {
    }

    public void run() {

      try {
        socket_on_server = serversocket.accept();
        in = new BufferedReader(
            new InputStreamReader(
            socket_on_server.getInputStream()));
        System.out.println("In inited");
        out = new PrintWriter(
            new BufferedWriter(
            new OutputStreamWriter(
            socket_on_server.getOutputStream())));
        isConected = true;
        System.out.println("Out inited");
      }
      catch (IOException e) {}
    }

  }

  public boolean isFocusTraversable() {
    return true;
  }

  public void run() {
    while (true) {
      if (is_serverFlag) {
        if (isConected) {
          try {
            user1.goOne();
            out.println("Go");
            out.flush();
            message_temp = in.readLine();
            if (message_temp.startsWith("Go")) {
              user2.goOne();
            }
            else {
              message = Integer.parseInt(message_temp);
              user2.doMessage(message);
            }
          }
          catch (IOException e) {}
        }
      }
      else {

        try {
          out.println("Go");
          out.flush();
          user2.goOne();

//System.out.println("Listening....");
          message_temp = in.readLine();

          if (message_temp.startsWith("Go")) {
            user1.goOne();
          }
          else {
            message = Integer.parseInt(message_temp);
            user1.doMessage(message);
          }
        }
        catch (IOException e) {}
      }

      repaint();
      try {
        thread.sleep(5);
      }
      catch (InterruptedException e) {

      }

    }
  }

//////////////////////keyListener for user1////////////////////////////////
  private class myKeyListenerUser1
      implements KeyListener {
    public void myKeyListenrUser1() {}

    public void keyPressed(KeyEvent ke) {
      user1.doMessage(ke.getKeyCode());
      out.println(ke.getKeyCode());
      out.flush();
    }

    public void keyReleased(KeyEvent ke) {}

    public void keyTyped(KeyEvent ke) {}
  }

//////////////////////keyListener for user2////////////////////////////////
  private class myKeyListenerUser2
      implements KeyListener {
    public void myKeyListenrUser2() {}

    public void keyPressed(KeyEvent ke) {
      user2.doMessage(ke.getKeyCode());
      out.println(ke.getKeyCode());
      out.flush();
    }

    public void keyReleased(KeyEvent ke) {}

    public void keyTyped(KeyEvent ke) {}
  }

//////////////////////override the paint method////////////////////////////
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
//System.out.println("paintComponent.....");
    g.setColor(Color.black);
    g.fill3DRect(user2.panelx + 10, user2.panely + 10, 300, 300, false);
    g.setColor(Color.white);
    g.fill3DRect(user2.panelx + 20, user2.panely + 20, 280, 280, true);
    g.setColor(Color.BLACK);
    g.drawRect(user2.panelx + 10, user2.panely + 320, 70, 19);
    g.fillRect(user2.panelx + 12, user2.panely + 322, 67, 16);
    g.setColor(Color.WHITE);
    g.drawString("Score : " + (user2.babyCount - 6), user2.panelx + 17,
                 user2.panely + 334);
    g.setColor(Color.BLACK);
    g.drawRect(user2.panelx + 241, user2.panely + 320, 70, 19);
    g.fillRect(user2.panelx + 243, user2.panely + 322, 67, 16);
    g.setColor(Color.WHITE);
    g.drawString("Level : " + (10 - user2.sleepTime), user2.panelx + 252,
                 user2.panely + 334);

    g.setColor(Color.black);
    g.fillRect(user1.panelx + 10, user1.panely + 10, 300, 300);
    g.setColor(Color.white);
    g.fillRect(user1.panelx + 20, user1.panely + 20, 280, 280);
    g.setColor(Color.BLACK);
    g.drawRect(user1.panelx + 10, user1.panely + 320, 70, 19);
    g.fillRect(user1.panelx + 12, user1.panely + 322, 67, 16);
    g.setColor(Color.WHITE);
    g.drawString("Score : " + (user1.babyCount - 6), user1.panelx + 17,
                 user1.panely + 334);
    g.setColor(Color.BLACK);
    g.drawRect(user1.panelx + 241, user1.panely + 320, 70, 19);
    g.fillRect(user1.panelx + 243, user1.panely + 322, 67, 16);
    g.setColor(Color.WHITE);
    g.drawString("Level : " + (10 - user1.sleepTime), user1.panelx + 252,
                 user1.panely + 334);

    g.setColor(Color.blue);

//显示图像
    for (int i = 0; i < user2.Baby.size(); i++) {

//得到图像位置
      int x = (int) ( (Point) user2.Baby.get(i)).getX();
      int y = (int) ( (Point) user2.Baby.get(i)).getY();
//g.drawRect(x+1,y +1,18,18);
      g.setColor( (Color) user2.BabyColor.get(i));
      g.fill3DRect(x + 1, y + 1, 18, 18, true);
    }
    g.setColor(Color.MAGENTA);
    g.fill3DRect(user2.posx + 1, user2.posy + 1, 18, 18, true);
    g.setColor(Color.red);
    if ( (user2.runFlag == false) & (user2.gameFlag == true)) {
      g.drawString("PAUSE...", user2.panelx + 130, user2.panely + 130);
    }
    if (user2.gameFlag == false) {
      g.drawString("Game Over!", user2.panelx + 130, user2.panely + 130);

//////////////////////draw user1/////////////////////////////////

//显示图像
    }
    for (int i = 0; i < user1.Baby.size(); i++) {

//得到图像位置
      int x = (int) ( (Point) user1.Baby.get(i)).getX();
      int y = (int) ( (Point) user1.Baby.get(i)).getY();
//g.drawRect(x+1,y +1,18,18);
      g.setColor( (Color) user1.BabyColor.get(i));
      g.fill3DRect(x + 1, y + 1, 18, 18, true);
    }
    g.setColor(Color.green);
    g.fill3DRect(user1.posx + 1, user1.posy + 1, 18, 18, true);
    g.setColor(Color.black);
    if ( (user1.runFlag == false) & (user1.gameFlag == true)) {
      g.drawString("PAUSE...", user1.panelx + 130, user1.panely + 130);
    }
    if (user1.gameFlag == false) {
      g.drawString("Game Over!", user1.panelx + 130, user1.panely + 130);

    }

  }

}

class User {

//public int goOne;
  public int startx, starty, panelx, panely;
  public int key_up, key_down, key_left, key_right, key_pause, key_reset;

//public Thread thread;
  public ArrayList Baby, BabyDir, BabyRectangle, BabyColor;
  public ArrayList Change, ChangeDir, ChangeCurrent, ChangeTotal;
  public int pic_choose_snake = 2, pic_choose_food = 5;
  public int imageWidth, imageHeight;

  public int x, y, posx, posy, newx, newy, currentx, currenty, steps, sleepTime;
  public Point pt, ptadd, ptlast, ptemp;

  public int dircount = 4, babyCount, turnCount;
  public Random random, random_color;

  public boolean eated, runFlag, gameFlag, drawFlag_snake, drawFlag_food,
      borderFlag, isSuspend;
  public Rectangle headRect, foodRect, rect1, rect2, rectTemp;

  public Color[] color = {
      Color.red, Color.green, new Color(3, 45, 209), new Color(223, 100, 26),
      new Color(200, 46, 13), new Color(190, 23, 200), new Color(224, 171, 12),
      new Color(120, 33, 180), new Color(69, 41, 52)};

  public int color_choose = 0;

  public User(int key_up, int key_down, int key_left, int key_right,
              int key_pause, int key_reset, int startx, int starty, int panelx,
              int panely) {

    this.key_up = key_up;
    this.key_down = key_down;
    this.key_left = key_left;
    this.key_right = key_right;
    this.key_pause = key_pause;
    this.key_reset = key_reset;
    this.startx = startx;
    this.starty = starty;
    this.panelx = panelx;
    this.panely = panely;

    isSuspend = false;
    sleepTime = 5;
    babyCount = 6;
    turnCount = 0;
    imageWidth = 20;
    steps = (babyCount - 1) * imageWidth + 1;
    random = new Random(400);
    random_color = new Random(100);
//pup = new Point(100,100);
    Change = new ArrayList();
    ChangeDir = new ArrayList();
    ChangeCurrent = new ArrayList();
    ChangeTotal = new ArrayList();
    Baby = new ArrayList();
    BabyDir = new ArrayList();
    BabyRectangle = new ArrayList();
    BabyColor = new ArrayList();
    eated = true;
    runFlag = true;
    gameFlag = true;
    drawFlag_snake = true;
    drawFlag_food = true;
    borderFlag = true;
    Toolkit kit = Toolkit.getDefaultToolkit();

    for (int i = 0; i < 6; i++) {
      color_choose = random_color.nextInt(9);
      pt = new Point(startx, starty);
      startx = startx + imageWidth;
      add(pt, 3);
      BabyColor.add(color[color_choose]);
      BabyRectangle.add(pt);
    }
  }

  public void add(Point pt, int dir) {
    Baby.add(pt);
    BabyDir.add(new Integer(dir));
    ptlast = pt;
  }

  public void addNode() {

    int size = Baby.size();

    int x = (int) ( (Point) Baby.get(size - 1)).getX();
    int y = (int) ( (Point) Baby.get(size - 1)).getY();
    int newDir = Integer.parseInt( (BabyDir.get(size - 1).toString()));
    switch (newDir) {
      case 0:
        y = y + imageWidth;
        break;
      case 1:
        x = x - imageWidth;
        break;
      case 2:
        y = y - imageWidth;
        break;
      case 3:
        x = x + imageWidth;
        break;
    }

    Point newPoint = new Point(x, y);
    BabyRectangle.add(newPoint);
    add(newPoint, newDir);
    color_choose = random_color.nextInt(9);
    BabyColor.add(color[color_choose]);
    ptlast = newPoint;
    babyCount++;
    steps = (babyCount - 1) * imageWidth + 1;
    if (!ChangeTotal.isEmpty()) {
      for (int k = 0; k < ChangeTotal.size(); k++) {
        int tempadd = Integer.parseInt(ChangeTotal.get(k).toString()) +
            imageWidth;
        ChangeTotal.set(k, new Integer(tempadd));
      }
    }
  }

  public void checkGame() {
    if ( ( ( (Point) Baby.get(0)).getX() > panelx + 300)
        || ( ( (Point) Baby.get(0)).getY() > panely + 300)
        || ( ( (Point) Baby.get(0)).getX() < panelx + 10)
        || ( ( (Point) Baby.get(0)).getY() < panely + 10)) {
      gameFlag = false;

    }
    int rectTempx = (int) ( (Point) BabyRectangle.get(0)).getX();
    int rectTempy = (int) ( (Point) BabyRectangle.get(0)).getY();
    rect1 = new Rectangle(rectTempx, rectTempy, imageWidth - 5, imageWidth - 5);
    for (int rectNum = 3; rectNum < BabyRectangle.size(); rectNum++) {
      int rectTempxx = (int) ( (Point) BabyRectangle.get(rectNum)).getX();
      int rectTempyy = (int) ( (Point) BabyRectangle.get(rectNum)).getY();
      rect2 = new Rectangle(rectTempxx, rectTempyy, imageWidth - 5,
                            imageWidth - 5);

      if (rect1.intersects(rect2)) {
        gameFlag = false;
        return;
      }
    }
  }

  public void cut() {
    ChangeCurrent.remove(0);
    ChangeTotal.remove(0);
    Change.remove(0);
    ChangeDir.remove(0);
  }

  public void checkEat() {
    eated = false;
    if (headRect.intersects(foodRect)) {
      eated = true;
    }
  }

  public void checkDir() {
    for (int j = 0; j < Change.size(); j++) {
      for (int i = 1; i < Baby.size(); i++) {
        if (Baby.get(i).equals( (Point) (Change.get(j)))) {
          BabyDir.set(i, ChangeDir.get(j));
        }
      }
    }
  }

  public void food() {
    if (eated == true) {
      posx = panelx + 20 + random.nextInt(260);
      posy = panely + 20 + random.nextInt(260);
      foodRect = new Rectangle(posx, posy, 15, 15);
    }
  }

  public void addChangeCurrent() {
    for (int i = 0; i < ChangeCurrent.size(); i++) {
      int ttt = Integer.parseInt( (ChangeCurrent.get(i).toString())) + 1;
      ChangeCurrent.set(i, new Integer(ttt));
    }
  }

  public void checkAddChangeCurrent() {
    if (!ChangeCurrent.isEmpty()) {
      if (!ChangeTotal.isEmpty()) {
        int tempCurrent = Integer.parseInt(ChangeCurrent.get(0).toString());
        int tempTotal = Integer.parseInt(ChangeTotal.get(0).toString());
        if (tempCurrent == tempTotal) {
          cut();
        }
        else if (tempCurrent > tempTotal) {
          System.out.println("Error");
          runFlag = false;
        }
      }
    }
  }

  public void go() {
//System.out.println("go");
    steps = (babyCount - 1) * imageWidth + 1;
    newx = (int) ( (Point) Baby.get(0)).getX();
    newy = (int) ( (Point) Baby.get(0)).getY();
    headRect = new Rectangle(newx, newy, 15, 15);

    for (int i = 0; i < Baby.size(); i++) {
      switch (Integer.parseInt( (BabyDir.get(i).toString()))) {
        case 0: //向上
          newx = (int) ( (Point) Baby.get(i)).getX();
          newy = (int) ( (Point) Baby.get(i)).getY() - 1;
          ptadd = new Point(newx, newy);
          Baby.set(i, ptadd);
          BabyRectangle.set(i, ptadd);
          break;

        case 1: //向右
          newx = (int) ( (Point) Baby.get(i)).getX() + 1;
          newy = (int) ( (Point) Baby.get(i)).getY();
          ptadd = new Point(newx, newy);
          Baby.set(i, ptadd);
          BabyRectangle.set(i, ptadd);
          break;

        case 2: //向下
          newx = (int) ( (Point) Baby.get(i)).getX();
          newy = (int) ( (Point) Baby.get(i)).getY() + 1;
          ptadd = new Point(newx, newy);
          Baby.set(i, ptadd);
          BabyRectangle.set(i, ptadd);
          break;

        case 3: //向左
          newx = (int) ( (Point) Baby.get(i)).getX() - 1;
          newy = (int) ( (Point) Baby.get(i)).getY();
          ptadd = new Point(newx, newy);
          Baby.set(i, ptadd);
          BabyRectangle.set(i, ptadd);
          break;
      }
    }
  }

  void doMessage(int message) {
    {
      if (message == key_up) {
        if (Integer.parseInt( (BabyDir.get(0).toString())) != 0) {
          if (Integer.parseInt( (BabyDir.get(0).toString())) != 2) {
            BabyDir.set(0, new Integer(0));
            ptemp = (Point) Baby.get(0);
            Change.add(ptemp);
            ChangeDir.add(new Integer(0));
            ChangeCurrent.add(new Integer(0));
            ChangeTotal.add(new Integer(steps));
            System.out.println("up");
          }
        }
      }

      else
      if (message == key_right) {
        if (Integer.parseInt( (BabyDir.get(0).toString())) != 1) {
          if (Integer.parseInt( (BabyDir.get(0).toString())) != 3) {
            BabyDir.set(0, new Integer(1));
            ptemp = (Point) Baby.get(0);
            Change.add(ptemp);
            ChangeDir.add(new Integer(1));
            ChangeCurrent.add(new Integer(0));
            ChangeTotal.add(new Integer(steps));
            System.out.println("right");
          }
        }
      }

      else
      if (message == key_down) {
        if (Integer.parseInt( (BabyDir.get(0).toString())) != 2) {
          if (Integer.parseInt( (BabyDir.get(0).toString())) != 0) {
            BabyDir.set(0, new Integer(2));
            ptemp = (Point) Baby.get(0);
            Change.add(ptemp);
            ChangeDir.add(new Integer(2));
            ChangeCurrent.add(new Integer(0));
            ChangeTotal.add(new Integer(steps));
            System.out.println("down");

          }
        }
      }

      else

      if (message == key_left) {
        if (Integer.parseInt( (BabyDir.get(0).toString())) != 3) {
          if (Integer.parseInt( (BabyDir.get(0).toString())) != 1) {
            BabyDir.set(0, new Integer(3));
            ptemp = (Point) Baby.get(0);
            Change.add(ptemp);
            ChangeDir.add(new Integer(3));
            ChangeCurrent.add(new Integer(0));
            ChangeTotal.add(new Integer(steps));
            System.out.println("left");
          }
        }
      }

      /*else if (ke.getKeyChar() == ke.VK_1) {
       if (sleepTime > 1) sleepTime--;
       }

       else if (ke.getKeyChar() == ke.VK_2) sleepTime++;
       */

      else
      if (message == key_pause) {
        if (runFlag) {
          runFlag = !runFlag;
        }
        else {
          runFlag = !runFlag;
        }
      }

      else
      if (message == key_reset) {
        newGame();
      }
    }
  }

  public void goOne() {
    if (runFlag == true) {
      if (gameFlag == true) {
        food();
        checkGame();
        checkDir();
        go();
        addChangeCurrent();
        checkAddChangeCurrent();
        checkEat();
        if (eated == true) {
          addNode();
        }
      }
    }
  }

  public void newGame() {

    sleepTime = 5;
    x = startx;
    y = starty;
    babyCount = 6;
    while (!Baby.isEmpty()) {
      Baby.remove(0);
    }
    while (!BabyDir.isEmpty()) {
      BabyDir.remove(0);
    }
    while (!BabyRectangle.isEmpty()) {
      BabyRectangle.remove(0);

    }

    while (!Change.isEmpty()) {
      Change.remove(0);
    }
    while (!ChangeDir.isEmpty()) {
      ChangeDir.remove(0);
    }
    while (!ChangeCurrent.isEmpty()) {
      ChangeCurrent.remove(0);
    }
    while (!ChangeTotal.isEmpty()) {
      ChangeTotal.remove(0);

    }
    for (int j = 0; j < 6; j++) {
      pt = new Point(x, y);
      x = x + imageWidth;
      add(pt, 3);
      BabyRectangle.add(pt);
      eated = true;
      gameFlag = true;
      runFlag = true;
    }
  }
}

class AboutDialog
    extends JPanel {
  private int WIDTH = 310, HEIGHT = 200;

//public BabyPanel babyPanel;
  public JLabel jl_auther, jl_date, jl_company, jl_qq, jl_email;
  public JButton jb_ok;
  private JDialog dialog;
  public JPanel jp1, jp2;
  public Border border;
  public AboutDialog() {
//this.babyPanel = babypanel;
    setSize(WIDTH, HEIGHT);
    setLayout(new BorderLayout());
    jp1 = new JPanel();

    jp2 = new JPanel();
    jp1.setLayout(new GridLayout(5, 1, 10, 10));
    border = BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
                                              "Info");
    jp1.setBorder(border);
    jl_auther = new JLabel("Auther: 张恩来");
    jl_date = new JLabel("Date: 2004-11-3");
    jl_company = new JLabel("Company: 山东济南中创软件");
    jl_qq = new JLabel("QQ: 36798636");
    jl_email = new JLabel("E-Mail: zhang_elai@cvicse.com");
    jb_ok = new JButton("OK");
    jb_ok.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent ae) {
        setRunFlag(true);
        dialog.setVisible(false);
      }
    });
    jp1.add(jl_auther);
    jp1.add(jl_date);
    jp1.add(jl_company);
    jp1.add(jl_qq);
    jp1.add(jl_email);

    jp2.add(jb_ok);

    add(jp1, BorderLayout.NORTH);
    add(jp2, BorderLayout.SOUTH);
  }

  public void setRunFlag(boolean flag) {
//babyPanel.user2.runFlag = flag;
  }

  public void showDialog(Component parent, String title) {

    JFrame owner = null;
    if (parent instanceof JFrame) {
      owner = (JFrame) parent;

    }
    if (dialog == null || dialog.getOwner() != owner) {
      owner = null;
      dialog = new JDialog(owner, false);
      dialog.getContentPane().add(this);
      dialog.pack();
    }

    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    dialog.setLocation( (int) (screenSize.getWidth() / 2 - WIDTH / 2),
                       (int) (screenSize.getHeight() / 2 - HEIGHT / 2));

    dialog.setTitle(title);
    dialog.show();

  }
}