import java.awt.event.*;
import java.io.*;
import java.nio.channels.FileLockInterruptionException;
import java.util.Vector;
import javax.swing.*;
/*
* Assignment 4
* Name: Guo Dafeng
* Student ID: 07608292
* Email Addr: dfguo7@cse.cuhk.edu.hk
*/
/**
* This SokobanMain class contains the main function as well as the interface with the user, including the responses to the mouse clicks and the key inputs and rendering gui.
*
* @author Guo Dafeng
*
*/
public class SokobanMain implements WindowListener, ActionListener, KeyListener {
private SokobanGame gameLogic;
private static SokobanMain gameMain;
private static SokobanGUI gui;
private JLabel label[][];
private JLabel levelLabel, moveLabel;
private Vector<GameRecord> gameRecord;
/**
* Constructs SokobanMain class containing the game logic, labels on gui, and game recorder.
*/
public SokobanMain() {
gameLogic = new SokobanGame();
label = new JLabel[21][21];
levelLabel = new JLabel("", JLabel.LEFT);
moveLabel = new JLabel("", JLabel.LEFT);
gameRecord = new Vector<GameRecord>();
}
/**
* Class main function
* @param args
*/
public static void main(String[] args) {
gameMain = new SokobanMain();
gui = new SokobanGUI("CSC3100 Sokoban", gameMain);
gui.getContentPane().setFocusable(true);
gui.getContentPane().addKeyListener(gameMain);
run(gui,630,680);
}
/**
* Runs the JFrame f with size width * height
*
* @param f JFrame that will be running
* @param width JFrame width
* @param height JFrame height
*/
public static void run(final JFrame f, final int width, final int height) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
f.setTitle(f.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(width, height);
f.setVisible(true);
}
});
}
/**
* Not implemented
*/
public void windowActivated(WindowEvent e) {
// TODO Auto-generated method stub
}
/**
* Not implemented
*/
public void windowClosed(WindowEvent e) {
// TODO Auto-generated method stub
}
/**
* Not implemented
*/
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
}
/**
* Not implemented
*/
public void windowDeactivated(WindowEvent e) {
// TODO Auto-generated method stub
}
/**
* Not implemented
*/
public void windowDeiconified(WindowEvent e) {
// TODO Auto-generated method stub
}
/**
* Not implemented
*/
public void windowIconified(WindowEvent e) {
// TODO Auto-generated method stub
}
/**
* Not implemented
*/
public void windowOpened(WindowEvent e) {
// TODO Auto-generated method stub
}
/**
* Performs the corresponding actions to events sent by the menu. Includes "New Game", "About", "Save Game", "Load Game", "Quit".
* @param e ActionEvent object that we caught
*/
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String item = ((JMenuItem) e.getSource()).getText();
boolean loop = true;
if (item.equals("New Game")) {
while (loop) {
String level = JOptionPane.showInputDialog(null,
"Select level: (1-92)");
if (level != null) {
try {
newGame(Integer.parseInt(level));
loop = false;
} catch (NumberFormatException exp) {
JOptionPane.showMessageDialog(null,
"Only numbers are allowed!");
}
} else {
loop = false;
}
}
} else if (item.equals("About")) {
JOptionPane
.showMessageDialog(null,
"CSC3100: Software Engineering\nAssignment 4: Sokoban\nGuo Dafeng");
} else if (item.equals("Save Game")) {
if (gameLogic.getIsStart()) {
JFileChooser c = new JFileChooser();
// Demonstrate "Save" dialog:
int rVal = c.showSaveDialog(gui);
if (rVal == JFileChooser.APPROVE_OPTION) {
String fileName = c.getSelectedFile().getName();
try {
// use buffering
OutputStream file = new FileOutputStream(fileName);
OutputStream buffer = new BufferedOutputStream(file);
ObjectOutput output = new ObjectOutputStream(buffer);
try {
output.writeInt(gameLogic.getLevel());
output.writeObject(gameRecord);
} finally {
output.close();
JOptionPane.showMessageDialog(gui, "Game saved to file "+fileName+".");
}
} catch (Exception exp) {
exp.printStackTrace();
JOptionPane.showMessageDialog(null, "File " + fileName
+ " can not be written!");
}
}
} else {
JOptionPane.showMessageDialog(gui, "Start a game first!");
}
} else if (item.equals("Load Game")) {
// Demonstrate "Open" dialog:
if (gameLogic.getIsStart()) {
JFileChooser c = new JFileChooser();
int rVal = c.showOpenDialog(gui);
if (rVal == JFileChooser.APPROVE_OPTION) {
String fileName = c.getSelectedFile().getName();
try {
// use buffering
InputStream file = new FileInputStream(fileName);
InputStream buffer = new BufferedInputStream(file);
ObjectInput input = new ObjectInputStream(buffer);
try {
int loadLevel = input.readInt();
System.out.println(loadLevel);
if (loadLevel!=gameLogic.getLevel()) throw new FileLockInterruptionException();
// deserialize the List
Vector<GameRecord> recoveredGameRecord = (Vector<GameRecord>) input
.readObject();
// display its data
gameLogic.initialize(gameLogic.getLevel());
startGame();
gui.paint(gui.getGraphics());
JOptionPane.showMessageDialog(gui, "Game move loaded. Press enter to start playing.");
for (GameRecord gameTemp : recoveredGameRecord) {
//gui.getContentPane().dispatchEvent();
moveAndRender(gameTemp.getDirection());
Thread.sleep(300);
gui.paint(gui.getGraphics());
}
} finally {
input.close();
}
} catch (FileLockInterruptionException ex) {
JOptionPane.showMessageDialog(null, "File "
+ fileName + " is not for this level!");
} catch (FileNotFoundException ex) {
JOptionPane.showMessageDialog(null, "File "
+ fileName + " is not found!");
} catch (ClassNotFoundException ex) {
JOptionPane.showMessageDialog(null, "File "
+ fileName + " is not valid!");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "File "
+ fileName + " is not valid!");
}
}
} else {
JOptionPane.showMessageDialog(gui, "Start a game first!");
}
} else if (item.equals("Quit")) {
gui.dispose();
System.exit(0);
}
}
/**
* Responds to the KeyEvent and perform corresponding movement and rendering of gui. Includes respond to up, down, left, right, . , 0
*/
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
int x, y;
Player player = null;
int dx, dy;
int ddx, ddy;
x = y=dx=dy=ddx=ddy=0;
if (gameLogic.getIsStart()) {
player = gameLogic.getPlayer();
x = player.getX();
y = player.getY();
}
if (arg0.getKeyCode() == KeyEvent.VK_UP) {
if (gameLogic.getIsStart()) {
moveAndRender("up");
}
} else if (arg0.getKeyCode() == KeyEvent.VK_DOWN) {
if (gameLogic.getIsStart()) {
moveAndRender("down");
}
} else if (arg0.getKeyCode() == KeyEvent.VK_LEFT) {
if (gameLogic.getIsStart()) {
moveAndRender("left");
}
} else if (arg0.getKeyCode() == KeyEvent.VK_RIGHT) {
if (gameLogic.getIsStart()) {
moveAndRender("right");
}
} else if (arg0.getKeyCode() == KeyEvent.VK_NUMPAD0) {
if (gameLogic.getIsStart() && !gameRecord.isEmpty()) {
// undo
GameRecord rec;
rec = (GameRecord) g