ObjectInputStream 不读取多次
ObjectInputStream Not Reading More Than Once
我一直在尝试制作一款两人多米诺骨牌游戏。现在,我只想在玩家 2 的屏幕上模仿玩家 1 的动作,仅此而已。如果我启动播放器 1 的屏幕并移动一些多米诺骨牌,则当我启动播放器 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()。)
我看到的问题在这里:
public void paint(Graphics g){
Image img = createImage(...);
//...
}
因此,每次调用都会创建另一个图像。 - 将 Image img 声明为 class 变量并在别处初始化它,以便绘制从获取 Graphics 对象开始。
有点奇怪 - 客户的主要电话:
p1GameThread.run()
这不是启动线程的正确方法;这是通过调用 Thread.start() 来完成的。但是 运行 方法应该监听对方的套接字消息。
不要使用睡眠来确定另一次发送的时间。侦听器检测 table 上的操作何时完成:这是发送时间。
不要使用两个不同的播放器 classes - 这会造成越来越多的陷阱。下棋(设置第一步除外)是对称的,因此单个玩家 class 应该就足够了。 - 可能需要某种 "referee" 来同步动作 - 因为一个玩家不能连续进行两次移动 - 将其添加到双方都存在的另一个 class 中。
您需要查找 ObjectOutputStream.reset()
及其用途。在每 writeObject()
.
之后调用它
我一直在尝试制作一款两人多米诺骨牌游戏。现在,我只想在玩家 2 的屏幕上模仿玩家 1 的动作,仅此而已。如果我启动播放器 1 的屏幕并移动一些多米诺骨牌,则当我启动播放器 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()。)
我看到的问题在这里:
public void paint(Graphics g){
Image img = createImage(...);
//...
}
因此,每次调用都会创建另一个图像。 - 将 Image img 声明为 class 变量并在别处初始化它,以便绘制从获取 Graphics 对象开始。
有点奇怪 - 客户的主要电话:
p1GameThread.run()
这不是启动线程的正确方法;这是通过调用 Thread.start() 来完成的。但是 运行 方法应该监听对方的套接字消息。
不要使用睡眠来确定另一次发送的时间。侦听器检测 table 上的操作何时完成:这是发送时间。
不要使用两个不同的播放器 classes - 这会造成越来越多的陷阱。下棋(设置第一步除外)是对称的,因此单个玩家 class 应该就足够了。 - 可能需要某种 "referee" 来同步动作 - 因为一个玩家不能连续进行两次移动 - 将其添加到双方都存在的另一个 class 中。
您需要查找 ObjectOutputStream.reset()
及其用途。在每 writeObject()
.