我正在用java创建一个程序来模拟一副基本卡片;没有特定的游戏,只是一个很好的老牌卡,你可以自由移动和翻转(当然,限制总共52张卡)。这是我目前的代码:
package cards;
import java.awt.Color;
import java.awt.Graphics;
import java.util.List;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
public class DeckOfCards extends JPanel{
/**
*
*/
private static final long serialVersionUID = 1L;
static final int SIZE = 500;
public static String side = "back";
static final int xSize = 73;
static final int ySize = 98;
static int x = SIZE - xSize;
static int y = 0;
static int i, j = 0;
static int inDeck = 52;
public boolean flipped = false;
static final DeckOfCards m = new DeckOfCards();
static final Color rgb = new Color(0, 180, 10);
static final JFrame frame = new JFrame();
static List<Integer> yList = new ArrayList<Integer>();
static List<Integer> xList = new ArrayList<Integer>();
Random random = new Random();
int randX = random.nextInt(13) * xSize;
int randY = random.nextInt(4) * ySize;
int xRand = randX;
int yRand = randY;
public static void main(String[] args){
frame.setTitle("Virtual Cards");
frame.add(m);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(SIZE, SIZE);
frame.setResizable(false);
m.setBackground(rgb);
frame.setVisible(true);
}
public void mouseClick(){
addMouseListener(new MouseAdapter(){
@Override
public void mouseClicked(MouseEvent e){
if(((e.getX() >= x && e.getX() <= (x + xSize)) && (e.getY() >= y && e.getY() <= (y + ySize))) && (flipped == false)){
flipped = true;
side = "front";
}else if(((e.getX() >= x && e.getX() <= (x + xSize)) && (e.getY() >= y && e.getY() <= (y + ySize))) && (flipped == true)){
flipped = false;
side = "back";
}else if((e.getX() >= SIZE - xSize && e.getX() <= SIZE) && (e.getY() >= 0 && e.getY() <= SIZE - (SIZE - ySize)) && inDeck > 0){
randCardFace(random);
inDeck--;
side = "back";
x = SIZE - xSize;
y = 0;
}
}
});
}
public void mouseMove(){
addMouseMotionListener(new MouseMotionAdapter(){
@Override
public void mouseDragged(MouseEvent e){
if(((e.getX() >= x && e.getX() <= (x + xSize)) && (e.getY() >= y && e.getY() <= (y + ySize)))){
x = e.getX() - (xSize / 2);
y = e.getY() - (ySize / 2);
}
}
});
}
public DeckOfCards(){
mouseClick();
mouseMove();
}
public void randCardFace(Random random){
randX = random.nextInt(13) * xSize;
randY = random.nextInt(4) * ySize;
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
paint(g);
}
public void paint(Graphics g){
try{
if(inDeck > 0){
g.drawImage(ImageIO.read(getClass().getResource("images/deck.png")), SIZE - xSize, 0, null, null);
}
BufferedImage image = ImageIO.read(getClass().getResource("images/"+side+".png"));
if(side != "back"){
image = image.getSubimage(randX, randY, xSize, ySize);
}
g.drawImage(image, x, y, xSize, ySize, null, null);
}catch(IOException e){
e.printStackTrace();
}
m.repaint();
}
}
然而,这个程序只允许我一次输出一张卡,直到我点击右上角的牌组并重新洗牌(用随机数发生器重新定义要读取的图像区域)。我想做的是能够在任何给定时间通过点击牌组获得0和52的任意数量的牌而不为其他牌创建51个新变量(我已经写了一些代码用于我的内容)我希望,但到目前为止,除了导致问题之外什么也没做,所以我决定从头开始并向专家询问我应该做些什么。
编辑:
在问到这个之后才意识到,这是一个比我想要发布的稍微旧的代码,并且可能还有很多其他问题。请忽略它们,因为它们已经修复。
答案 0 :(得分:3)
你发布了很多问题的代码,请允许我给你一些建议。如果它不是正确的代码,请更正:
repaint()
。链接到有关纸牌游戏的其他一些答案和代码:
答案 1 :(得分:2)
有两种基本方法,两种方法都遵循相同的基本概念......
生成图像列表并绘制它们......
创建一个自定义组件,专门负责绘制单张卡片。这样做的好处是,它通常易于管理和使用已有的功能。
缺点是,您需要负责布局管理(稍微)。
您可以从LayredPane
开始,这样您就可以上下推动卡片(虚拟地),并允许它们放置在您想要的位置。
就个人而言,我会创建一个MouseListener
/ MouseMotionListener
并将其注册到每个“卡片面板”,这样可以轻松控制与LayeredPane
相关的卡片。 (例如,当点击它们时将它们移动到顶部)
另一种选择是加载每张卡片图像并将它们放入List
。然后基本上,你只需在paintComponent
方法中通过简单地遍历列表来绘制它们。
问题是,您突然负责z顺序的整个管理并检查点击的内容。
自定义图像的绘制(例如添加边框)变得有点麻烦,因为您需要为每个图像执行此操作并确定何时。如果它们是自定义组件,这将更容易
static
变量,这可能很快导致您进入问题区域并试图确定实际被引用的内容paint
致电paintComponent
。 paint
实际上调用了paintComponent
本身,这可能会产生堆栈溢出错误paintXxx
的{{1}}方法中调用任何方法,因为绘画的工作方式,这只会让EDT简单地继续绘制您的组件,这最终会消耗你的CPU ...... 详细了解Performing Custom Painting和Painting in AWT and Swing了解详情