⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mjserver.java

📁 麻将程序
💻 JAVA
字号:
package com.newpalm.game.mj.server;

import java.util.Observer;

import com.newpalm.game.framework.Client;
import com.newpalm.game.framework.Server;
import com.newpalm.game.mj.client.MJBotClient;
import com.newpalm.game.mj.client.MJClient;
import com.newpalm.game.mj.share.GameState;
import com.newpalm.game.mj.share.MJCard;
import com.newpalm.game.mj.share.MJEventEat;
import com.newpalm.game.mj.share.Player;
import com.newpalm.game.mj.share.MJEventObject;
import com.newpalm.game.mj.share.MJEventRoundResult;

public class MJServer
    extends Server {

  /**
   *@see java.lang.Object#Object()
   */
  public MJServer() {
    setServerModule(new MJModule());
  }

  // Query interfaces
  public MJModule getMJModule() {
    return (MJModule)this.getServerModule();
  }

  private GameState getGameState() {
    return getMJModule().getGameState();
  }

  // Client commands.

  /* (non-Javadoc)
   * @see com.inxun.game.framework.Server#startNewGame()
   */
  public void onNewGame() {
    int left = 4 - countObservers();
    for (int i = 0; i < left; i++) {
      Player p = new Player("COM" + i, 25000);
      MJBotClient clt = new MJBotClient(p);
      clt.joinServer(this);
    }
    setChanged();
    notifyObservers(MJEventObject.getNewGameInstance());
  }

  public void onNewRound() {
    runMainCycler();
  }

  public void onDropACard(Object cid, MJCard card) {
    int cltNo = getClientPlayerNo(cid);
    if (getMJModule().getCurrentPlayerNo() != cltNo) {
      return;
    }
    getMJModule().getCardModule().dropCard(cltNo, card);
  }

  public void onPassSignal(Object cid) {
    int playerNo = getClientPlayerNo(cid);
    getMJModule().setPassResult(playerNo, MJEventObject.getPassInstance());
  }

  public void onEatWithPair(Object cid, MJCard card, MJCard[] pair) {
    int playerNo = getClientPlayerNo(cid);
    MJEventEat eeat = new MJEventEat(card, pair);
    getMJModule().setPassResult(playerNo, eeat);
  }

  public void onPeng(Object cid, MJCard card) {
    int playerNo = getClientPlayerNo(cid);
    MJEventObject epeng = MJEventObject.getPengInstance(card);
    getMJModule().setPassResult(playerNo, epeng);
  }

  public void onGang(Object cid, MJCard card) {
    int playerNo = getClientPlayerNo(cid);
    MJEventObject egang = MJEventObject.getGangInstance(card);
    getMJModule().setPassResult(playerNo, egang);
  }

  public void onAnGang(Object cid, MJCard card) {
    int playerNo = getClientPlayerNo(cid);
    MJEventObject egang = MJEventObject.getAnGangInstance(card);
    getMJModule().setPassResult(playerNo, egang);
  }

  public void onHu(Object cid) {
    int playerNo = getClientPlayerNo(cid);
    int bankNo = getMJModule().getBankerNo();
    MJEventRoundResult ehu = MJEventRoundResult.getHuInstance();
    ehu.setWinnerNo(playerNo);
    int[] jetons = ehu.getJetons();
    int jetonwin = 0;
    for (int i = 0; i < jetons.length; i++) {
      if (i != playerNo) {
        jetons[i] = -1000;
        if (i == bankNo) {
          jetons[i] += -1000;
        }
        if (bankNo == playerNo) {
          jetons[i] *= 2;
        }
        jetonwin += ( -jetons[i]);
      }
    }
    jetons[playerNo] = jetonwin;
    ehu.setJetons(jetons);

    String winner = getMJModule().getOnlineClient(playerNo).getPlayer().getName();
    String str = winner + " WIN!\n\n";
    for (int i = 0; i < 4; i++) {
      str += getMJModule().getOnlineClient(i).getPlayer().getName();
      str += ": " + jetons[i] + "\n";
    }
    ehu.setDescription(str);

    getMJModule().setPassResult(playerNo, ehu);
  }

  // Private method

  private void runMainCycler() {
    // goes round after round
    while (true) {
      int bankerNo = getMJModule().getBankerNo();
      bankerNo = (bankerNo + 1) % 4;
      getMJModule().getGameState().setBankerSeatNo(bankerNo);
      getMJModule().getCardModule().sendInitialCards(bankerNo);
      getMJModule().getCardModule().setCurrentPlayerNo(bankerNo);
      getMJModule().getCardModule().setLastPlayerNo(bankerNo);
      setChanged();
      notifyObservers(MJEventObject.getNewRoundInstance());

      MJEventRoundResult rt = runPlayCycler();
      for (int i = 0; i < 4; i++) {
        Player p = getMJModule().getOnlineClient(i).getPlayer();
        p.setJeton(p.getJeton() + rt.getJetons()[i]);
      }
      setChanged();
      notifyObservers(rt);

      try {
        Thread.sleep(3000);
      }
      catch (InterruptedException e) {
        System.err.println(e);
      }

    }
  }

  /**
   * 处理出牌逻辑,主循环是
   * 1、通知当前玩家出牌
   * 1.1如果当前玩家胡(自摸),退出循环
   * 1.2如果当前玩家暗杠,则跳至3
   * 1.3不胡不暗杠,就是舍牌的情况,继续到2
   * 2、询问其他玩家,是否要吃、碰、杠、胡(点炮)舍牌
   * 3、发下一张牌,返回1
   *
   * 需要注意的是对notify的处理,一般情况下,接受到Client的指令,需要立即
   * 做处理,并推进循环(比如在onDropACard中set CurrentPlayer++)
   * 但是,有个很严重的潜在问题:
   * 因为是单线程,server-(notify)->client-(command)->server-(notify)->client
   * 是顺序执行的,所以会形成多个方法间的递归调用,加上有多个client……
   *
   * 解决办法是client对server的指令存放在passResult里,但不推进循环,存放
   * 结果后立即返回主循环,由主循环负责结果指令,并推进
   *
   * @return
   */
  private MJEventRoundResult runPlayCycler() {
    MJEventRoundResult rt = null;
    boolean hasMoreCard = true;
    int playerNo;
    int passResultNo;
    MJEventObject passResult;
    int lastPlayerNo;

    // play -> eat|peng|gang|hu -> play ... loop
    while (hasMoreCard) {
      playerNo = getMJModule().getCurrentPlayerNo();

      getMJModule().clearPassResult();
      //因为用单线程,调用会立即返回。
      notifyClient(playerNo, MJEventObject.getWaitPlayInstance());

      if (getMJModule().getPassResultCount() > 0) {
        // hu, zimo, an gang
        passResult = getMJModule().getPassResult(playerNo);
        if (passResult.getEventId() == MJEventObject.HU) {
          return (MJEventRoundResult) passResult;
        }
        else if (passResult.getEventId() == MJEventObject.AN_GANG) {
          MJCard card = (MJCard) passResult.getData();
          getMJModule().getCardModule().anGang(playerNo, card);
          card =
              getMJModule()
              .getCardModule()
              .fetchNextBoardCardToCurrentPlayer();
          if (card == null) {

            //	hasMoreCard = false;
            break;
          }
          else {
            continue;
          }
        }
      }

      lastPlayerNo = getMJModule().getLastPlayerNo();
      getMJModule().clearPassResult();
      //因为用单线程,调用会立即返回。
      notifyOtherClientsByOrder(
          lastPlayerNo,
          MJEventObject.getWaitPassInstance());

      // Choose priority result
      // getMJModule().getPassResultCount() == 3;
      passResultNo =
          getMJModule().getPriotityPassNo( (lastPlayerNo + 1) % 4);
      passResult =
          (passResultNo == -1)
          ? null
          : getMJModule().getPassResult(passResultNo);

      if (passResultNo == -1) {
        // all pass
        playerNo = (playerNo + 1) % 4;
        getMJModule().getCardModule().setCurrentPlayerNo(playerNo);

      }
      else if (passResult.getEventId() == MJEventObject.EAT) {
        // eat
        MJEventEat eeat = (MJEventEat) passResult;
        getMJModule().getCardModule().eatWithPair(
            passResultNo,
            eeat.getCard(),
            eeat.getPair());
        getMJModule().getCardModule().setCurrentPlayerNo(passResultNo);

      }
      else if (passResult.getEventId() == MJEventObject.PENG) {
        // peng
        MJCard card = (MJCard) passResult.getData();
        getMJModule().getCardModule().peng(passResultNo, card);
        getMJModule().getCardModule().setCurrentPlayerNo(passResultNo);

      }
      else if (passResult.getEventId() == MJEventObject.GANG) {
        // gang
        MJCard card = (MJCard) passResult.getData();
        getMJModule().getCardModule().gang(passResultNo, card);
        getMJModule().getCardModule().setCurrentPlayerNo(passResultNo);

      }
      else if (passResult.getEventId() == MJEventObject.HU) {
        // hu
        return (MJEventRoundResult) passResult;

      }

      if (passResultNo == -1
          || passResult.getEventId() == MJEventObject.GANG) {
        MJCard card =
            getMJModule()
            .getCardModule()
            .fetchNextBoardCardToCurrentPlayer();
        if (card == null) {
          hasMoreCard = false;
        }
      }

    } // while

    return MJEventRoundResult.getDrawInstance();
  }

  private int getClientPlayerNo(Object cid) {
    return getMJModule().getClientPlayerNo(cid);
  }

  // observable methods
  private void notifyClient(int playerNo, Object arg) {
    Client clt = getMJModule().getOnlineClient(playerNo);
    if (clt != null) {
      clt.update(this, arg);
    }
  }

  private void notifyOtherClientsByOrder(int playerNo, Object arg) {
    for (int i = playerNo + 1; i < playerNo + 4; i++) {
      notifyClient(i % 4, arg);
    }
  }

  public synchronized void addObserver(Observer o) {
    if (! (o instanceof MJClient)) {
      return;
    }

    MJClient clt = (MJClient) o;
    int playerNo = countObservers();

    getMJModule().setOnlineClient(playerNo, clt);

    super.addObserver(clt);
    setChanged();
    notifyObservers(MJEventObject.getNewJoinInstance());

  }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -