3

我实际上正在开发一个记忆游戏,我被困在我应该编写游戏的游戏部分的地方。所以:我有一系列Ncard objects。每个对象都有一个名为cardNum- 标识符的属性。我想我应该actionListener在那个数组上写一个,所以当我翻转一张卡片时,它会将翻转的卡片cardNum放在一个包含两个元素的数组中,如果数组的两个元素相等,就会找到一对。问题是我只是不知道如何获得最后一张翻转的卡片cardNum。任何帮助,将不胜感激。

这是我尝试的方式:

private void easyGame(Card[] cards) {
    int flippedCards = 0;
    int card1;

    while(flippedCards != 24) {
        for(int i=0; i<cards.length; i++) {
            if(cards[i].getIsFlipped())
                flippedCards ++;
        }
        if(flippedCards % 2 == 0 && flippedCards > 0)
            for(int i=0; i<cards.length; i++) {
                card1 = getCardIndByCardNum(cards[i].getCardNum(), cards, i);

                if(!cards[card1].getIsFlipped()) {
                    for(int j=0; j<cards.length; j++) {
                        if(cards[i].getIsFlipped())
                            cards[i].flip();
                    }
                    flippedCards = 0;
                    break;
                }
            }
    }
}

问题是如果我调用这个方法,游戏将不会被绘制。我可以以某种方式使用使用线程吗?

编辑

以下是我如何获取点击卡片的索引,我在 UI 中调用它:

private void setCardHandlers() {
    for(final Card card : cards) {

        card.setOnMouseClicked(new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent t) {
                clickedCardInd = getChildren().indexOf(card)-1;
            }
        });
    }
}

比这里是我如何使用它:

setOnMouseReleased(new EventHandler<MouseEvent> () {

        @Override
        public void handle(MouseEvent t) {
            int cardIndex = clickedCardInd; // get index of what user clicked
            clickedCardInd = -1;
            if (cardIndex != -1 && moveRequestedFlag) { // our controller waits for the move
                // get the position and report
                moveRequestedFlag = false; // we handled the move
                //System.out.println(cardIndex);
                nextMove.setMove(cardIndex); // this will unblock controller's thread
            }
        }

    });

它在翻转卡片上有延迟,在easyGamerequestMove方法中也将两个索引设置为相同。

4

1 回答 1

1

我建议将您的职责拆分为模型/视图/控制器模块,在最简单的情况下,它们看起来像:

  • 模型 - 你的游戏当前状态和数据,即卡片数组Cards mCards = new Cards[24];
  • 查看 - 您的 UI,可以在主线程的屏幕上反映 mCards(model) 的当前状态
  • 控制器 - 你的主要游戏逻辑。这是最复杂的部分,负责
    1. 请求/处理用户移动,
    2. 根据用户移动更新 mCards(model),
    3. 请求重新绘制 UI。

控制器的代码(easyGame方法)应该在单独的线程上运行,以免阻塞 UI。

下面我绘制了一个应该符合您要求的骨架代码:

class Game {

    /*
     * controller - main logic
     */
    void startEasyGame() {
        // initialize cards array, shuffle if needed

        // we start with zero cards flipped
        int flippedCards = 0;

        // main loop
        while (flippedCards != mCards.length) {
            // 1. show updated UI
            mBoard.showUpdatedCards();

            // 2. request player move 
            // and block current thread to wait till move is done
            // the result of the move - index of the card
            int index1 = requestMove();
            // temporarily flip first card face-up
            mCards[index1].flip();
            // show it on screen
            mBoard.showUpdatedCards();

            // same for second card
            int index2 = requestMove();
            mCards[index2].flip();
            mBoard.showUpdatedCards();


            // 3. check the result
            if (mCards[index1].getCardNum() == mCards[index2].getCardNum()) {
                // hooray, correct guess, update count
                // possibly show some encouraging feedback to user
                flippedCards += 2;
            } else {
                // incorrect, flip cards back face down
                mCards[index1].flip();
                mCards[index2].flip();
            }

        } // end of while loop

        // game ended -> show score and time
        mBoard.showResult();    
    }

}

编辑
有关如何等待 UI 线程结果的额外详细信息:

int requestMove() {
    // 1. show user prompt to make a move
    // ...

    // 2. construct latch to wait for move done on UI thread
    mBoard.moveRequestedFlag = true;
    NextMove nextMove = new NextMove();
    mBoard.nextMove = nextMove;

    // 3. await for move and get the result
    return nextMove.getMove();
}

然后,在 UI 代码中的某处:

// handling card onClick somewhere on UI thread
if (mBoard.moveRequestedFlag) { // our controller waits for the move
    // get the position and report
    int cardIndex = ... // get index of what user clicked
    mBoard.moveReqestedFlag = false; // we handled the move
    mBoard.nextMove.setMove(cardIndex); // this will unblock controller's thread
}

和 NextMove 实用程序类来同步线程:

public class NextMove {
    private volatile int mCardIndex;
    private final CountDownLatch mMoveReady = new CountDownLatch(1);

    public int getMove() throws InterruptedException {
        mMoveReady.await();
        return mCardIndex;
    }

    public synchronized void setMove(int selectedCardIndex) {
        if (mMoveReady.getCount() > 0) {
            mCardIndex = selectedCardIndex;
            mMoveReady.countDown();
        }
    }
}
于 2013-12-28T12:41:50.497 回答