首页 文章

Java RMI游戏未运行[关闭]

提问于
浏览
-1

我一直在撞墙试图解决这个问题 . 很确定我今天丢了一些头发 .

基本上,我们得到了一些工作类,并被要求在其上实施RMI . 在给定的代码中有一些错误,但我修复了它们 . 现在我根本没有任何错误,但它无法正常工作 .

这是课程:

GameClient.java - 由我完成

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class GameClient extends UnicastRemoteObject implements IGUI, IGameEngine, Runnable {
    IGameServer ser;
    PlayerInfo player;
    IGUI g;
    IGameEngine ge;

    public GameClient(IGameServer ss) throws RemoteException {
        ser = ss;
        ser.registerClient(this);
    }

    @Override
    public void markedAsOriginalDisplayMode() throws RemoteException {
        g.markedAsOriginalDisplayMode();
    }

    @Override
    public void noMarkedDisplayMode() throws RemoteException {
        g.noMarkedDisplayMode();
    }

    @Override
    public void normalDisplayMode() throws RemoteException {
        g.normalDisplayMode();
    }

    @Override
    public void update() throws RemoteException {
        g.update();
    }

    @Override
    public void exit(int i) throws RemoteException {
        g = null;
        setGUI(g);
        ser.setGameOver();
        System.exit(i);
    }

    @Override
    public PlayingBlock getNextBlock() throws RemoteException {
        return ser.getNextBlock();
    }

    @Override
    public PlayArea getPlayArea() throws RemoteException {
        return ser.getPlayArea();
    }

    @Override
    public String getPlayerName() throws RemoteException {
        return ser.getPlayerName();
    }

    @Override
    public int getPlayerScore() throws RemoteException {
        return ser.getPlayerScore();
    }

    @Override
    public boolean isGameOver() throws RemoteException {
        return ser.isGameOver();
    }

    @Override
    public void setGameOver() throws RemoteException {
        ser.setGameOver();
    }

    public void setGUI(IGUI gui) {
        g = gui;
    }

    @Override
    public void setPlayer(PlayerInfo pi) {
        try {
            ser.setPlayer(pi);
        }
        catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void setPlayerName(String name) throws RemoteException {
        ser.setPlayerName(name);
    }

    @Override
    public void start() throws RemoteException {
        ser.start();
    }

    @Override
    public void treatEvent(int event) throws RemoteException {
        ser.treatEvent(event);
    }

    @Override
    public void run() {
        String playerName = "Vasilis";
        setPlayer(new PlayerInfo(playerName));
        IGUI gui = new GUI(this, 20, 25);
        setGUI(gui);
    }
}

IGameEngine.java

import java.rmi.RemoteException;

/**
 * Interface representing the logic of the game
 */

public interface IGameEngine {

    public void treatEvent(int event) throws RemoteException;

    public void start() throws RemoteException;

    public PlayingBlock getNextBlock() throws RemoteException;

    public boolean isGameOver() throws RemoteException;

    public void setGameOver() throws RemoteException;

    public PlayArea getPlayArea() throws RemoteException;

    public int getPlayerScore() throws RemoteException;

    public void setPlayerName(String name) throws RemoteException;

    public void setPlayer(PlayerInfo pi);

    public String getPlayerName() throws RemoteException;

    public void setGUI(IGUI gui);

    public void exit(int status) throws RemoteException;

}

GameEngine.java

import java.rmi.RemoteException;
import java.util.*;

class GameEngine {
    private PlayArea board;

    private PlayerInfo player;

    private PlayingBlock activeBlock;

    private PlayingBlock nextBlock;

    private Timer timer;

    private TimerTask pendingTask;

    private int timerValue;

    private float timerScaleFactor;

    private int minTimerValue;

    private int timerValueChangeInterval;

    private int numBlocks;

    private Random rng;

    private IGUI gui;

    private boolean gameOver;

    private boolean controlsLocked;

    public GameEngine(int size) {
        board = new PlayArea(size);
        rng = new Random(System.currentTimeMillis());
        resetGame();
    }

    protected void resetGame() {
        nextBlock = null;
        board.init();
        timerScaleFactor = Settings.TIMERSCALE;
        minTimerValue = Settings.MINTIMER;
        timerValue = Settings.INITTIMER;
        timerValueChangeInterval = Settings.CHANGETIMER;
        timer = new Timer();
        gameOver = false;
        controlsLocked = true;
        if (player != null) player.reset();
    }

    public void setGUI(IGUI gui) {
        this.gui = gui;
    }

    private void updateGUI() throws RemoteException {
        gui.update();
    }

    public void setPlayer(PlayerInfo player) {
        this.player = player;
    }

    public String getPlayerName() {
        return player.getName();
    }

    public void setPlayerName(String name) {
        player.setName(name);
    }

    public int getPlayerScore() {
        return player.getScore();
    }

    public PlayArea getPlayArea() {
        return board;
    }

    public boolean isGameOver() {
        return gameOver;
    }

    public void setGameOver() {
        this.gameOver = true;
    }

    public PlayingBlock getNextBlock() {
        return nextBlock;
    }

    // --> game_engine_timer_methods
    private void adjustTimerValue() {
        if (++numBlocks % timerValueChangeInterval == 0) {
            float nextTimerValue = (float) timerValue / timerScaleFactor;
            timerValue = nextTimerValue < minTimerValue ? minTimerValue : Math.round(nextTimerValue);
        }
    }

    private void rescheduleTimer() {
        stopTimer();
        final PlayingBlock block = activeBlock;
        pendingTask = new TimerTask() {
            public void run() {
                synchronized (GameEngine.this) {
                    if (block.equals(activeBlock)) try {
                        treatEvent(GameEvent.TIMEOUT);
                    }
                    catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        timer.schedule(pendingTask, timerValue);
    }

    // --<
    // --> game_engine_start_method
    public void start() throws RemoteException {
        resetGame();
        nextBlock = new PlayingBlock(rng.nextInt(3) + 1, Colour.randomColour(rng), PlayArea.randomSide(rng));
        nextBlock();
        updateGUI();
        controlsLocked = false;
        rescheduleTimer();
    }

    public void stopTimer() {
        if (pendingTask != null) pendingTask.cancel();
    }

    public void exit(int status) {
        System.exit(status);
    }

    // --<
    // --> game_engine_nextBlock_method
    private boolean nextBlock() {
        int size = board.getSize();
        switch (nextBlock.getSide()) {
            case PlayArea.NORTHSIDE:
                nextBlock.activate(new Coord(size / 2, 1).add(nextBlock.getCoG().neg()));
                break;
            case PlayArea.SOUTHSIDE:
                nextBlock.activate(new Coord(size / 2, size - 2).add(nextBlock.getCoG().neg()));
                break;
            case PlayArea.EASTSIDE:
                nextBlock.activate(new Coord(size - 2, size / 2).add(nextBlock.getCoG().neg()));
                break;
            case PlayArea.WESTSIDE:
                nextBlock.activate(new Coord(1, size / 2).add(nextBlock.getCoG().neg()));
                break;
            default: // should never occur
                break;
        }
        activeBlock = nextBlock;
        if (board.collision(activeBlock)) return false;
        else {
            board.flipDraw(activeBlock);
            nextBlock = new PlayingBlock(rng.nextInt(3) + 1, Colour.randomColour(rng), PlayArea.randomSide(rng));
            adjustTimerValue();
            return true;
        }
    }

    // --<
    // --> game_engine_movement_methods
    private boolean rotate() {
        return move(null);
    }

    private boolean slideActiveBlock() {
        return move(activeBlock.getSlidingDirection());
    }

    private boolean move(Direction direction) {
        boolean success = false;

        // is the move forbidden?
        if (direction != null && direction.equals(activeBlock.getSlidingDirection().getReverse())) return false;

        board.flipDraw(activeBlock);
        if (direction == null) activeBlock.rotate();
        else activeBlock.move(direction);
        if (!board.collision(activeBlock)) success = true;
        else // put activeBlock back
            if (direction == null) activeBlock.rotate();
            else activeBlock.move(direction.getReverse());
        board.flipDraw(activeBlock);
        return success;
    }

    // --<
    // --> game_engine_event_handler
    synchronized public void treatEvent(int event) throws RemoteException {
        if (controlsLocked || gameOver) return;

        switch (event) {
            case GameEvent.TIMEOUT:
                if (slideActiveBlock()) {
                    rescheduleTimer();
                    updateGUI();
                    break;
                }
                else {
                    updateScore();
                    return;
                }
            case GameEvent.UP:
                if (move(Direction.up())) updateGUI();
                break;
            case GameEvent.DOWN:
                if (move(Direction.down())) updateGUI();
                break;
            case GameEvent.RIGHT:
                if (move(Direction.right())) updateGUI();
                break;
            case GameEvent.LEFT:
                if (move(Direction.left())) updateGUI();
                break;
            case GameEvent.ROTATE:
                if (rotate()) updateGUI();
                break;
            case GameEvent.FLY:
                pendingTask.cancel();
                pendingTask = null;
                while (slideActiveBlock()) ;
                updateScore();
                return;
            default:
                // should never occur
        }
    }

    // --<
    // --> game_engine_scoring_methods
    private void updateScore() {
        controlsLocked = true;
        new Thread() {
            public void run() {
                int rounds = 0;
                while (findSquares(++rounds)) {
                    // animate square
                    for (int i = 0; i < 4; i++) {
                        if (i % 2 == 0) try {
                            gui.markedAsOriginalDisplayMode();
                        }
                        catch (RemoteException e) {
                            e.printStackTrace();
                        }
                        else try {
                            gui.normalDisplayMode();
                        }
                        catch (RemoteException e) {
                            e.printStackTrace();
                        }
                        try {
                            updateGUI();
                        }
                        catch (RemoteException e) {
                            e.printStackTrace();
                        }
                        try {
                            Thread.sleep(150);
                        }
                        catch (InterruptedException e) {
                            e.printStackTrace();
                            exit(1);
                        }
                    }
                    try {
                        updateBoard();
                    }
                    catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }

                if (nextBlock()) {
                    rescheduleTimer();
                }
                else {
                    timer.cancel();
                    gameOver = true;
                }
                try {
                    updateGUI(); // new block is active, display
                }
                catch (RemoteException e) {
                    e.printStackTrace();
                }
                controlsLocked = false; // unlock controls
            }
        }.start();
    }

    private boolean findSquares(int round) {
        int roundScore = 0;
        // brute force
        boolean found = false;
        int playSize = board.getSize();
        for (int size = 3; size >= 2; size--)
            for (int x = 0; x < playSize; x++)
                for (int y = 0; y < playSize; y++) {
                    int squareColour = board.getSquareColour(x, y, size);
                    if (Colour.isPlayBrick(squareColour)) {
                        roundScore += size * size;
                        // player.incScore((int) Math.pow(size * size, round));
                        if (size == 2) {
                            board.mark(x, y, size);
                            found = true;
                        }
                    }
                }
        if (roundScore > 0) player.incScore((int) Math.pow(roundScore, round));
        return found;
    }

    public void updateBoard() throws RemoteException {
        Direction blockDir = activeBlock.getSlidingDirection();
        Direction updateDir = blockDir.getReverse();
        Coord checkBrick;
        boolean falling;
        int size = board.getSize();

        gui.noMarkedDisplayMode();
        for (int i = 0; i < size; i++) {
            falling = false;

            if (blockDir.equals(Direction.up())) checkBrick = new Coord(i, 0);
            else if (blockDir.equals(Direction.down())) checkBrick = new Coord(i, size - 1);
            else if (blockDir.equals(Direction.left())) checkBrick = new Coord(0, i);
            else checkBrick = new Coord(size - 1, i);

            for (int j = 0; j < size; j++) {
                int brickColour = board.getBrick(checkBrick);
                if (Colour.isMarked(brickColour)) {
                    falling = true;
                    board.setBrick(checkBrick, Colour.BASE);
                }
                else if (falling) if (Colour.isPlayBrick(brickColour)) {
                    board.setBrick(checkBrick, Colour.BASE);
                    PlayingBlock tmpBlock = new PlayingBlock(1, brickColour, PlayArea.NORTHSIDE);
                    // we just need any temporary block
                    tmpBlock.activate(checkBrick.add(blockDir.getCoordIncrement()));
                    while (!board.collision(tmpBlock)) {
                        // animate the fall
                        board.flipDraw(tmpBlock);
                        updateGUI();
                        try {
                            Thread.sleep(50);
                        }
                        catch (InterruptedException e) {
                            e.printStackTrace();
                            exit(1);
                        }
                        board.flipDraw(tmpBlock);
                        tmpBlock.move(blockDir);
                    }
                    tmpBlock.move(updateDir);
                    board.flipDraw(tmpBlock);
                }
                else {
                    break; /* stop falling, finish with this loop */
                }
                checkBrick = checkBrick.add(updateDir.getCoordIncrement());
            }
        }
        gui.normalDisplayMode();
    }
    // --<
}

IGUI.java

/**
 * The server's remote reference to a client
 *
 *
 */

import java.rmi.*;

public interface IGUI extends Remote {

    public void update() throws RemoteException;

    public void normalDisplayMode() throws RemoteException;

    public void noMarkedDisplayMode() throws RemoteException;

    public void markedAsOriginalDisplayMode() throws RemoteException;

}

Squares.java

import java.rmi.RemoteException;

//--> squares_class
class Squares {

    public static void main(String[] args) throws RemoteException {
        GameClient gc = new GameClient();
        String playerName = "Quidam";

        if (args.length == 1) if (args[0].length() > 15) playerName = args[0].substring(0, 15);
        else playerName = args[0];
        gc.setPlayer(new PlayerInfo(playerName));

        IGUI gui = new GUI(gc, 20, 25);
        gc.setGUI(gui);

    }
}
// --<

IGameServer.java

/**
 * The interface which defines what operations our server can perform for clients
 *
 *
 */

import java.rmi.*;

public interface IGameServer extends Remote {

    public void registerClient(IGUI clientGUI) throws RemoteException;

    public void treatEvent(int event) throws RemoteException;

    public void start() throws RemoteException;

    public PlayingBlock getNextBlock() throws RemoteException;

    public boolean isGameOver() throws RemoteException;

    public void setGameOver() throws RemoteException;

    public PlayArea getPlayArea() throws RemoteException;

    public int getPlayerScore() throws RemoteException;

    public void setPlayerName(String name) throws RemoteException;

    public void setPlayer(PlayerInfo pi) throws RemoteException;

    public String getPlayerName() throws RemoteException;

}

这是我创建的文件, GameServer.java

import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.LinkedList;

/**
 * Created with IntelliJ IDEA.
 * User: akay
 * Date: 25/11/2013
 * Time: 19:07
 * To change this template use File | Settings | File Templates.
 */
public class GameServer extends UnicastRemoteObject implements IGameServer, Serializable {
    LinkedList<IGUI> array;
    GameEngine ge = new GameEngine(25);

    public GameServer() throws RemoteException {
        array = new LinkedList();
    }

    @Override
    public PlayingBlock getNextBlock() throws RemoteException {
        return ge.getNextBlock();
    }

    @Override
    public PlayArea getPlayArea() throws RemoteException {
        return ge.getPlayArea();
    }

    @Override
    public String getPlayerName() {
        return ge.getPlayerName();
    }

    @Override
    public int getPlayerScore() {
        return ge.getPlayerScore();
    }

    @Override
    public boolean isGameOver() throws RemoteException {
        return ge.isGameOver();
    }

    @Override
    public void registerClient(IGUI clientGUI) throws RemoteException {
        array.add(clientGUI);
        ge.setGUI(clientGUI);
    }

    @Override
    public void setGameOver() throws RemoteException {
        ge.setGameOver();
    }

    @Override
    public void setPlayer(PlayerInfo pi) {
        ge.setPlayer(pi);
    }

    @Override
    public void setPlayerName(String name) {
        ge.setPlayerName(name);
    }

    @Override
    public void start() throws RemoteException {
        ge.start();
    }

    @Override
    public void treatEvent(int event) throws RemoteException {
        ge.treatEvent(event);
    }

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

        Registry registry;
        GameServer s;
        final int port = Registry.REGISTRY_PORT;

        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new java.rmi.RMISecurityManager());
        }

        try {
            registry = LocateRegistry.createRegistry(port);
        }
        catch (RemoteException e) {
            System.out.println("The registry couldn't be created.");
            e.printStackTrace();
        }

        try {
            s = new GameServer();
            java.rmi.Naming.rebind("Server", s);
        }
        catch (MalformedURLException e) {
            System.out.println("Bad server URI in registration.");
        }
        catch (RemoteException e) {
            System.out.println("Couldn't bind server.");
            e.printStackTrace();
        }

        try {
            System.in.read();
        }
        catch (IOException e) {
        }

        System.exit(0);
    }
}

修改了这些文件以修复错误并实现RMI . 现在,应该采取的步骤如下:

  • 创建实现 IGUIIGameEngine 接口的 GameClient 类 . 它将使用注册表找到服务器,并接受来自 GUI 的本地调用,将它们转换为服务器上的远程调用并返回任何结果 .

  • 更改 GUI 类,使其对 GameEngine 的引用的类型为 IGameEngine 而不是

  • Squares 类,将启动游戏的客户端部分,现在需要创建 GameClient 的实例并将其传递给 GUI 作为对 IGameEngine 的引用

  • 创建实现 IGameServer 接口的 GameServer 类,还包含启动服务器和游戏引擎的 main() 方法

  • 更改 GameEngine 类,使其对 GUI 的引用现在为 IGUI 类型;这将是它对客户端的远程引用 . 当 GameEngine 现在远程调用 GUI 时,您需要捕获一些异常 .

  • 编译你所做的事情,修复你遇到的任何错误,然后尝试运行你的分布式游戏 . 您可能会看到一些运行时异常,您还需要解决这些异常 .

这些是建议的步骤 . 我已经实现了除了一个以外的所有,这是第三个 .

任何帮助表示赞赏 .

如果要下载zip文件中的所有文件,请执行以下操作:http://akay.me/gameCode.zip

谢谢你的任何指示 .

编辑:我编辑了我的 Squares 类,通过包括以下内容从注册表中获取服务器名称:

String host = null;

Registry registry = LocateRegistry.getRegistry(host);
IGameServer s = (IGameServer) registry.lookup("Server");
GameClient gc = new GameClient(s);

正如所建议的那样

现在我收到以下错误:

java.rmi.MarshalException: error marshalling arguments; nested exception is: 
    java.io.NotSerializableException: PlayerInfo
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:138)
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
    at com.sun.proxy.$Proxy0.setPlayer(Unknown Source)
    at GameClient.setPlayer(GameClient.java:80)
    at Squares.main(Squares.java:21)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.io.NotSerializableException: PlayerInfo
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1165)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:329)
    at sun.rmi.server.UnicastRef.marshalValue(UnicastRef.java:274)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:133)
    ... 10 more
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at GameEngine.getPlayerName(GameEngine.java:67)

1 回答

  • 2

    你真的需要学习阅读错误信息 . 它们具有问题的精确位置,并且问题的描述也很清楚:

    GameClient类中的构造函数GameClient不能应用于给定的类型; required:发现IGameServer:无参数原因:实际和形式参数列表的长度不同

    那么,这意味着什么?这意味着你正在调用 new GameClient() ,没有任何参数,而GameClient的构造函数被声明为

    public GameClient(IGameServer ss) throws RemoteException {
    

    因此,您必须将IGameServer类型的对象传递给构造函数,而不是传递任何东西 .

相关问题