Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java代码-纸牌_Java_Swing_Drawing - Fatal编程技术网

Java代码-纸牌

Java代码-纸牌,java,swing,drawing,Java,Swing,Drawing,我用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(

我用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);
      }
  }
}

我拿了你的片段,自己做了一个片段。该代码片段仅使用
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);
            }
        });
    }
}
结果:


我的一些建议从以下内容中删除:

  • 首先,没有所谓的“静态构造函数”,静态初始值设定项块,是的,但它们并不像构造函数那样以类名开头,因此看起来不像构造函数,更重要的是,它们不像构造函数那样行为,它们不创建类的实例。相反,它们用于类加载时调用的特定于类(而不是特定于实例)的代码
  • 我自己,我会在GUI卡创建上创建我的卡特定实例,因此我认为无论您在哪里创建卡的GUI表示,这些代码都应该放在构造函数中。请注意,这可能(并且应该)与您创建的逻辑卡分开,尽管我在下面的示例中没有这样做
  • 由于卡备份映像是特定于类的,而不是特定于卡实例的,因此我将在静态初始值设定项块中创建卡备份映像,或者将其作为一个实例创建。这样,它应该一次创建一次。在下面的示例中,我使用单例模式(有人说是“反”模式)。在Swing GUI中使用它应该是安全的,因为Swing是单线程的,所以只能在一个线程中调用它
  • 正如我在您的原始问题中的评论,您的代码目前做的最慢的事情是重复读取图像文件,您希望通过将图像存储在变量中,然后根据需要使用它们来避免这样做,如下例所示
  • 一个侧面建议(与你原来的问题无关):考虑使用渲染提示来平滑你可能正在做的任何文本或图形的绘制。例如,请参见下面的代码
  • 也可以为你的卡等级和套装使用枚举。这是讨论枚举主题时使用的规范示例,正如您将在下面看到的,它们非常适合使用枚举
  • 你的代码使用了很多“神奇”数字,换句话说,很多无法解释的数字文字,比如
    g.drawString(club,x+12,y+45)。所以有人只要看一下你的代码就会想,12和45代表什么?最好通过使用带有逻辑名称的变量或常量来避免这种情况,从而使代码更具自注释性。例如,类似于:
    g2.drawString(s.getSymbol(),SYMBOL_X,SYMBOL_Y)您可以猜测符号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;
    }

}
import java.awt.BasicStroke;
导入java.awt.Font;
导入java.awt.Graphics2D;
导入java.awt.GridLayout;
导入java.awt.RenderingHints;
导入java.awt.TexturePaint;
导入java.awt.event.*;
导入java.awt.geom.Rectangle2D;
导入java.awt.image.buffereImage;
导入java.awt.Color;
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.List;
导入javax.swing.*;
/**
* 
*@author@fullofeels
*链接:https://stackoverflow.com/a/35351199/522444
*
*/    
公共类播放卡示例{
私有静态void createAndShowGui(){
PlayingCardPanel主面板=新的PlayingCardPanel();
JFrame=新JFrame(“扑克牌示例”);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(主面板);
frame.pack();
frame.setLocationByPlatform(真);
frame.setVisible(true);
}
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(()->{
createAndShowGui();
});
}
}
@抑制警告(“串行”)
类播放CardPanel扩展JPanel{
私有静态最终颜色BG=Color.GREEN.darker().darker();
专用静态最终内部间隙=15;
私有MyDeck MyDeck=新MyDeck();
公共播放CardPanel(){
退避地(BG);
int rows=Suit.values().length;
int cols=Rank.values().length;
setLayout(新网格布局(行、列、间隙、间隙));
setBorder(BorderFactory.createEmptyByOrder(间隙,间隙,间隙));
而(myDeck.size()>0){
Card myCard=myDeck.deal();
最终CardLabel CardLabel=新的CardLabel(myCard);
添加(cardLabel.getLabel());
addMouseListener(新的CardListener(cardLabel));
}
}
}
//类以允许我们在鼠标按下时翻转卡片
类CardListener扩展了MouseAdapter{
私人信用卡标签;
公共CardListener(CardLabel CardLabel){
this.cardLabel=cardLabel;
}
@凌驾
公共无效鼠标按下(MouseEvent e){
布尔faceDown=!cardLabel.isFaceDown();
cardLabel.setFaceDown(面朝下);
}
}
类别卡片标签{
专用JLabel标签=新JLabel();
私人卡我的卡;
private boolean faceDown=true;
公共卡标签(卡myCard){
this.myCard=myCard;
setFaceDown(真);
}
public void addMouseStener(MouseStener侦听器){
label.addMouseListener(侦听器);
}
公共布尔值isFaceDown(){
正面朝下返回;
}
公共void setFaceDown(布尔值faceDown){
this.faceDown=faceDown;
//获取我的单身图标:
Icon cardBackIcon=CardBack.getInstance().getIcon();
Icon-Icon=faceDown?cardBackIcon:myCard.getIcon();
label.setIcon(图标);
}
公共JLabel getLabel(){
退货标签;
}
公共卡getMyCard(){
返回m