ObjectInputStream不会读取多次

时间:2015-11-22 07:10:34

标签: java serializable objectoutputstream

我一直试图制作一个双人多米诺骨牌游戏。现在,我希望玩家1的动作可以在玩家2的屏幕上模仿,仅此而已。如果我启动播放器1的屏幕并移动一些Domino,则在我启动播放器2的屏幕时会出现更改。但是从那时起的任何动作都不会改变。这有什么不对?

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非常相似,但有一个调用repaint()的setP1Dominoes()。)

2 个答案:

答案 0 :(得分:2)

你需要查找ObjectOutputStream.reset()以及它的用途。每隔writeObject()后调用一次。

答案 1 :(得分:0)

我看到的问题是:

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

因此,每次调用都会创建另一个Image。 - 使Image img声明为一个类变量并在其他地方初始化它,以便绘制从获取Graphics对象开始。

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

p1GameThread.run()

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

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

不要使用两个不同的Player类 - 这会产生越来越多的陷阱。播放(除了设置第一步之外)是对称的,因此单个Player类就足够了。 - 可能需要某种“裁判”来同步动作 - 因为连续一个玩家不能有两个动作 - 将它添加到双方存在的另一个类别。