2

I'm working on creating a simple mine sweeper game in java using JButtons. So far I have a code that creates a 20x20 grid of JButtons, but I am unsure of how I can get my bombs randomly assigned to multimple JButtons durring the game.

Here is what I have written so far:

MineSweeper Class:

import javax.swing.*;
import java.awt.GridLayout;
public class MineSweeper extends JFrame {
JPanel p = new JPanel();
bombButton points[][]= new bombButton[20][20];

public static void main(String args[]){
    new MineSweeper();
}

public MineSweeper(){
    super("Mine Sweeper Version: Beta");
    setSize(400,400);
    setResizable(false);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    p.setLayout(new GridLayout(20,20));
    int y=0;
    int counter=0;
    while(counter<20){   
        for(int x=0;x<20;x++){
            points[x][y] = new bombButton();
            p.add(points[x][y]);
        }
        y++;
        counter++;
    }
    add(p);

    setVisible(true);
}
}

bombButton Class:

import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.net.URL;

public class bombButton extends JButton implements ActionListener {
ImageIcon Bomb,zero,one,two,three,four,five,six,seven,eight;

public bombButton(){
    URL imageBomb = getClass().getResource("Bomb.png");
    Bomb= new ImageIcon(imageBomb);

    URL imageZero = getClass().getResource("0.jpg");
    zero= new ImageIcon(imageZero);

    URL imageOne = getClass().getResource("1.jpg");
    one= new ImageIcon(imageOne);

    URL imageTwo = getClass().getResource("2.jpg");
    two= new ImageIcon(imageTwo);

    URL imageThree = getClass().getResource("3.jpg");
    three= new ImageIcon(imageThree);

    URL imageFour = getClass().getResource("4.jpg");
    four= new ImageIcon(imageFour);

    URL imageFive = getClass().getResource("5.jpg");
    five= new ImageIcon(imageFive);

    URL imageSix = getClass().getResource("6.jpg");
    six= new ImageIcon(imageSix);

    URL imageSeven = getClass().getResource("7.jpg");
    seven= new ImageIcon(imageSeven);

    URL imageEight = getClass().getResource("8.jpg");
    eight= new ImageIcon(imageEight);

    this.addActionListener(this);
}

public void actionPerformed(ActionEvent e){
    switch(){
        case 0:
            setIcon(null);
            break;
        case 1:
            setIcon(Bomb);
            break;
        case 2:
            setIcon(one);
            break;
        case 3:
            setIcon(two);
            break;
        case 4:
            setIcon(three);
            break;
        case 5:
            setIcon(four);
            break;
        case 6:
            setIcon(five);
            break;
        case 7:
            setIcon(six);
            break;
        case 8:
            setIcon(seven);
            break;    
        case 9:
            setIcon(eight);
            break;    
    }
}

int randomWithRange(int min, int max)
{
    int range = Math.abs(max - min) + 1;     
    return (int)(Math.random() * range) + (min <= max ? min : max);
}
}

As you can see I already have a randomizer set up, I just don't know how I should implement it. Should I use (X,Y) cordinates? How do I assign my bombs to random JButtons?

Thnak you to all in advance!

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
MooseMan55
  • 524
  • 2
  • 6
  • 21

2 Answers2

4

Create an ArrayList<JButton>, fill it with all your buttons, call Collections.shuffle(..) on the list, and then select the first N buttons to add mines to.

Having said this, my real recommendation is to chuck all this and go the MVC route where your data model, including where the mines are located, and your GUI are completely distinct.

here are some of my prior musings on this problem from 2011.

Community
  • 1
  • 1
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • 1
    Unfortunatly I am fairly new to Java, so I don't know what a MVC is. Could you elaborate? – MooseMan55 Jul 05 '15 at 01:16
  • 4
    @MooseMan55: MVC stands for Model-View-Control, and is a design pattern used to help separate your program logic from its display. Doing this or something like this can allow you to greatly reduce the cyclomatic complexity of your program, making it **much** easier to debug and enhance. – Hovercraft Full Of Eels Jul 05 '15 at 01:18
  • 1
    Oh okay, thanks! Is it relativly easy to learn how to use MVC? – MooseMan55 Jul 05 '15 at 01:54
1

here are my Miseweeper Clone

    package MWeeper;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

public class MMWeeper extends JFrame implements Runnable {

    private JFrame  mainFrame ;
    private JPanel  mainPanel;
    
    private int boardX  = 15;
    private int boardY  = 15;
    private int bombs   = 35;
    
    private int bombsMarked;
    private int cleanFields;
    private int seconds;
    
    private boolean gameOver = false;
    
    private Map<Integer, Map<Integer, mweeperField>> boardMap;
    private Map<Integer,position> bombMap;
    private JPanel boardPanel;
    private JPanel headPanel;
    private JTextField bombsField;
    
    @Override
    public void run() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                mainFrame = new JFrame("MMWEEEEEEPER");
                
                int w = Toolkit.getDefaultToolkit().getScreenSize().width;
                int h = Toolkit.getDefaultToolkit().getScreenSize().height;
                mainFrame.setPreferredSize(new Dimension(350,390));
                mainFrame.setResizable(true);
                
                mainPanel = new JPanel(new BorderLayout());
                
                init();
                //setContent();
                setPanel();
                
                mainFrame.add(mainPanel);
                mainFrame.setContentPane(mainFrame.getContentPane());
                mainFrame.pack();
                mainFrame.setLocationRelativeTo(null);
                mainFrame.setVisible(true);
                
                
            }
            });
    }
    
    private void init() {
        bombMap     = new HashMap<Integer, MMWeeper.position>();
        boardMap    = new HashMap<Integer, Map<Integer,mweeperField>>();
        bombsMarked = 0;
        cleanFields = (boardX * boardY) - bombs;
        seconds     = 0;
        
        for(int i = 1; i<= boardX; i++) {
            boardMap.put(i, new HashMap<Integer, mweeperField>());
            for(int j = 1; j <= boardY; j++) {
                boardMap.get(i).put(j, new mweeperField(i, j ));
            }
        }
        placeBombs();
    }
    
    
    private boolean placeBombs() {
        
        Random pX = new Random();
        Random pY = new Random();
        int bombCount = 0;
        //while( bombMap.size() < bombs ) {
        while(bombCount < bombs) {
            int x = (1 + pX.nextInt( boardX ) );
            int y = (1 + pY.nextInt( boardY ) );
            if(!boardMap.get(x).get(y).isBomb() ) {
                boardMap.get(x).get(y).setBomb();
                bombCount++;
                bombMap.put(bombCount, new position(x, y));
            }
        }
        return true;
    }
    
    private void setPanel() {
        
        mainPanel.add(head(), BorderLayout.PAGE_START);
        
        mainPanel.add(board(), BorderLayout.CENTER);
    }
    
    
    private JPanel head() {
        headPanel = new JPanel(new BorderLayout());
        
        bombsField = new JTextField(6);
        bombsField.setEditable(true);
        bombsField.setText( String.valueOf(bombs));
        
        JButton start = new JButton("Start");
        start.addActionListener( new mweeperAction(GameActions.START) );
        
        
        
        headPanel.add(bombsField, BorderLayout.LINE_START);
        
        headPanel.add(start, BorderLayout.LINE_END);
        return headPanel;
    }
    
    private JPanel board() {
        boardPanel = new JPanel();
        GridLayout gLayout = new GridLayout(15, 15, 0, 0 );
        boardPanel.setLayout(gLayout);
        
        for( Integer x : boardMap.keySet()) {
            for(Integer y : boardMap.get(x).keySet()) {
                boardPanel.add( boardMap.get(x).get(y).getButton() );
            }
        }
        
        return boardPanel;
    }
    
    private void gameOver() {
        this.gameOver = true;
        for( Integer x : boardMap.keySet()) {
            for(Integer y : boardMap.get(x).keySet()) {
                boardMap.get(x).get(y).trigger();
            }
        }
    }
    
    
    public class mweeperField implements mousePerformer {
        private position    pos;
        private FieldStatus status          = FieldStatus.HIDE_UNMARKED;
        private boolean     isBomb          = false;
        private int         bombsAroundMe   = 0;
        private JButton     but;
        private boolean     isTriggered     = false;
        
        public mweeperField( int x, int y ) {
            this.pos = new position(x, y);
            init();
        }
        public mweeperField( position p ) {
            this.pos = p;
            init();
        }
        public void resetField() {
            status          = FieldStatus.HIDE_UNMARKED;
            isBomb          = false;
            bombsAroundMe   = 0;
            isTriggered     = false;
            but.setFont(new Font("Arial", Font.BOLD, 13));
            but.setBackground(Color.LIGHT_GRAY);
            but.setText(" ");
            but.setEnabled(true);
        }
        public void setBomb() {
            this.isBomb = true;
        }
        public boolean isBomb() {
            return isBomb;
        }
        private void init() {
            but = new JButton(" ");
            but.setMaximumSize(new Dimension(16, 16));
            but.setMinimumSize(new Dimension(16, 16));
            but.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1));
            but.setMargin(new Insets(0, 0, 0, 0));
            but.setBackground(Color.LIGHT_GRAY);
            but.addMouseListener(new mweeperMouseListener(this.pos, this));
            but.setFont(new Font("Arial", Font.BOLD, 14));
        }
        
        private void setButton() {
            
            switch(status) {
                case HIDE_MARKED:
                    //but.setForeground( new Color(224, 124, 168) );
                    but.setForeground( Color.RED);
                    but.setText("@");
                    but.setEnabled(true);
                    break;
                case HIDE_UNMARKED: 
                    but.setForeground(Color.BLACK);
                    but.setText(" ");
                    but.setEnabled(true);
                    break;
                case OPEN_NOBOMB: 
                    switch(this.bombsAroundMe) {
                        case 1: 
                        case 2: 
                            but.setForeground(Color.BLUE);
                            break;
                        case 3:
                        case 4:
                            but.setForeground(Color.MAGENTA);
                            break;
                        case 5:
                        case 6:
                            but.setForeground(Color.RED);
                            break;
                        case 7:
                        case 8:
                            but.setForeground(Color.PINK);
                            break;
                    }
                    String butText = " ";
                    if(this.bombsAroundMe > 0) {
                        butText = String.valueOf(this.bombsAroundMe);
                    }
                    but.setEnabled(false);
                    but.setText( butText );
                    
                    break;
                    
                case OPEN_BOMB: // GAME OVER
                    but.setForeground(Color.BLACK);
                    but.setFont(new Font("Arial", Font.BOLD, 20));
                    but.setVerticalAlignment(SwingConstants.CENTER);
                    but.setHorizontalAlignment(SwingConstants.CENTER);
                    but.setText("*");
                    
                    break;
            }
//          but.setEnabled(false);
            but.validate();
            but.repaint();
            boardPanel.validate();
            boardPanel.repaint();
            mainPanel.repaint();
        }
        
        public JButton getButton() {
            return but;
        }
        
        /*
         +-----+-----+-----+
         | x-1 |  x  | x+1 |
         | y-1 | y-1 | y-1 |
         +-----+-----+-----+
         | x-1 | x/y | x+1 |
         |  y  |     |  y  |
         +-----+-----+-----+
         | x-1 |  x  | x+1 |
         | y+1 | y+1 | y+1 |
         +-----+-----+-----+
         */
        
        private void scan() {
            bombsAroundMe = 0;
            for(Integer k : pos.posAroundMe.keySet() ) {
                position p2 = pos.posAroundMe.get(k);
                if(boardMap.get(p2.x).get(p2.y).isBomb()) {
                    bombsAroundMe++;
                }
            }
        }
        
        public void trigger() {
            if(!isTriggered) {
                isTriggered = true;
                if(!isBomb) {
                    status = FieldStatus.OPEN_NOBOMB;
                }else {
                    status = FieldStatus.OPEN_BOMB;
                }
                scan();

                setButton();
                if(bombsAroundMe == 0) {
                    // um mich herum triggern
                    for(Integer k : pos.posAroundMe.keySet() ) {
                        position p2 = pos.posAroundMe.get(k);
                        boardMap.get(p2.x).get(p2.y).trigger();
                    }
                }
            }
        }
        
        @Override
        public void doClick(MouseEvent e, position pos) {
            switch(e.getButton()) {
                case 1: //Links Klick = triggern wenn nich markiert und hide
                        if(this.status.equals(FieldStatus.HIDE_UNMARKED)){
                            if(this.isBomb) {
                                // GAME OVER =8-(
                                status = FieldStatus.OPEN_BOMB;
                                but.setBackground(Color.RED);
                                gameOver();
                            }else {
                                trigger();
                            }   
                        }
                    break;
                    
                case 3: // Rechtsklick
                    
                    if(this.status.equals(FieldStatus.HIDE_UNMARKED)) {
                        // Mark Field
                        this.status = FieldStatus.HIDE_MARKED;
                        bombsMarked++;
                    }else {
                        // Umark Field
                        this.status = FieldStatus.HIDE_UNMARKED;
                        bombsMarked--;
                    }
                    setButton();
                    break;
            }
            
        }
        
        
    }
    
    public class position {
        public int x = 0;
        public int y = 0;
        public Map<Integer, position> posAroundMe;
        public position(int x, int y) {
            this.x = x;
            this.y = y;
            posAroundMe = new HashMap<Integer, MMWeeper.position>();
            setPosAroundMe();
        }
        public position(int x, int y, boolean setPos) {
            posAroundMe = new HashMap<Integer, MMWeeper.position>();
            this.x = x;
            this.y = y;
        }
        private void setPosAroundMe() {
            int c = 1;
            for(int x2 = (x-1); x2 <= (x+1); x2++) {
                for(int y2 = (y-1); y2 <= (y+1); y2++) {
                    if( ((x2 != x) || (y2 != y)) && ( x2>0 && x2<=boardX && y2>0 && y2<=boardY ) ){
                        posAroundMe.put(c++, new position(x2, y2, false));
                    }
                }
            }
        }
    }
    
    public enum FieldStatus{
        HIDE_UNMARKED,
        HIDE_MARKED,
        OPEN_NOBOMB,
        OPEN_BOMB;
    }
    
    public enum GameActions{
        START;
    }
    
    public class mweeperAction extends AbstractAction{
        private GameActions gameAction;
        
        public mweeperAction(GameActions ga ) {
            this.gameAction = ga;
        }
        
        @Override
        public void actionPerformed(ActionEvent ae) {
            switch(gameAction) {
            case START:
                    for( Integer x : boardMap.keySet()) {
                        for(Integer y : boardMap.get(x).keySet()) {
                            boardMap.get(x).get(y).resetField();;
                            boardMap.get(x).get(y).getButton().validate();
                            boardMap.get(x).get(y).getButton().repaint();;
                        }
                    }
                    int newBombCount = Integer.valueOf(bombsField.getText()) ;
                    if(newBombCount < 10) {
                        newBombCount = 10;
                    }
                    if(newBombCount > ((boardX * 2) + 20 ) ){
                        newBombCount = ((boardX * 2) + 20 ); 
                    }
                    bombs = newBombCount;
                    bombsField.setText(String.valueOf(bombs) );
                    placeBombs();
                    boardPanel.validate();
                    boardPanel.repaint();
                    mainPanel.repaint();
                break;
            }
        }
    }
    
    public class mweeperMouseListener implements MouseListener{
        private position pos;
        mousePerformer performer;
        public mweeperMouseListener(position pos, mousePerformer acPerf) {
            this.pos = pos;
            this.performer = acPerf;
        }

        @Override
        public void mouseClicked(MouseEvent e) {
            this.performer.doClick(e , pos );
        }

        @Override
        public void mouseEntered(MouseEvent e) {}

        @Override
        public void mouseExited(MouseEvent e) {}

        @Override
        public void mousePressed(MouseEvent e) {}

        @Override
        public void mouseReleased(MouseEvent e) {}
        
    }
    
    public interface mousePerformer{
        public void doClick(MouseEvent e, position pos   );
    }
    public interface actionPerformer{
        public void doAction(ActionEvent ae, GameActions ga );
    }
}
Ralf
  • 11
  • 2