Hey guys!
I have a project for school that involves changing the code I posted under this. One problem that I cannot figure out is how I would convert the mouse listener to a key listener. I believe the checkEmpty, moveTile, and exchangeTile methods will have to be coded differently in the LOGIC portion of the code, along with the listener in the GUI section of the code.
Any help would be greatly appreciated! Thanks!
Gary
MAIN PROGRAM
import javax.swing.JFrame;
///////////////////////////////////////////// class SlidePuzzle
class SlidePuzzle {
//============================================= method main
public static void main(String[] args) {
JFrame window = new JFrame("Slide Puzzle");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setContentPane(new SlidePuzzleGUI());
window.pack(); // finalize layout
window.show(); // make window visible
window.setResizable(false);
}//end main
}//endclass SlidePuzzle
GUI
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/////////////////////////////////////////////////// class SlidePuzzleGUI
// This class contains all the parts of the GUI interface
class SlidePuzzleGUI extends JPanel {
//=============================================== instance variables
private GraphicsPanel _puzzleGraphics;
private SlidePuzzleModel _puzzleModel = new SlidePuzzleModel();
//end instance variables
//====================================================== constructor
public SlidePuzzleGUI() {
//--- Create a button. Add a listener to it.
JButton newGameButton = new JButton("New Game");
newGameButton.addActionListener(new NewGameAction());
//--- Create control panel
JPanel controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
controlPanel.add(newGameButton);
//--- Create graphics panel
_puzzleGraphics = new GraphicsPanel();
//--- Set the layout and add the components
this.setLayout(new BorderLayout());
this.add(controlPanel, BorderLayout.NORTH);
this.add(_puzzleGraphics, BorderLayout.CENTER);
}//end constructor
//////////////////////////////////////////////// class GraphicsPanel
// This is defined inside the outer class so that
// it can use the outer class instance variables.
class GraphicsPanel extends JPanel implements MouseListener {
private static final int ROWS = 3;
private static final int COLS = 3;
private static final int CELL_SIZE = 80; // Pixels
private Font _biggerFont;
//================================================== constructor
public GraphicsPanel() {
_biggerFont = new Font("SansSerif", Font.BOLD, CELL_SIZE/2);
this.setPreferredSize(
new Dimension(CELL_SIZE * COLS, CELL_SIZE*ROWS));
this.setBackground(Color.black);
this.addMouseListener(this); // Listen own mouse events.
}//end constructor
//=======================================x method paintComponent
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int r=0; r<ROWS; r++) {
for (int c=0; c<COLS; c++) {
int x = c * CELL_SIZE;
int y = r * CELL_SIZE;
String text = _puzzleModel.getFace(r, c);
if (text != null) {
g.setColor(Color.gray);
g.fillRect(x+2, y+2, CELL_SIZE-4, CELL_SIZE-4);
g.setColor(Color.black);
g.setFont(_biggerFont);
g.drawString(text, x+20, y+(3*CELL_SIZE)/4);
}
}
}
}//end paintComponent
//======================================== listener mousePressed
public void mousePressed(MouseEvent e) {
//--- map x,y coordinates into a row and col.
int col = e.getX()/CELL_SIZE;
int row = e.getY()/CELL_SIZE;
if (!_puzzleModel.moveTile(row, col)) {
// moveTile moves tile if legal, else returns false.
Toolkit.getDefaultToolkit().beep();
}
this.repaint(); // Show any updates to model.
}//end mousePressed
//========================================== ignore these events
public void mouseClicked (MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered (MouseEvent e) {}
public void mouseExited (MouseEvent e) {}
}//end class GraphicsPanel
////////////////////////////////////////// inner class NewGameAction
public class NewGameAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
_puzzleModel.reset();
_puzzleGraphics.repaint();
}
}//end inner class NewGameAction
}//end class SlidePuzzleGUI
LOGIC
class SlidePuzzleModel {
private static final int ROWS = 3;
private static final int COLS = 3;
private Tile[][] _contents; // All tiles.
private Tile _emptyTile; // The empty space.
//================================================= constructor
public SlidePuzzleModel() {
_contents = new Tile[ROWS][COLS];
reset(); // Initialize and shuffle tiles.
}//end constructor
//===================================================== getFace
// Return the string to display at given row, col.
String getFace(int row, int col) {
return _contents[row][col].getFace();
}//end getFace
//======================================================= reset
// Initialize and shuffle the tiles.
public void reset() {
for (int r=0; r<ROWS; r++) {
for (int c=0; c<COLS; c++) {
_contents[r][c] = new Tile(r, c, "" + (r*COLS+c+1));
}
}
//--- Set last tile face to null to mark empty space
_emptyTile = _contents[ROWS-1][COLS-1];
_emptyTile.setFace(null);
//-- Shuffle - Exchange each tile with random tile.
for (int r=0; r<ROWS; r++) {
for (int c=0; c<COLS; c++) {
exchangeTiles(r, c, (int)(Math.random()*ROWS)
, (int)(Math.random()*COLS));
}
}
}//end reset
//==================================================== moveTile
// Move a tile to empty position beside it, if possible.
// Return true if it was moved, false if not legal.
public boolean moveTile(int r, int c) {
//--- It's a legal move if the empty cell is next to it.
return checkEmpty(r, c, -1, 0) || checkEmpty(r, c, 1, 0)
|| checkEmpty(r, c, 0, -1) || checkEmpty(r, c, 0, 1);
}//end moveTile
//================================================== checkEmpty
// Check to see if there is an empty position beside tile.
// Return true and exchange if possible, else return false.
private boolean checkEmpty(int r, int c, int rdelta, int cdelta) {
int rNeighbor = r + rdelta;
int cNeighbor = c + cdelta;
//--- Check to see if this neighbor is on board and is empty.
if (isLegalRowCol(rNeighbor, cNeighbor)
&& _contents[rNeighbor][cNeighbor] == _emptyTile) {
exchangeTiles(r, c, rNeighbor, cNeighbor);
return true;
}
return false;
}//end checkEmpty
//=============================================== isLegalRowCol
// Check for legal row, col
public boolean isLegalRowCol(int r, int c) {
return r>=0 && r<ROWS && c>=0 && c<COLS;
}//end isLegalRowCol
//=============================================== exchangeTiles
// Exchange two tiles.
private void exchangeTiles(int r1, int c1, int r2, int c2) {
Tile temp = _contents[r1][c1];
_contents[r1][c1] = _contents[r2][c2];
_contents[r2][c2] = temp;
}//end exchangeTiles
//=================================================== isGameOver
public boolean isGameOver() {
for (int r=0; r<ROWS; r++) {
for (int c=0; c<ROWS; c++) {
Tile trc = _contents[r][c];
return trc.isInFinalPosition(r, c);
}
}
//--- Falling thru loop means nothing out of place.
return true;
}//end isGameOver
}//end class SlidePuzzleModel
////////////////////////////////////////////////////////// class Tile
// Represents the individual "tiles" that slide in puzzle.
class Tile {
//============================================ instance variables
private int _row; // row of final position
private int _col; // col of final position
private String _face; // string to display
//end instance variables
//==================================================== constructor
public Tile(int row, int col, String face) {
_row = row;
_col = col;
_face = face;
}//end constructor
//======================================================== setFace
public void setFace(String newFace) {
_face = newFace;
}//end getFace
//======================================================== getFace
public String getFace() {
return _face;
}//end getFace
//=============================================== isInFinalPosition
public boolean isInFinalPosition(int r, int c) {
return r==_row && c==_col;
}//end isInFinalPosition
}//end class Tile