2015-11-22 40 views
0

我一直在尝试制作双人多米诺骨牌游戏。现在,我希望玩家1的动作能够在玩家2的屏幕上模拟出来,仅此而已。如果我启动播放器1的屏幕,并移动一些多米诺骨牌,当我启动播放器2的屏幕时,这些变化就会出现。但从此以后的任何变动都不会改变。这里有什么问题?ObjectInputStream不能读取多于一次

public class Server { 

    private static ObjectOutputStream output; 
    private static ObjectInputStream input; 
    private static ServerSocket server; 
    private static Socket connection; 
    private static Player1 p1Game; 
    private static final int port = 12345; 

    public static void main(String[] args){ 
     p1Game = new Player1(); 
     Thread p1GameThread = new Thread(p1Game); 
     p1GameThread.run(); 
     startServer(); 
    } 

    private static void startServer() { 
     p1Game.setStatusMessage("Starting server..."); 
     try{ 
      server = new ServerSocket(port, 100); 
      p1Game.setStatusMessage("Awaiting connection from player 2..."); 
      connection = server.accept(); 
      output = new ObjectOutputStream(connection.getOutputStream()); 
      output.flush(); 
      p1Game.setStatusMessage(""); 
      while(true){ 
       ArrayList <CDomino> sendDominoes = p1Game.getP1Dominoes(); 
       System.out.println("N" + sendDominoes.get(0).getX()); 
       output.writeObject(sendDominoes); 
       output.flush(); 
       Thread.sleep(1000); 

       } 
     } catch (Exception e) {e.printStackTrace();} 
    } 
} 

public class Client { 

    private static ObjectOutputStream output; 
    private static ObjectInputStream input; 
    private static Socket client; 
    private static Player2 p2Game; 
    private static final String serverAddress = "127.0.0.1"; 
    private static final int serverPort = 12345; 

    public static void main(String[] args){ 
     p2Game = new Player2(); 
     Thread p2GameThread = new Thread(p2Game); 
     p2GameThread.run(); 
     connect(); 
    } 

    private static void connect() { 
     p2Game.setStatusMessage("Attempting to connect to " + serverAddress + " on port " + serverPort + "..."); 
     try{ 
      client = new Socket(InetAddress.getByName(serverAddress), serverPort); 
      input = new ObjectInputStream(client.getInputStream()); 
      p2Game.setStatusMessage(""); 
      while (true) 
       p2Game.setP1Dominoes((ArrayList<CDomino>) input.readObject()); 
     } catch (Exception e) {e.printStackTrace();} 
    } 
} 

public class CDomino implements Serializable{ 
    private static final long serialVersionUID = 345L; 
    private int xC; 
    private int yC; 
    private int rotation; 

    private Color playerColorDark; 
    private Color playerColorLight; 
    private int player; 
    private int topSpots; 
    private int bottomSpots; 

    private final int[][] spotMatrix = { 
       { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 
       { 0, 0, 0, 0, 1, 0, 0, 0, 0 }, 
       { 1, 0, 0, 0, 0, 0, 0, 0, 1 }, 
       { 1, 0, 0, 0, 1, 0, 0, 0, 1 }, 
       { 1, 0, 1, 0, 0, 0, 1, 0, 1 }, 
       { 1, 0, 1, 0, 1, 0, 1, 0, 1 }, 
       { 1, 0, 1, 1, 0, 1, 1, 0, 1 } 
       }; 

    private final int[][] topGridMatrix = { 
      {-12, -30}, {-2, -30}, {8, -30}, 
      {-12, -20}, {-2, -20}, {8, -20}, 
      {-12, -10}, {-2, -10}, {8, -10} 
    }; 

    private final int[][] bottomGridMatrix = { 
      {-12, 5}, {-2, 5}, {8, 5}, 
      {-12, 15}, {-2, 15}, {8, 15}, 
      {-12, 25}, {-2, 25}, {8, 25}, 
    }; 

    public CDomino(int x, int y, int angle, int color){ 
     xC = x; 
     yC = y; 
     rotation = angle; 
     topSpots = new Random().nextInt(7); 
     bottomSpots = new Random().nextInt(7); 

     if (color == 2){ 
      playerColorLight = new Color(60, 180, 60); 
      playerColorDark = new Color(0, 100, 0); 
     } 
     else{ 
      playerColorLight = new Color(120, 120, 255); 
      playerColorDark = new Color(0, 0, 200); 
     } 
    } 

    public boolean isInside(int x, int y){ 
     if (rotation == 0 | rotation == 180) return (x > xC-15) && (x < xC+15) && (y > yC-30) && (y < yC+30); 
     else return (x > xC-30) && (x < xC+30) && (y > yC-15) && (y < yC+15); 
    } 

    public int getX(){return xC;} 
    public int getY(){return yC;} 
    public void setPosition(int x, int y){ 
     xC = x; 
     yC = y; 
    } 

    public void rotate(){ 
     if (rotation == 270) rotation = 0; 
     else rotation += 90; 
    } 

    //dimensions are 36x71px 
    public void draw(Graphics g, int viewingPlayer){ 

     g.setColor(Color.WHITE); 
     if (rotation == 0 || rotation == 180){ 
      g.fillRect(xC-18, yC-36, 36, 71); 
      g.setColor(playerColorDark); 
      g.drawRoundRect(xC-18, yC-36, 36, 71, 5, 5); 
      g.setColor(playerColorLight); 
      g.drawRoundRect(xC-19, yC-37, 38, 73, 5, 5); 
      g.setColor(Color.GRAY); 
      g.drawLine(xC-13, yC, xC+14, yC); 
     } 
     else { 
      g.fillRect(xC-36, yC-18, 71, 36); 
      g.setColor(playerColorDark); 
      g.drawRoundRect(xC-36, yC-18, 71, 36, 5, 5); 
      g.setColor(playerColorLight); 
      g.drawRoundRect(xC-37, yC-19, 73, 38, 5, 5); 
      g.setColor(Color.GRAY); 
      g.drawLine(xC, yC-13, xC, yC+14); 
     } 

     g.setColor(Color.RED); 
     if (isInOpponentHomeArea(yC, viewingPlayer)) return; 
     for (int i = 0; i < 9; i++){ 
      if (spotMatrix[topSpots][i] == 1){ 
       if (rotation == 0) 
        g.fillOval(xC+topGridMatrix[i][0]-1, yC+topGridMatrix[i][1]-1, 7, 7); 
       else if (rotation == 90) 
        g.fillOval(xC-topGridMatrix[i][1]-7, yC+topGridMatrix[i][0]-1, 7, 7); 
       else if (rotation == 180) 
        g.fillOval(xC-topGridMatrix[i][0]-6, yC-topGridMatrix[i][1]-6, 7, 7); 
       else if (rotation == 270) 
        g.fillOval(xC+topGridMatrix[i][1]-1, yC-topGridMatrix[i][0]-7, 7, 7); 
      } 
     } 

     for (int i = 0; i < 9; i++){ 
      if (spotMatrix[bottomSpots][i] == 1){ 
       if (rotation == 0) 
        g.fillOval(xC+bottomGridMatrix[i][0]-1, yC+bottomGridMatrix[i][1]-1, 7, 7); 
       else if (rotation == 90) 
        g.fillOval(xC-bottomGridMatrix[i][1]-7, yC+bottomGridMatrix[i][0]-1, 7, 7); 
       else if (rotation == 180) 
        g.fillOval(xC-bottomGridMatrix[i][0]-6, yC-bottomGridMatrix[i][1]-6, 7, 7); 
       else if (rotation == 270) 
        g.fillOval(xC+bottomGridMatrix[i][1]-1, yC-bottomGridMatrix[i][0]-7, 7, 7); 
      } 
     } 
    } 

    private boolean isInOpponentHomeArea(int y, int player){ 
     if (player == 1) return (y < 125); 
     else return (y > 651); 
    } 
} 


public class Player1 extends JApplet implements KeyListener, MouseListener, MouseMotionListener, Runnable{ 

    private ArrayList<CDomino> p1Dominoes; 
    private ArrayList<CDomino> p2Dominoes; 
    private CDomino activeDomino; 
    private String statusMessage; 

    public Player1(){ 
    } 

    public void run(){ 
     setFocusable(true); 
     addKeyListener(this); 
     addMouseListener(this); 
     addMouseMotionListener(this); 
     initialize(); 
     showWindow(); 
    } 

    public void initialize(){ 
     statusMessage = "Initializing window..."; 
     p1Dominoes = new ArrayList<CDomino>(); 
     p2Dominoes = new ArrayList<CDomino>(); 
     for (int i = 0; i < 7; i++){ 
      p1Dominoes.add(new CDomino(85 + i*100, 715, 0, 1)); 
      p2Dominoes.add(new CDomino(85 + i*100, 60, 0, 2)); 
     } 
     activeDomino = null; 
    } 

    public void paint(Graphics g){ 

     Image img = createImage(getSize().width, getSize().height); 
     Graphics gimg = img.getGraphics(); 
     gimg.setColor(new Color(235, 235, 235)); 
     gimg.clearRect(0, 0, getSize().width, getSize().height); 
     gimg.fillRect(0, 0, 800, 800); 

     gimg.setColor(Color.MAGENTA); 
     gimg.drawLine(0, 125, 800, 125); 
     gimg.drawLine(0, 650, 800, 650); 
     gimg.setColor(new Color(200, 255, 200)); 
     gimg.fillRect(0, 0, 800, 125); 
     gimg.setColor(new Color(180, 230, 255)); 
     gimg.fillRect(0, 651, 800, 125); 

     gimg.setColor(Color.RED); 
     gimg.setFont(new Font("SansSerif", Font.BOLD, 18)); 
     gimg.drawString(statusMessage, 10, 630); 

     for (CDomino domino : p1Dominoes) domino.draw(gimg, 1); 
     for (CDomino domino : p2Dominoes) domino.draw(gimg, 1); 


     g.drawImage(img, 0, 0, null); 
    } 

    public void setStatusMessage(String message){ 
     statusMessage = message; 
     repaint(); 
    } 

    public ArrayList<CDomino> getP1Dominoes(){ 
     return p1Dominoes; 
    } 

    public void mouseDragged(MouseEvent e) { 
     if (e.isMetaDown()) return; 
     for (CDomino domino : p1Dominoes){ 
      if ((domino.isInside(e.getX(), e.getY()) && activeDomino == null) || (activeDomino == domino)){ 
        activeDomino = domino; 
        domino.setPosition(e.getX(), e.getY()); 
        repaint(); 
      } 
     } 
    } 

    public void mouseMoved(MouseEvent e) { 
     // TODO Auto-generated method stub 

    } 

    public void mouseClicked(MouseEvent e) { 
     //if (!e.isMetaDown()) return; 
     tryRotate(e); 
    } 

    public void mouseEntered(MouseEvent e) { 
     // TODO Auto-generated method stub 

    } 

    public void mouseExited(MouseEvent e) { 
     // TODO Auto-generated method stub 

    } 

    public void mousePressed(MouseEvent e) { 
     } 

    private void tryRotate(MouseEvent e) { 
     if (!SwingUtilities.isRightMouseButton(e)) return; 
     for (CDomino domino : p1Dominoes){ 
      if (domino.isInside(e.getX(), e.getY())){ 
       domino.rotate(); 
       repaint(); 
      } 
     } 
    } 

    public void mouseReleased(MouseEvent e) { 
     activeDomino = null; 
    } 

    public void keyPressed(KeyEvent e) { 
    } 

    public void keyReleased(KeyEvent e) { 

    } 

    public void keyTyped(KeyEvent e) { 

    } 

    public void showWindow(){ 
     JFrame application = new JFrame("Dominoes - Player 1 (Server)"); 
     application.add(this); 
     application.setDefaultCloseOperation(3); 
     application.setSize(800, 800); 
     application.setLocationRelativeTo(null); 
     application.setVisible(true); 
     application.setResizable(false); 
    } 

} 

(Player2.java非常相似,但有setP1Dominoes(),它调用重绘()。)

回答

2

您需要查看ObjectOutputStream.reset()和什么是。在每个writeObject()之后调用它。

0

我看到的问题是在这里:

public void paint(Graphics g){ 
    Image img = createImage(...); 
    //... 
} 

因此,每个调用会创建另一个Image。 - 使Image的声明成为一个类变量,并在别处初始化它,以便绘制以获取Graphics对象开始。

有些奇怪 - 客户的主要电话:

p1GameThread.run() 

这是不是启动一个线程的正确方法;这是通过调用Thread.start()完成的。但是,然后运行方法应该监听对方的套接字消息。

请勿使用睡眠来确定另一次发送的时间。监听器检测表上的操作何时完成:这是发送的时间。

不要使用两个不同的Player类 - 这会造成越来越多的陷阱。演奏(除了设置第一步之外)是对称的,所以单个演奏者类应该是足够的。 - 可能需要某种“裁判”来同步动作 - 因为一个球员不能连续两步移动 - 将其添加到双方的另一个球员。

+0

所有的都是真的,但这里没有解决实际问题。 – EJP