我用Java创建了一个单人纸牌游戏。
我的问题是:如何在每张黑色或红色卡片上填充物体(心形,黑桃,钻石,球杆)?
以下是我现在的代码:
// draw the card
public void draw (Graphics g, int x, int y) {
// clear rectangle, draw border
g.clearRect(x, y, width, height);
g.setColor(Color.black);
g.drawRect(x, y, width, height);
// draw body of card
if (faceUp())
{
if (color() == red)
g.setColor(Color.red);
else
g.setColor(Color.black);
g.drawString(names[rank()], x+3, y+15);
if (suit() == heart)
{
g.drawLine(x+25, y+30, x+35, y+20);
g.drawLine(x+35, y+20, x+45, y+30);
g.drawLine(x+45, y+30, x+25, y+60);
g.drawLine(x+25, y+60, x+5, y+30);
g.drawLine(x+5, y+30, x+15, y+20);
g.drawLine(x+15, y+20, x+25, y+30);
// g.fill(Color.red);
}
else if (suit() == spade)
{
g.drawLine(x+25, y+20, x+40, y+50);
g.drawLine(x+40, y+50, x+10, y+50);
g.drawLine(x+10, y+50, x+25, y+20);
g.drawLine(x+23, y+45, x+20, y+60);
g.drawLine(x+20, y+60, x+30, y+60);
g.drawLine(x+30, y+60, x+27, y+45);
}
else if (suit() == diamond)
{
g.drawLine(x+25, y+20, x+40, y+40);
g.drawLine(x+40, y+40, x+25, y+60);
g.drawLine(x+25, y+60, x+10, y+40);
g.drawLine(x+10, y+40, x+25, y+20);
}
else if (suit() == club)
{
g.drawOval(x+20, y+25, 10, 10);
g.drawOval(x+25, y+35, 10, 10);
g.drawOval(x+15, y+35, 10, 10);
g.drawLine(x+23, y+45, x+20, y+55);
g.drawLine(x+20, y+55, x+30, y+55);
g.drawLine(x+30, y+55, x+27, y+45);
}
}
else // face down
{
g.setColor(Color.black);
g.drawLine(x+15, y+5, x+15, y+65);
g.drawLine(x+35, y+5, x+35, y+65);
g.drawLine(x+5, y+20, x+45, y+20);
g.drawLine(x+5, y+35, x+45, y+35);
g.drawLine(x+5, y+50, x+45, y+50);
}
}
}
答案 0 :(得分:3)
我拿了你的片段,并制作了我自己的片段。该片段仅使用Graphics.fillPolygon
填充心脏套装。我已经注释掉了片段中的旧线条,因此您可以将其与您所做的相比较。其他卡片我会留给你。
import java.awt.*;
import javax.swing.*;
public class CardFrame {
enum CardColor{red,black};
enum CardSuit{heart,diamond,spade,club}
public static void main( String[] args )
{
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JPanel cardDisplay = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(50,100);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g,0,0);
}
private int width = 50;
private int height = 80;
private boolean faceUp() {
return true;
}
private CardColor color() {
return CardColor.red;
}
private CardSuit suit() {
return CardSuit.heart;
}
private int rank() {
return 0;
}
private String[] names = {"1","2","3","4","5","6","7","8","9","10","J","Q","K","A"};
private void draw(Graphics g, int x, int y) {
// clear rectangle, draw border
g.clearRect(x, y, width, height);
g.setColor(Color.black);
g.drawRect(x, y, width, height);
// draw body of card
if (faceUp()) {
if (color() == CardColor.red)
g.setColor(Color.red);
else
g.setColor(Color.black);
g.drawString(names[rank()], x + 3, y + 15);
if (suit() == CardSuit.heart) {
// g.drawLine(x + 25, y + 30, x + 35, y + 20);
// g.drawLine(x + 35, y + 20, x + 45, y + 30);
// g.drawLine(x + 45, y + 30, x + 25, y + 60);
// g.drawLine(x + 25, y + 60, x + 5, y + 30);
// g.drawLine(x + 5, y + 30, x + 15, y + 20);
// g.drawLine(x + 15, y + 20, x + 25, y + 30);
int[] xPoints = new int[]{x + 5,x + 15,x + 25,x + 35,x + 45,x + 25};
int[] yPoints = new int[]{y + 30,y + 20,y + 30,y + 20,y + 30,y + 60};
g.fillPolygon(xPoints, yPoints, 6);
} else if (suit() == CardSuit.spade) {
// ...
} else if (suit() == CardSuit.diamond) {
// ...
} else if (suit() == CardSuit.club) {
//
}
} else // face down
{
// ...
}
}
};
JFrame frm = new JFrame();
frm.setContentPane(cardDisplay);
frm.pack();
frm.setVisible(true);
}
});
}
}
结果:
答案 1 :(得分:0)
我从your recent question中删除了一些答案中的一些建议:
g.drawString(club, x + 12, y + 45);
。所以有人只是想看看你的代码会想知道,12和45代表什么?最好通过使用带有逻辑名称的变量或常量来避免这种情况,以使代码更具自我评论性。例如:g2.drawString(s.getSymbol(), SYMBOL_X, SYMBOL_Y);
,您可以猜到SYMBOL_X是符号的x位置。例如,请查看此代码,该代码可以复制到单个文件中并运行:
import java.awt.BasicStroke;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.TexturePaint;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.*;
/**
*
* @author Hovercraftfullofeels
* link: https://stackoverflow.com/a/35351199/522444
*
*/
public class PlayingCardExample {
private static void createAndShowGui() {
PlayingCardPanel mainPanel = new PlayingCardPanel();
JFrame frame = new JFrame("Playing Card Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}
@SuppressWarnings("serial")
class PlayingCardPanel extends JPanel {
private static final Color BG = Color.GREEN.darker().darker();
private static final int GAP = 15;
private MyDeck myDeck = new MyDeck();
public PlayingCardPanel() {
setBackground(BG);
int rows = Suit.values().length;
int cols = Rank.values().length;
setLayout(new GridLayout(rows, cols, GAP, GAP));
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
while (myDeck.size() > 0) {
Card myCard = myDeck.deal();
final CardLabel cardLabel = new CardLabel(myCard);
add(cardLabel.getLabel());
cardLabel.addMouseListener(new CardListener(cardLabel));
}
}
}
// class to allow us to flip cards on mouse press
class CardListener extends MouseAdapter {
private CardLabel cardLabel;
public CardListener(CardLabel cardLabel) {
this.cardLabel = cardLabel;
}
@Override
public void mousePressed(MouseEvent e) {
boolean faceDown = ! cardLabel.isFaceDown();
cardLabel.setFaceDown(faceDown);
}
}
class CardLabel {
private JLabel label = new JLabel();
private Card myCard;
private boolean faceDown = true;
public CardLabel(Card myCard) {
this.myCard = myCard;
setFaceDown(true);
}
public void addMouseListener(MouseListener listener) {
label.addMouseListener(listener);
}
public boolean isFaceDown() {
return faceDown;
}
public void setFaceDown(boolean faceDown) {
this.faceDown = faceDown;
// get my singleton icon:
Icon cardBackIcon = CardBack.getInstance().getIcon();
Icon icon = faceDown ? cardBackIcon : myCard.getIcon();
label.setIcon(icon);
}
public JLabel getLabel() {
return label;
}
public Card getMyCard() {
return myCard;
}
}
// singleton class to create the backing image shared by all cards
class CardBack {
private static final Color BG = Color.WHITE;
private static final Color COLOR = Color.BLUE;
private static final int W = 10;
private static final float STROKE_WIDTH = 3f;
private static CardBack instance = null;
private BufferedImage image;
private Icon icon;
// singleton constructor is private and so is only called by this class itself
private CardBack() {
BufferedImage repeatImg = new BufferedImage(W, W, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = repeatImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setBackground(BG);
g2.clearRect(0, 0, W, W);
g2.setStroke(new BasicStroke(STROKE_WIDTH));
g2.setColor(COLOR);
g2.drawLine(0, 0, W, W);
g2.drawLine(0, W, W, 0);
g2.dispose();
int width = Card.WIDTH;
int height = Card.HEIGHT;
int imageType = BufferedImage.TYPE_INT_ARGB;
image = new BufferedImage(width, height, imageType);
g2 = image.createGraphics();
Rectangle2D anchor = new Rectangle2D.Double(0, 0, W, W);
TexturePaint texturePaint = new TexturePaint(repeatImg, anchor);
g2.setPaint(texturePaint);
g2.fillRect(0, 0, width, height);
g2.dispose();
icon = new ImageIcon(image);
}
public BufferedImage getImage() {
return image;
}
public Icon getIcon() {
return icon;
}
public static CardBack getInstance() {
// create the instance in a lazy fashion -- only create it if it has not
// yet been created. Thus, it should only be created *once*
if (instance == null) {
instance = new CardBack();
}
return instance;
}
}
class MyDeck {
List<Card> cards = new ArrayList<>();
public MyDeck() {
initialize();
shuffle();
}
public final void initialize() {
cards.clear();
for (Rank rank : Rank.values()) {
for (Suit suit : Suit.values()) {
cards.add(new Card(rank, suit));
}
}
}
public int size() {
return cards.size();
}
public Card deal() {
if (cards.size() > 0) {
return cards.remove(0);
} else {
// TODO: better to use exceptions here!
// String text = "cards size is " + cards.size();
// throw new MyDeckException(text);
return null;
}
}
public void shuffle() {
Collections.shuffle(cards);
}
}
// Quick an dirty code below. If this were a "real" program,
// I'd probably create a class without image or icon
// and then use a wrapper or decorator class to add the image information
// since this would be GUI library specific
class Card {
public static final int WIDTH = 50;
public static final int HEIGHT = 70;
private static final Font TEXT_FONT = new Font(Font.DIALOG, Font.BOLD, 14);
private static final Font SYMBOL_FONT = TEXT_FONT.deriveFont(Font.PLAIN, 28f);
private static final int NAME_X = 3;
private static final int NAME_Y = 15;
private static final int SYMBOL_X = 12;
private static final int SYMBOL_Y = 45;
private Rank rank;
private Suit suit;
private BufferedImage image;
private Icon icon;
public Card(Rank rank, Suit suit) {
this.rank = rank;
this.suit = suit;
// create each card's image and icon once on Card creation
image = createImage(rank, suit);
icon = new ImageIcon(image);
}
private static BufferedImage createImage(Rank r, Suit s) {
BufferedImage img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2.setColor(java.awt.Color.WHITE);
g2.fillRect(0, 0, WIDTH, HEIGHT);
g2.setColor(java.awt.Color.BLACK);
g2.drawRect(0, 0, WIDTH - 1, HEIGHT - 1);
g2.setColor(s.getColor());
g2.setFont(TEXT_FONT);
g2.drawString(r.getName(), NAME_X, NAME_Y);
g2.setFont(SYMBOL_FONT);
g2.drawString(s.getSymbol(), SYMBOL_X, SYMBOL_Y);
g2.dispose();
return img;
}
public Rank getRank() {
return rank;
}
public Suit getSuit() {
return suit;
}
public BufferedImage getImage() {
return image;
}
public Icon getIcon() {
return icon;
}
}
enum Rank {
ACE("A"), TWO("2"), THREE("3"), FOUR("4"), FIVE("5"), SIX("6"), SEVEN("7"), EIGHT("8"),
NINE("9"), TEN("10"), JACK("J"), QUEEN("Q"), KING("K");
private String name;
private Rank(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// Suit enum will hold its own color and symbol
enum Suit {
CLUB("Club", "\u2663", Color.BLACK),
DIAMOND("Diamond", "\u2666", Color.RED),
HEART("Heart", "\u2665", Color.RED),
SPADE("Spade", "\u2660", Color.BLACK);
private String name;
private String symbol;
private Color color;
private Suit(String name, String symbol, Color color) {
this.name = name;
this.symbol = symbol;
this.color = color;
}
public String getName() {
return name;
}
public String getSymbol() {
return symbol;
}
public Color getColor() {
return color;
}
}