我只是想构建一个带有瓷砖的游戏板。我通过使用BufferedImage将图块绘制成行和列来实现它,但是我将需要在游戏播放时不断更新GUI。
所以我尝试将图块图像添加到ImageIcon,然后添加到JLabel数组,以便我可以设置位置。之后我会将标签添加到gui JPanel,但是它们之间有这些默认的间隙。
我接近这个错误吗?我是Swing和Java的新手
public static void main (String[] args) throws IOException{
int NUMROWS = 10;
int NUMCOLS = 10;
int NUMMINES = 10;
int[] mineList = GameBoard.setMines(NUMMINES, NUMROWS, NUMCOLS);
int[][] cellNums = GameBoard.setCellNum(NUMROWS, NUMCOLS);
boolean[][] mineField = GameBoard.getMineField(mineList, cellNums);
int[][] adjacentMineVals = GameBoard.getAdjacentMineVals(cellNums, mineField);
ImageIcon img = new ImageIcon(ImageIO.read(new File("GraphicFile\\Cell.png")));
JLabel[][] label = new JLabel[NUMROWS][NUMCOLS];
for (int i = 0; i < NUMROWS; i++){
for (int j = 0; j < NUMCOLS; j++){
label[i][j] = new JLabel();
label[i][j].setIcon(img);
label[i][j].setLocation(i*img.getIconHeight(), j*img.getIconWidth());
}
}
JFrame frame = buildFrame();
int fX = 2*frame.getInsets().left;
int fY = (frame.getInsets().top + frame.getInsets().bottom);
JPanel GUI = new JPanel();
GUI.setSize(NUMCOLS*img.getIconWidth(), NUMROWS*img.getIconHeight());
for (int i = 0; i < NUMCOLS; i++){
for (int j = 0; j < NUMROWS; j ++){
GUI.add(label[i][j]);
}
}
frame.setSize(NUMCOLS*img.getIconWidth() + fX, NUMROWS*img.getIconHeight() + fY);
frame.add(GUI);
}
public static JFrame buildFrame(){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
return frame;
}
这是它给我的东西 https://i.stack.imgur.com/rX3yM.png
更新到新版本。通过使用网格并将图像作为图标放入按钮
,解决了以前的问题这就是我所拥有的。它不会将带有文本的标签放在已按下的按钮上。我调试了它,它的接收输入用于coords和text,但它只是没有将它绘制到面板上
public MinesweeperGraphics() throws IOException {
GUI.setOpaque(false);
for (int i = 0; i < NUMROWS; i++){
for (int j = 0; j < NUMCOLS; j++){
buttons[i][j] = new JButton();
buttons[i][j].setIcon(tileUp);
buttons[i][j].setBorder(null);
buttons[i][j].addActionListener(this);
buttons[i][j].setPressedIcon(tilePressed);
GUI.add(buttons[i][j]);
}
}
frame.add(GUI, BorderLayout.CENTER);
frame.add(reset, BorderLayout.NORTH);
reset.addActionListener(this);
frame.setResizable(false);
frame.pack();
GUI.setLayout(null);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(reset)){
for (int i = 0; i < NUMROWS; i++){
for (int j = 0; j < NUMCOLS; j++){
buttons[i][j].setIcon(tileUp);
}
}
}else {
for (int i = 0; i < buttons.length; i++) {
for (int j = 0; j < buttons.length; j++) {
if (e.getSource().equals(buttons[i][j])){
if (mineField[i][j] == false){
buttons[i][j].setIcon(tileEmpty);
numberText.setOpaque(false);
numberText.setSize(buttons[i][j].getWidth(), buttons[i][j].getHeight());
numberText.setText("a");
numberText.setLocation(buttons[i][j].getLocation());
GUI.add(numberText);
} else if (mineField[i][j] == true){
buttons[i][j].setIcon(tileExplodedMine);
}
//isn't working here
buttons[i][j].setEnabled(false);
}
}
}
}
}
答案 0 :(得分:1)
构建Mine Sweeper游戏的最佳方法是将带有动作侦听器的按钮放入网格布局中。按钮将响应键盘和鼠标输入&amp;可以显示图标。网格布局可以在屏幕上组织它们。
以下是GridLayout
中的按钮MCVE。与上述不同的是它:
MineFieldModel
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class MineSweeper {
private JComponent ui = null;
private MineFieldModel mineFieldModel;
Color[] colors = {
Color.BLUE,
Color.CYAN.darker(),
Color.GREEN.darker(),
Color.YELLOW.darker(),
Color.ORANGE.darker(),
Color.PINK.darker(),
Color.MAGENTA,
Color.RED
};
public final static String BOMB = new String(Character.toChars(128163));
JButton[][] buttons;
int size = 16;
MineSweeper() {
initUI();
}
public final void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
mineFieldModel = new MineFieldModel(16, 40);
JPanel mineFieldContainer = new JPanel(new GridLayout(
size, size));
ui.add(mineFieldContainer, BorderLayout.CENTER);
int in = 5;
Insets insets = new Insets(in, in, in, in);
Font f = getCompatibleFonts().firstElement().deriveFont(16f);
buttons = new JButton[size][size];
for (int ii = 0; ii < size; ii++) {
for (int jj = 0; jj < size; jj++) {
JButton b = new JButton();
b.setMargin(insets);
b.setFont(f);
b.setText("?");
if (mineFieldModel.isExposed(ii, jj)) {
if (mineFieldModel.isBomb(ii, jj)) {
b.setForeground(Color.red);
b.setForeground(Color.BLACK);
b.setText(BOMB);
} else if (mineFieldModel.countSurroundingMines(ii, jj) > 0) {
int count = mineFieldModel.countSurroundingMines(ii, jj);
if (count > 0) {
b.setForeground(colors[count - 1]);
b.setText("" + count);
}
} else {
b.setText("");
}
}
mineFieldContainer.add(b);
}
}
}
private static Vector<Font> getCompatibleFonts() {
Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
Vector<Font> fontVector = new Vector<>();
for (Font font : fonts) {
if (font.canDisplayUpTo("12345678" + BOMB) < 0) {
fontVector.add(font);
}
}
return fontVector;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
MineSweeper o = new MineSweeper();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}
class MineFieldModel {
public int size;
/**
* Records bomb locations.
*/
boolean[][] mineField;
/**
* Records whether this location has been exposed.
*/
boolean[][] fieldPlaceExposed;
int numberMines;
Random r = new Random();
MineFieldModel(int size, int numberMines) {
this.size = size;
this.numberMines = numberMines;
mineField = new boolean[size][size];
fieldPlaceExposed = new boolean[size][size];
ArrayList<Point> locations = new ArrayList<>();
for (int ii = 0; ii < this.size; ii++) {
for (int jj = 0; jj < size; jj++) {
mineField[ii][jj] = false;
// must change this to false for the actual game.
fieldPlaceExposed[ii][jj] = true;
Point p = new Point(ii, jj);
locations.add(p);
}
}
Collections.shuffle(locations, r);
for (int ii = 0; ii < numberMines; ii++) {
Point p = locations.get(ii);
mineField[p.x][p.y] = true;
}
}
public boolean isBomb(int x, int y) {
return mineField[x][y];
}
public boolean isExposed(int x, int y) {
return fieldPlaceExposed[x][y];
}
public int getSize() {
return size;
}
public int countSurroundingMines(int x, int y) {
int lowX = x - 1;
lowX = lowX < 0 ? 0 : lowX;
int highX = x + 2;
highX = highX > size ? size : highX;
int lowY = y - 1;
lowY = lowY < 0 ? 0 : lowY;
int highY = y + 2;
highY = highY > size ? size : highY;
int count = 0;
for (int ii = lowX; ii < highX; ii++) {
for (int jj = lowY; jj < highY; jj++) {
if (ii != x || jj != y) {
if (mineField[ii][jj]) {
count++;
}
}
}
}
return count;
}
}