我正在编写一个简单的纸牌游戏。当你点击一副牌时,它会抽一张牌,然后它应该会弹出一个消息对话框,说明轮到玩家 2 了。但是,被移除并涂到玩家 1 手上的牌会被 JOptionPane 消息对话框打断,它会创建一个工件(我的意思是它会涂上手中的牌,但也会在牌组和你的牌组之间随机绘制手。)在 AI 响应和 JOptionPane.showMessageDialog 上的 SwingUtilities.invokeLater 似乎是合乎逻辑的选择,但它会导致代码执行两次,让玩家 2(一个 AI)两个回合。使用 invokeAndWait 会引发错误,因为它是从 EDT 调用的,所以我没有选择。我将如何摆脱工件?http://i1065.photobucket.com/albums/u400/mfgravesjr/go%20fish%20screenshot_zpsxav4hn59.png
这是每一堆卡片中的鼠标监听器。它是我命名为 Stack 的类的一部分。mouseReleased 中有一个 if 语句,用于查看卡片是否被拖动。如果不是,它将执行 StackRuleConstraints.stackClickAction(),它在下一个代码块中定义。
private MouseAdapter ml = new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
targetCardTable = (CardTable)SwingUtilities.getAncestorOfClass(CardTable.class,selfReference);
if((rules&INACCESSIBLE)==0)
{
if((rules&RECEPTACLE)>0)
{
reasonForRejection = "This stack abides by the RECEPTACLE rule. You cannot draw cards from this pile.";
if(printRuleRejections)System.out.println(reasonForRejection);
return;
}
xOrigin = e.getXOnScreen();
yOrigin = e.getYOnScreen();
for(int i = 0; i < cards.size(); i++)
{
if(cards.get(i).getLocationOnScreen().x<xOrigin
&&xOrigin<cards.get(i).getLocationOnScreen().x+50
&&cards.get(i).getLocationOnScreen().y<yOrigin
&&yOrigin<cards.get(i).getLocationOnScreen().y+70)
{
cardsToRemove.clear();
groupedCards = null;
if(i!=cards.size()-1)
{
if((rules&GRAB_FROM_TOP)>0)continue;
if((rules&GRAB_BY_GROUP)>0&&i!=cards.size()-1)
{
groupedCards = new Card[cards.size()-1-i];
for(int j = i+1; j < cards.size(); j++)
{
groupedCards[j-i-1] = cards.get(j);
cardsToRemove.add(cards.get(j));
}
}
}
if((rules&DRAW_PILE)==0&&!cards.get(i).isSelected())//if the card you clicked is facedown
{
if(i!=cards.size()-1)
{
continue; //if it's not the top card, return
}
else if((rules&FLIPPABLE)>0)//otherwise flip it faceup
{
cards.get(i).setSelected(true);
repaint();
return;
}
}
cardOrigin = cards.get(i).getLocationOnScreen();
selectedCard = cards.get(i);
draggedCardXOffset = xOffset;
draggedCardYOffset = yOffset;
}
}
}
else
{
reasonForRejection = "This stack abides by the INACCESSIBLE rule. You cannot manipulate the cards in this stack.";
if(printRuleRejections)System.out.println(reasonForRejection);
}
}
public void mouseDragged(MouseEvent e)
{
if(!dragging&&selectedCard!=null)
{
remove(selectedCard);
if(cardsToRemove.size()>0)for(int i = 0; i < cardsToRemove.size(); i++){remove(cardsToRemove.get(i));}
dragging = true;
}
mouseX = e.getXOnScreen();
mouseY = e.getYOnScreen();
((CardTable)SwingUtilities.getAncestorOfClass(CardTable.class,selfReference)).repaint();
}
public void mouseReleased(MouseEvent e)
{
if(dragging)ADDING_CARD_TO_STACK:
{
for(Component c: getParent().getComponents())
{
if(c instanceof Stack
&&e.getXOnScreen()>c.getLocationOnScreen().x
&&e.getXOnScreen()<c.getLocationOnScreen().x+c.getWidth()
&&e.getYOnScreen()>c.getLocationOnScreen().y
&&e.getYOnScreen()<c.getLocationOnScreen().y+c.getHeight()
&&selectedCard!=null)
{
if((((Stack)c).rules&DRAW_PILE)>0)
{
reasonForRejection = "This stack abides by the DRAW_PILE rule. You cannot place a card here.";
if(printRuleRejections)System.out.println(reasonForRejection);
break;
}
if((((Stack)c).rules&INACCESSIBLE)>0)
{
reasonForRejection = "This stack abides by the INACCESSIBLE rule. You cannot manipulate the cards in this stack.";
if(printRuleRejections)System.out.println(reasonForRejection);
break;
}
if((((Stack)c).rules&AUTO_FACEUP)==0&&!selectedCard.isSelected())
{
reasonForRejection = "This stack does not abide by the AUTO_FACEUP rule. Cards placed on this stack must be faceup.";
if(printRuleRejections)System.out.println(reasonForRejection);
break;
}
if((((Stack)c).rules&ASCENDING)>0&&(((Stack)c).cards.size()>0&&((Stack)c).cards.get(((Stack)c).cards.size()-1).getRank()!=selectedCard.getRank()-1)||(((Stack)c).cards.size()==0&&selectedCard.getRank()!=1&&(((Stack)c).rules&ASCENDING)>0))
{
reasonForRejection = "This stack abides by the ASCENDING rule. Cards placed on this pile must have a rank equal to one plus the rank of the card below it.";
if(printRuleRejections)System.out.println(reasonForRejection);
break;
}
if(((((Stack)c).rules&DESCENDING)>0&&((Stack)c).cards.size()>0&&((Stack)c).cards.get(((Stack)c).cards.size()-1).getRank()!=selectedCard.getRank()+1)||(((Stack)c).cards.size()==0&&selectedCard.getRank()!=13&&(((Stack)c).rules&DESCENDING)>0))
{
reasonForRejection = "This stack abides by the DESCENDING rule. Cards placed on this pile must have a rank equal to the rank of the card below it, minus one.";
if(printRuleRejections)System.out.println(reasonForRejection);
break;
}
if((((Stack)c).rules&SAME_SUITS)>0&&(((Stack)c).cards.size()>0&&((Stack)c).cards.get(((Stack)c).cards.size()-1).getSuit()!=selectedCard.getSuit()))
{
reasonForRejection = "This stack abides by the SAME_SUITS rule. Cards played on this stack must have the same suit as the card below it.";
if(printRuleRejections)System.out.println(reasonForRejection);
break;
}
if((((Stack)c).rules&ALTERNATING_COLORS)>0&&(((Stack)c).cards.size()>0&&((Stack)c).cards.get(((Stack)c).cards.size()-1).getColor()==selectedCard.getColor()))
{
reasonForRejection = "This stack abides by the ALTERNATING_COLORS rule. Cards played on this stack must have a different color than the card below it.";
if(printRuleRejections)System.out.println(reasonForRejection);
break;
}
if(ruleConstraints!=null)if(ruleConstraints.restrictedTo.size()>0)if((rules&RESTRICTED_STACK)>0&&!ruleConstraints.restrictedTo.contains((Stack)c))
{
reasonForRejection = "The stack you drew this card from abides by the RESTRICTED_STACK rule. The stack you are playing this card on is not contained within the restrictedTo list from the StackRuleConstraints object.";
if(printRuleRejections)System.out.println(reasonForRejection);
break;
}
if(((Stack)c).ruleConstraints!=null)if(((Stack)c).ruleConstraints.restrictedFrom.size()>0)if((((Stack)c).rules&RESTRICTED_STACK)>0&&!((Stack)c).ruleConstraints.restrictedFrom.contains(selfReference))
{
reasonForRejection = "This stack abides by the RESTRICTED_STACK rule. The stack you drew from is not contained within this stack's restrictedFrom list from the StackRuleConstraints object.";
if(printRuleRejections)System.out.println(reasonForRejection);
break;
}
((Stack)c).add(selectedCard);
if(groupedCards!=null)for(Card card: groupedCards)((Stack)c).add(card);
if((((Stack)c).rules&STACK_ACTION)>0&&((Stack)c).ruleConstraints!=null){((Stack)c).ruleConstraints.stackDropAction();}
break ADDING_CARD_TO_STACK;
}
}
if(dragging&&selectedCard!=null){add(selectedCard);if(groupedCards!=null)for(Card card: groupedCards)add(card);}
}
else
{
if((rules&INACCESSIBLE)==0)
{
if((rules&DRAW_PILE)>0&&ruleConstraints!=null)
{
if(ruleConstraints.recyclePile!=null)
{
if(cards.size()==0&&(ruleConstraints.recyclePile.rules&RECYCLABLE)>0)
{
for(int i = ruleConstraints.recyclePile.cards.size()-1; i >= 0; i--)
{
Card c = ruleConstraints.recyclePile.cards.get(i);
c.setSelected(false);
add(c);
}
ruleConstraints.recyclePile.cards.clear();
}
}
else
{
reasonForRejection = "This stack abides by the RECYCLABLE rule, but does not have a recycle pile set up to do that.";
if(printRuleRejections)System.out.println(reasonForRejection);
}
if(ruleConstraints.dropPile!=null)
{
if(cards.size()>0)
{
if(selectedCard!=null)selectedCard.setSelected(true);
else return;
dealTo(selectedCard,ruleConstraints.dropPile,true);
// remove(selectedCard);
// ruleConstraints.dropPile.add(selectedCard);
}
}
else
{
reasonForRejection = "This stack abides by the DROP_PILE rule, but does not have a StackRuleConstraints dropPile set up to do that.";
if(printRuleRejections)System.out.println(reasonForRejection);
}
}
if((rules&STACK_ACTION)>0&&ruleConstraints!=null)ruleConstraints.stackClickAction();
}
else
{
reasonForRejection = "This stack abides by the INACCESSIBLE rule. You cannot manipulate the cards in this stack.";
if(printRuleRejections)System.out.println(reasonForRejection);
}
}
selectedCard = null;
groupedCards = null;
cardsToRemove.clear();
dragging = false;
targetCardTable = (CardTable)SwingUtilities.getAncestorOfClass(CardTable.class,selfReference);
targetCardTable.repaint();
if(!targetCardTable.isGameOver())
{
if(targetCardTable.isGameWon()){targetCardTable.performGameWonAction();targetCardTable.endGame();}
if(targetCardTable.isGameLost()){targetCardTable.performGameLostAction();targetCardTable.endGame();}
}
}
};
这是我的 GoFish 游戏的构造函数。
public GoFish()
{
super("Go Fish");
inquireDialog.setLayout(new GridBagLayout());
JPanel pnl = new JPanel();
pnl.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = gbc.CENTER;
gbc.weightx = 1;
gbc.gridy = 1;
gbc.gridx = 1;
gbc.gridwidth = 2;
gbc.insets = new Insets(10,10,10,10);
pnl.add(spinnerLbl,gbc);
gbc.gridx = 1;
gbc.gridwidth = 1;
gbc.gridy = 2;
gbc.anchor = gbc.EAST;
spinner.setPreferredSize(new Dimension(spinner.getPreferredSize().width+15,spinner.getPreferredSize().height));
tf = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField();
tf.setEditable(false);
tf.addKeyListener(ka);
pnl.add(spinner,gbc);
gbc.gridx = 2;
gbc.anchor = gbc.WEST;
pnl.add(inquireButton,gbc);
inquireButton.addActionListener(this);
inquireDialog.add(pnl);
inquireDialog.setSize(400,150);
WindowPositioner.setLocation(inquireDialog,WindowPositioner.CENTER,false);
inquire.add(inquireLbl);
inquire.addActionListener(this);
ws = getWorkspace();
ws.setLayout(new BorderLayout());
player1PairLbl.setForeground(Color.WHITE);
player2PairLbl.setForeground(Color.WHITE);
player1SidePnl.setLayout(new BorderLayout());
player2SidePnl.setLayout(new BorderLayout());
centerPnl.setLayout(new GridBagLayout());
player2Hand.setStackRules(Stack.INACCESSIBLE);
src = new StackRuleConstraints()
{
public void stackClickAction()
{
// SwingUtilities.invokeLater(new Runnable(){public void run(){
deck.setStackRules(Stack.INACCESSIBLE);
if(player1Hand.cards.get(player1Hand.cards.size()-1).getRankText().equals(inquireText))
{
inquire.setEnabled(true);
player1Hand.setStackRules(player1HandStackRules);
}
else
{
status.setStatus("Player 2's turn.");
JOptionPane.showMessageDialog(null,"Player 2's turn.");
while(true)
{
for(int rank = 1; rank <= 13; rank++)
{
int cardCount = 0;
Card[] pair = new Card[2];
for(Card c: player2Hand.cards)
{
if(c.getRank()==rank)cardCount++;
}
if(cardCount>=2)
{
int i = 0;
for(Card c: player2Hand.cards)
{
if(c.getRank()==rank){pair[i] = c;i++;}
if(i==2){for(Card c2: pair)player2Hand.dealTo(c2,playStack2,true);break;}
}
}
}
if(isGameWon())performGameWonAction();
if(isGameLost())performGameLostAction();
if(isGameWon()||isGameLost())endGame();
if(isGameOver()) return;
//EASY
if(difficultySetting==0)try{
String cardInquiry = player2Hand.cards.get(new Random().nextInt(player2Hand.cards.size())).getRankText();
JOptionPane.showMessageDialog(null,"Player 2 is fishing for "+cardInquiry+(cardInquiry.equals("Six")?"e":"")+"s.");
CHECKING:
{
for(int i = 0; i < player1Hand.cards.size(); i++)
{
if(player1Hand.cards.get(i).getRankText().equals(cardInquiry)){player1Hand.dealTo(player1Hand.cards.get(i),player2Hand,false);break CHECKING;}
}
deck.dealTo(player2Hand,false);
if(!player2Hand.cards.get(player2Hand.cards.size()-1).getRankText().equals(cardInquiry))
{
status.setStatus("Player 1's turn.");
inquire.setEnabled(true);
player1Hand.setStackRules(player1HandStackRules);
JOptionPane.showMessageDialog(null,"Player 1's turn.");
return;
}
}}
catch(IllegalArgumentException e){}
//NORMAL
else if(difficultySetting==1)
{
int player2AskCount=Integer.MAX_VALUE;
int player1AskCount=0;
int player1MaximumCardIndex = -1;
int player2MinimumCardIndex = -1;
for(int i = 1; i <= 13; i++)
{
for(Card c: player2Hand.cards)
{
if(Card.getRankText(i).equals(c.getRankText())&&player1CardTracker[i]>player1AskCount)
{
player1AskCount = player1CardTracker[i];
player1MaximumCardIndex = i;
}
if(Card.getRankText(i).equals(c.getRankText())&&player2CardTracker[i]<player2AskCount)
{
player2AskCount = player2CardTracker[i];
player2MinimumCardIndex = i;
}
}
}
String cardInquiry;
if(player1MaximumCardIndex!=-1)
{
cardInquiry = Card.getRankText(player1MaximumCardIndex);
}
else
{
cardInquiry = Card.getRankText(player2MinimumCardIndex);
player2CardTracker[player2MinimumCardIndex]++;
}
JOptionPane.showMessageDialog(null,"Player 2 is fishing for "+cardInquiry+(cardInquiry.equals("Six")?"e":"")+"s.");
CHECKING:
{
for(int i = 0; i < player1Hand.cards.size(); i++)
{
if(player1Hand.cards.get(i).getRankText().equals(cardInquiry)){player1Hand.dealTo(player1Hand.cards.get(i),player2Hand,false);break CHECKING;}
}
deck.dealTo(player2Hand,false);
if(!player2Hand.cards.get(player2Hand.cards.size()-1).getRankText().equals(cardInquiry))
{
status.setStatus("Player 1's turn.");
inquire.setEnabled(true);
player1Hand.setStackRules(player1HandStackRules);
JOptionPane.showMessageDialog(null,"Player 1's turn.");
return;
}
}
}
}
}
// }});
}
};
src.dropPile = player1Hand;
deckStackRules = deck.getStackRules()|Stack.STACK_ACTION;
deck.setStackRules(Stack.INACCESSIBLE,src);
setMainPile(deck);
src = new StackRuleConstraints()
{
public void stackDropAction()
{
deck.getStackRuleConstraints().stackClickAction();
}
};
player1Hand.setStackRules(0,src);
src = new StackRuleConstraints()
{
@Override
public void stackDropAction()
{
if(playStack1.cards.size()==2)
{
if(playStack1.cards.get(0).getRank()==playStack1.cards.get(1).getRank())
{
addPair(true);
}
else
{
playStack1.dealTo(player1Hand,true);
playStack1.dealTo(player1Hand,true);
}
}
}
};
src.restrictedFrom.add(player1Hand);
playStack1.setStackRules(Stack.STACK_ACTION|Stack.RESTRICTED_STACK,src);
src = new StackRuleConstraints()
{
@Override
public void stackDropAction()
{
if(playStack2.cards.size()==2)
{
if(playStack2.cards.get(0).getRank()==playStack2.cards.get(1).getRank())
{
addPair(false);
}
else
{
playStack2.dealTo(player2Hand,false);
playStack2.dealTo(player2Hand,false);
}
}
}
};
src.restrictedFrom.add(player2Hand);
playStack2.setStackRules(Stack.STACK_ACTION|Stack.RESTRICTED_STACK,src);
player1SidePnl.add(player1PairLbl,BorderLayout.NORTH);
player2SidePnl.add(player2PairLbl,BorderLayout.NORTH);
player1SidePnl.add(player1CardPairs,BorderLayout.CENTER);
player2SidePnl.add(player2CardPairs,BorderLayout.CENTER);
ws.add(player2SidePnl,BorderLayout.WEST);
gbc.weighty = 1;
gbc.anchor = gbc.NORTH;
gbc.insets = new Insets(0,0,10,0);
gbc.gridy = 0;
centerPnl.add(player2Hand,gbc);
gbc.anchor = gbc.CENTER;
gbc.gridy = 1;
centerPnl.add(playStack2,gbc);
gbc.gridy = 2;
centerPnl.add(deck,gbc);
gbc.gridy = 3;
centerPnl.add(playStack1,gbc);
gbc.anchor = gbc.SOUTH;
gbc.gridy = 4;
centerPnl.add(player1Hand,gbc);
ws.add(centerPnl,BorderLayout.CENTER);
ws.add(player1SidePnl,BorderLayout.EAST);
getContentPane().add(status,BorderLayout.SOUTH);
status.add(inquire,BorderLayout.EAST);
player1HandStackRules = player1Hand.getStackRules();
setVisible(true);
init();
}
您可以在此处查看完整代码:www.github.com/mfgravesjr 查看名为 projects-in-progress 的存储库。