Code cleanup in Window class and improved comments in other classes.

This commit is contained in:
t-moe
2016-06-24 23:29:08 +02:00
parent ef0cdb4764
commit b217734b49
5 changed files with 137 additions and 82 deletions

View File

@@ -1,13 +1,15 @@
### **7not7** ### **7not7**
### *A 7x7 clone written in java* ### *A 7x7 clone written in java*
This page should be viewed on [Github](https://github.com/id101010/7not7)
--- ---
### Summary ### Summary
7x7 is a concentration game which challenges you to connect 4 or more blocks of the same color on the game field. 7x7 is a concentration game which challenges you to connect 4 or more blocks of the same color on the game field.
To make things harder each round n blocks of random colors get thrown upon the field and the number n increases with each level. To make things harder each round n blocks of random colors get thrown upon the field and the number n increases with each level.
You can choose the field size to be eighter 7x7, 8x8, 9x9 or 10x10. You can choose the field size to be either 7x7, 8x8, 9x9 or 10x10.
![Moving Blocks](https://github.com/id101010/7not7/blob/master/doc/movingBlocks.png) ![Moving Blocks](https://github.com/id101010/7not7/blob/master/doc/movingBlocks.png)
@@ -15,6 +17,7 @@ You can choose the field size to be eighter 7x7, 8x8, 9x9 or 10x10.
The goal is to clear as much lines as possible by stacking blocks of the same color in any direction. The goal is to clear as much lines as possible by stacking blocks of the same color in any direction.
So you can eighter build up blocks vertically, horizontally or diagonal. So you can eighter build up blocks vertically, horizontally or diagonal.
To move blocks click on the block you want to move, hold the mouse and release it on the target position.
### Tools and how to get them ### Tools and how to get them

View File

@@ -24,6 +24,7 @@ public class FieldCanvas extends JPanel{
static final int borderTop = 5; static final int borderTop = 5;
static final int borderBottom = 5; static final int borderBottom = 5;
//Colors to use to paint the blocks. Chosen with a color scheme designer
public static final Color[] colors = { public static final Color[] colors = {
new Color(0xD66436), new Color(0xD66436),
new Color(0x486F70), new Color(0x486F70),
@@ -34,11 +35,11 @@ public class FieldCanvas extends JPanel{
private Game game; private Game game;
private Point src; private Point src; //Position of the Block that the user wants to move (can be null)
private Point dst; private Point dst; //Destination Position (can be null)
private List<Point> path; private List<Point> path; //Path that visualizes src->dst (can be null)
private List<Point> blockedFields; private List<Point> blockedFields; //Fields that should be marked as blocked (can be null)
private boolean freeMoveMode = false; private boolean freeMoveMode = false; //Whether or not we're in free moving mode
/** /**
* Constructor of FieldCanvas * Constructor of FieldCanvas
@@ -53,9 +54,9 @@ public class FieldCanvas extends JPanel{
super.mousePressed(e); super.mousePressed(e);
Point p = FieldCanvas.this.getClickPoint(e.getPoint()); Point p = FieldCanvas.this.getClickPoint(e.getPoint());
if(p==null || game.getField()[p.x][p.y]==0) { //invalid click if(p==null || game.getField()[p.x][p.y]==0) { //invalid click (outside of bounds or on empty position)
src = null; src = null;
} else { } else { //valid click
src = p; src = p;
if(freeMoveMode) { if(freeMoveMode) {
blockedFields = game.getReachablePoints(src); blockedFields = game.getReachablePoints(src);
@@ -69,24 +70,26 @@ public class FieldCanvas extends JPanel{
@Override @Override
public void mouseDragged(MouseEvent e) { public void mouseDragged(MouseEvent e) {
super.mouseDragged(e); super.mouseDragged(e);
if(src!=null) { if(src!=null) { //we have a valid point that the users wants to move
Point lastDst = dst; Point lastDst = dst;
dst = FieldCanvas.this.getClickPoint(e.getPoint()); dst = FieldCanvas.this.getClickPoint(e.getPoint());
if(lastDst!=dst && dst!=null) { //hovered field changed if(lastDst!=dst && dst!=null) { //hovered field changed
if(freeMoveMode) { if(freeMoveMode) {
//Check if the target position is empty and we could not move the block there in normal mode
if(!game.canMove(src, dst) && game.getField()[dst.x][dst.y]==0) { if(!game.canMove(src, dst) && game.getField()[dst.x][dst.y]==0) {
//Create fake path with only src and dst
path = new ArrayList<Point>(); path = new ArrayList<Point>();
path.add(src); path.add(src);
path.add(dst); path.add(dst);
} else { } else {
path= null; path= null;
} }
} else { } else { //not in freemove mode
path= game.getPath(src, dst); path= game.getPath(src, dst); //calculate path from src to dst (pathfinding)
} }
repaint(); repaint();
} }
}else { } else { //no valid src
dst = null; dst = null;
path = null; path = null;
} }
@@ -96,13 +99,13 @@ public class FieldCanvas extends JPanel{
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent e) {
super.mouseReleased(e); super.mouseReleased(e);
dst = FieldCanvas.this.getClickPoint(e.getPoint()); dst = FieldCanvas.this.getClickPoint(e.getPoint());
path = null; path = null; //do no longer paint path
if(freeMoveMode) { if(freeMoveMode) {
if(!game.canMove(src, dst)) { if(!game.canMove(src, dst)) { //if we couldn't move there in normal mode
game.doFreeMove(src, dst); game.doFreeMove(src, dst);
} }
} else { } else { //not in freemove mode
if(dst != null && src!=null && !src.equals(dst)) { if(dst != null && src!=null && !src.equals(dst)) { //src and dst are valid
System.out.println("Moving from "+src.toString()+ " to "+dst.toString()); System.out.println("Moving from "+src.toString()+ " to "+dst.toString());
game.doMove(src, dst); game.doMove(src, dst);
} }
@@ -147,11 +150,11 @@ public class FieldCanvas extends JPanel{
} }
/** /**
* Calculates the position in which a click event has happened. * Maps a mouse position to game coordinates
* *
* @author timo * @author timo
* @param globalPos * @param globalPos Position of clickevent
* @return Position of clickevent * @return point in game coordinates
*/ */
private Point getClickPoint(Point globalPos) { private Point getClickPoint(Point globalPos) {
int total = Math.min(this.getHeight()-borderTop-borderBottom,FieldCanvas.this.getWidth()-borderLeft-borderRight); int total = Math.min(this.getHeight()-borderTop-borderBottom,FieldCanvas.this.getWidth()-borderLeft-borderRight);
@@ -170,6 +173,8 @@ public class FieldCanvas extends JPanel{
public void paintComponent(Graphics g) { public void paintComponent(Graphics g) {
super.paintComponent(g); super.paintComponent(g);
if(game==null) return;
//Draw field (background and lines) //Draw field (background and lines)
if(freeMoveMode) { if(freeMoveMode) {
g.setColor(Color.gray); g.setColor(Color.gray);
@@ -180,21 +185,20 @@ public class FieldCanvas extends JPanel{
g.translate(borderLeft, borderTop); g.translate(borderLeft, borderTop);
int total = Math.min(this.getHeight()-borderTop-borderBottom,FieldCanvas.this.getWidth()-borderLeft-borderRight); int total = Math.min(this.getHeight()-borderTop-borderBottom,FieldCanvas.this.getWidth()-borderLeft-borderRight);
int space = total/game.getSize(); int space = total/game.getSize();
total = space*game.getSize();
g.setClip(0, 0, total-4,total-4); g.setClip(0, 0, total+1,total+1);
g.fillRect(0, 0, total-4,total-4); g.fillRect(0, 0, total,total);
g.setColor(Color.white); g.setColor(Color.white);
for(int i=0; i<=game.getSize(); i++) { for(int i=0; i<=game.getSize(); i++) {
g.drawLine(0,i*space,total-2,i*space); g.drawLine(0,i*space,total,i*space);
g.drawLine(i*space,0,i*space,total-2); g.drawLine(i*space,0,i*space,total);
} }
if(game==null) return;
//Draw blocks //Draw blocks
for(int x=0; x<game.getSize(); x++) { for(int x=0; x<game.getSize(); x++) {
for(int y=0; y<game.getSize(); y++) { for(int y=0; y<game.getSize(); y++) {
int colorCode = game.getField()[x][y]; int colorCode = game.getField()[x][y];
@@ -206,7 +210,6 @@ public class FieldCanvas extends JPanel{
} }
//Draw blocked fields //Draw blocked fields
if(blockedFields!=null) { if(blockedFields!=null) {
g.setColor(Color.darkGray); g.setColor(Color.darkGray);
for(int i=0; i<blockedFields.size(); i++) { for(int i=0; i<blockedFields.size(); i++) {

View File

@@ -16,7 +16,7 @@ public class Game {
* *
*/ */
public interface UpdateListener { public interface UpdateListener {
public void gameUpdate(); public void gameUpdated();
} }
// Constants // Constants
@@ -173,7 +173,7 @@ public class Game {
*/ */
private void emitUpdateEvent(){ private void emitUpdateEvent(){
for(UpdateListener e: updateListeners) { for(UpdateListener e: updateListeners) {
e.gameUpdate(); e.gameUpdated();
} }
} }
@@ -326,6 +326,8 @@ public class Game {
// Populate game field // Populate game field
this.populateField(); this.populateField();
emitUpdateEvent();
} }
/** /**

View File

@@ -6,7 +6,15 @@ import java.util.List;
import javax.swing.JPanel; import javax.swing.JPanel;
public class NextMovesCanvas extends JPanel { /**
* Class which renders the Blocks that will be placed next on the field
* @author timo
*
*/
public class NextMovesCanvas extends JPanel implements Game.UpdateListener {
private static final long serialVersionUID = 1L;
private Game game; private Game game;
static final int borderLeft = 1; static final int borderLeft = 1;
@@ -16,19 +24,17 @@ public class NextMovesCanvas extends JPanel {
public NextMovesCanvas(Game g) { public NextMovesCanvas(Game g) {
this.game = g; this.game = g;
g.addUpdateListener(new Game.UpdateListener() { g.addUpdateListener(this);
@Override
public void gameUpdate() {
NextMovesCanvas.this.repaint();
}
});
} }
@Override
public void gameUpdated() {
NextMovesCanvas.this.repaint();
}
public void paintComponent(Graphics g) { public void paintComponent(Graphics g) {
super.paintComponent(g); super.paintComponent(g);
g.setColor(Color.lightGray); g.setColor(Color.lightGray);
int height = getHeight() - borderTop-borderBottom; int height = getHeight() - borderTop-borderBottom;

View File

@@ -2,25 +2,28 @@ package ch.bfh.sevennotseven;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.CardLayout; import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.FlowLayout; import java.awt.FlowLayout;
import java.awt.HeadlessException; import java.awt.HeadlessException;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter; import java.net.URI;
import java.awt.event.WindowEvent;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
/** /**
* Window class, places gui elements and listeners. * Window class, contains the welcome screen and the game itself
* *
* @author timo * @author timo
*/ */
public class Window extends JFrame implements ActionListener{ public class Window extends JFrame implements ActionListener, Game.UpdateListener {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Game game; private Game game;
@@ -29,6 +32,7 @@ public class Window extends JFrame implements ActionListener{
private JButton buttonUndo; private JButton buttonUndo;
private JButton buttonFreeMove; private JButton buttonFreeMove;
private JButton buttonReset;
private JLabel labelScore; private JLabel labelScore;
private JLabel labelLinesLeft; private JLabel labelLinesLeft;
private JLabel labelLevel; private JLabel labelLevel;
@@ -44,15 +48,26 @@ public class Window extends JFrame implements ActionListener{
public Window(String title) throws HeadlessException { public Window(String title) throws HeadlessException {
super(title); super(title);
this.addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
game = new Game(); game = new Game();
game.addUpdateListener(this); //register for game updates
initMainLayout();
}
private void initMainLayout() {
mainPanel = new JPanel();
cardLayout = new CardLayout();
mainPanel.setLayout(cardLayout);
initWelcomeLayout();
initGameLayout();
this.setContentPane(mainPanel);
this.setSize(800,600);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void initGameLayout() {
moves = new NextMovesCanvas(game); moves = new NextMovesCanvas(game);
field = new FieldCanvas(game); field = new FieldCanvas(game);
@@ -62,16 +77,23 @@ public class Window extends JFrame implements ActionListener{
buttonFreeMove.setEnabled(false); buttonFreeMove.setEnabled(false);
buttonFreeMove.addActionListener(this); buttonFreeMove.addActionListener(this);
buttonFreeMove.setActionCommand("freemove"); buttonFreeMove.setActionCommand("freemove");
buttonUndo = new JButton("Undo (0)"); buttonUndo = new JButton("Undo (0)");
buttonUndo.setEnabled(false); buttonUndo.setEnabled(false);
buttonUndo.addActionListener(this); buttonUndo.addActionListener(this);
buttonUndo.setActionCommand("undo"); buttonUndo.setActionCommand("undo");
buttonReset = new JButton("Reset");
buttonReset.addActionListener(this);
buttonReset.setActionCommand("reset");
labelScore= new JLabel("Score: 0"); labelScore= new JLabel("Score: 0");
labelLinesLeft = new JLabel("Lines Left: 40"); labelLinesLeft = new JLabel("Lines Left: 40");
labelLevel = new JLabel("Level: 1"); labelLevel = new JLabel("Level: 1");
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
topPanel.add(buttonReset);
topPanel.add(buttonFreeMove); topPanel.add(buttonFreeMove);
topPanel.add(buttonUndo); topPanel.add(buttonUndo);
topPanel.add(labelScore); topPanel.add(labelScore);
@@ -84,50 +106,43 @@ public class Window extends JFrame implements ActionListener{
buttonFreeMove.setText("Free Move ("+game.getAvailFreeMoves()+")"); buttonFreeMove.setText("Free Move ("+game.getAvailFreeMoves()+")");
buttonUndo.setText("Undo ("+game.getAvailUndo()+")"); buttonUndo.setText("Undo ("+game.getAvailUndo()+")");
game.addUpdateListener(new Game.UpdateListener() { JPanel gamePanel = new JPanel();
gamePanel.setLayout(new BorderLayout());
@Override gamePanel.add(topPanel, BorderLayout.NORTH);
public void gameUpdate() { gamePanel.add(field);
labelScore.setText("Score: "+game.getScore()); mainPanel.add(gamePanel);
buttonFreeMove.setEnabled(game.getAvailFreeMoves()>0);
buttonUndo.setEnabled(game.getAvailUndo()>0);
buttonFreeMove.setText("Free Move ("+game.getAvailFreeMoves()+")");
buttonUndo.setText("Undo ("+game.getAvailUndo()+")");
labelLinesLeft.setText("Lines Left: "+game.getLinesLeft());
labelLevel.setText("Level: "+game.getLevel());
} }
});
private void initWelcomeLayout() {
JPanel welcomePanel = new JPanel(); JPanel welcomePanel = new JPanel();
welcomePanel.setLayout(new BoxLayout(welcomePanel, BoxLayout.Y_AXIS));
JButton btnInstr = new JButton("Instructions & More");
btnInstr.setAlignmentX(Component.CENTER_ALIGNMENT);
btnInstr.setActionCommand("github");
btnInstr.addActionListener(this);
welcomePanel.add(Box.createRigidArea(new Dimension(0,5)));
welcomePanel.add(btnInstr);
welcomePanel.add(Box.createRigidArea(new Dimension(0,10)));
int sizes [] = {7,8,9,10}; int sizes [] = {7,8,9,10};
for(int i=0; i<sizes.length; i++) { for(int i=0; i<sizes.length; i++) {
JButton btn = new JButton(sizes[i]+"x"+sizes[i]); JButton btn = new JButton(sizes[i]+"x"+sizes[i]);
btn.addActionListener(this); btn.addActionListener(this);
btn.setActionCommand(Integer.toString(sizes[i])); btn.setActionCommand(Integer.toString(sizes[i]));
btn.setAlignmentX(Component.CENTER_ALIGNMENT);
welcomePanel.add(btn); welcomePanel.add(btn);
welcomePanel.add(Box.createRigidArea(new Dimension(0,5)));
} }
JPanel gamePanel = new JPanel();
gamePanel.setLayout(new BorderLayout());
gamePanel.add(topPanel, BorderLayout.NORTH);
gamePanel.add(field);
mainPanel = new JPanel();
cardLayout = new CardLayout();
mainPanel.setLayout(cardLayout);
mainPanel.add(welcomePanel); mainPanel.add(welcomePanel);
mainPanel.add(gamePanel);
this.setContentPane(mainPanel);
this.setSize(470,460);
this.setVisible(true);
} }
/** /**
* Action listener callback, determines which function to call. * Action listener callback: gets called when a button was pressed
* The method will either start a game or forward an action to the game
* *
* @author timo * @author timo
* @param e ActionEvent * @param e ActionEvent
@@ -139,6 +154,17 @@ public class Window extends JFrame implements ActionListener{
field.doUndo(); field.doUndo();
} else if (command.equals("freemove")) { } else if (command.equals("freemove")) {
field.toggleFreeMove(); field.toggleFreeMove();
} else if(command.equals("github")) {
if(Desktop.isDesktopSupported()) {
final String url = "https://github.com/id101010/7not7/blob/master/README.md";
try {
Desktop.getDesktop().browse(new URI(url));
} catch(Exception ex) {
System.out.println("Couldn't open link: "+url+" "+ex.toString());
}
}
} else if(command.equals("reset")) {
cardLayout.first(mainPanel);
} else { } else {
int size = Integer.parseInt(command); int size = Integer.parseInt(command);
cardLayout.last(mainPanel); cardLayout.last(mainPanel);
@@ -147,6 +173,21 @@ public class Window extends JFrame implements ActionListener{
} }
/**
* GameUpdateListener: gets called when the games was updated (e.g. user made a move)
*/
@Override
public void gameUpdated() {
labelScore.setText("Score: "+game.getScore());
buttonFreeMove.setEnabled(game.getAvailFreeMoves()>0);
buttonUndo.setEnabled(game.getAvailUndo()>0);
buttonFreeMove.setText("Free Move ("+game.getAvailFreeMoves()+")");
buttonUndo.setText("Undo ("+game.getAvailUndo()+")");
labelLinesLeft.setText("Lines Left: "+game.getLinesLeft());
labelLevel.setText("Level: "+game.getLevel());
}
/** /**
* Main method * Main method
* *