diff --git a/src/main/java/com/billenius/img/splitscreen.png b/src/main/java/com/billenius/img/splitscreen.png new file mode 100644 index 0000000..2d09488 Binary files /dev/null and b/src/main/java/com/billenius/img/splitscreen.png differ diff --git a/src/main/java/com/billenius/schack/BasicMove.java b/src/main/java/com/billenius/schack/BasicMove.java new file mode 100644 index 0000000..7153a04 --- /dev/null +++ b/src/main/java/com/billenius/schack/BasicMove.java @@ -0,0 +1,24 @@ +package com.billenius.schack; + +import java.awt.Point; +import java.io.Serializable; + +public class BasicMove implements Serializable { + public Point from; + public Point to; + + public BasicMove(Point from, Point to) { + this.from = from; + this.to = to; + } + + public BasicMove(Move m) { + this.from = m.from; + this.to = m.to; + } + + public String toString() { + return (from.x + 1) + ":" + (from.y + 1) + + " " + '\u27F6' + " " + (to.x + 1) + ":" + (to.y + 1); + } +} diff --git a/src/main/java/com/billenius/schack/Move.java b/src/main/java/com/billenius/schack/Move.java index 432a1c6..73d9a8a 100644 --- a/src/main/java/com/billenius/schack/Move.java +++ b/src/main/java/com/billenius/schack/Move.java @@ -4,21 +4,17 @@ import java.awt.Point; import com.billenius.schack.pieces.Piece; -public class Move { +public class Move extends BasicMove { public Piece movedPiece; - public Point from; - public Point to; - public String color; - public Move(Piece movedPiece, Point from, Point to) { - this.from = from; - this.to = to; - this.color = movedPiece.isWhite() ? "White" : "Black"; - this.movedPiece = movedPiece; + public Move(Piece piece, Point from, Point to) { + super(from, to); + this.movedPiece = piece; } - public String toString() { - return (from.x + 1) + ":" + (from.y + 1) - + " " + '\u27F6' + " " + (to.x + 1) + ":" + (to.y + 1); + public Move(Piece piece, BasicMove basicMove) { + super(basicMove.from, basicMove.to); + this.movedPiece = piece; } + } diff --git a/src/main/java/com/billenius/schack/Schack.java b/src/main/java/com/billenius/schack/Schack.java index b84ae61..fe2b90b 100644 --- a/src/main/java/com/billenius/schack/Schack.java +++ b/src/main/java/com/billenius/schack/Schack.java @@ -1,12 +1,16 @@ package com.billenius.schack; +import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Font; import java.awt.HeadlessException; import java.awt.event.ActionEvent; +import java.awt.image.BufferedImage; import java.io.IOException; import java.net.Inet4Address; import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.Map; import javax.swing.DefaultListModel; import javax.swing.JFrame; @@ -20,10 +24,10 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.UIManager; -import java.awt.BorderLayout; -import com.billenius.schack.Move; -import com.billenius.schack.PieceRenderer; +import com.billenius.schack.boards.Board; +import com.billenius.schack.boards.NetworkBoard; +import com.billenius.schack.boards.SameBoard; import com.formdev.flatlaf.FlatLightLaf; /** @@ -33,6 +37,10 @@ import com.formdev.flatlaf.FlatLightLaf; public class Schack { final JFrame frame; + // Förlåt mig fader för jag kommer synda + public final static Map pieceIcons = new HashMap<>(); + + public Schack() throws IOException { // Set theme @@ -45,15 +53,30 @@ public class Schack { } catch (Exception cantGetSystemTheme) { } + String[] options = { "On the same screen", "Over the internet" }; + int choosenTransformations = JOptionPane.showOptionDialog(null, + "How do you want to connect with your opponent", + "Schack: Selection", + JOptionPane.DEFAULT_OPTION, + JOptionPane.INFORMATION_MESSAGE, + null, + options, + options[0]); + + DefaultListModel listModel = new DefaultListModel<>(); + final Board board; + if (choosenTransformations == 0) + board = new SameBoard(listModel); + else + board = new NetworkBoard(listModel); + frame = new JFrame(); frame.setTitle("Schack"); frame.setAlwaysOnTop(false); frame.setResizable(true); - DefaultListModel listModel = new DefaultListModel<>(); - // Might throw an IOException if the icon of the Pieces isn't embedded correctly - final Board board = new Board(listModel); + // final Board board = new BlistModeloard(listModel); // Logger final JList jlist = new JList<>(listModel); diff --git a/src/main/java/com/billenius/schack/Board.java b/src/main/java/com/billenius/schack/boards/Board.java similarity index 82% rename from src/main/java/com/billenius/schack/Board.java rename to src/main/java/com/billenius/schack/boards/Board.java index aedbc48..a6f302c 100644 --- a/src/main/java/com/billenius/schack/Board.java +++ b/src/main/java/com/billenius/schack/boards/Board.java @@ -1,4 +1,4 @@ -package com.billenius.schack; +package com.billenius.schack.boards; import java.awt.Color; import java.awt.Dimension; @@ -12,9 +12,10 @@ import java.util.ArrayList; import java.util.List; import javax.swing.DefaultListModel; -import javax.swing.JOptionPane; import javax.swing.JPanel; +import com.billenius.schack.Move; +import com.billenius.schack.SchackState; import com.billenius.schack.pieces.Bishop; import com.billenius.schack.pieces.Horse; import com.billenius.schack.pieces.King; @@ -23,16 +24,16 @@ import com.billenius.schack.pieces.Piece; import com.billenius.schack.pieces.Queen; import com.billenius.schack.pieces.Rook; -public class Board extends JPanel implements MouseListener { +public abstract class Board extends JPanel implements MouseListener { public static final int SIZE_OF_TILE = 100; - private Piece[][] pieces = new Piece[8][8]; - private List validMovesToDraw = new ArrayList<>(); + protected Piece[][] pieces = new Piece[8][8]; + protected List validMovesToDraw = new ArrayList<>(); private Point previouslyClickedPoint = new Point(); private final Color moveableColor = new Color(255, 191, 0); short turnCount = 0; - private boolean whitesTurn = true; - private DefaultListModel moveList; + protected boolean whitesTurn = true; + protected DefaultListModel moveList; public Board(DefaultListModel listModel) throws IOException { this.pieces = getPieces(); @@ -115,33 +116,7 @@ public class Board extends JPanel implements MouseListener { } } - private void makeMove(Move move) { - move.movedPiece.move(pieces, move.to); - turnCount++; - whitesTurn = !whitesTurn; - - SchackState state = getSchackState(); - switch (state) { - case SCHACK: - JOptionPane.showMessageDialog(this, "Du står i schack"); - break; - case SCHACKMATT: - case PATT: - String stateStr = state.toString(); - String msg = stateStr.charAt(0) + stateStr.substring(1, stateStr.length()).toLowerCase(); - int choice = JOptionPane.showConfirmDialog(this, msg + "\nVill du starta om?"); - - if (choice == JOptionPane.YES_OPTION) - try { - restartGame(); - } catch (IOException ex) { - } - - break; - default: - } - - } + protected abstract void makeMove(Move move); @Override public void mousePressed(MouseEvent mouseEvent) { @@ -158,7 +133,6 @@ public class Board extends JPanel implements MouseListener { } Move move = new Move(selectedPiece, selectedPiece.position, clickedCoordinate); - moveList.addElement(move); makeMove(move); } else { previouslyClickedPoint = new Point(clickedCoordinate); @@ -168,24 +142,21 @@ public class Board extends JPanel implements MouseListener { // Om vi inte redan har valt en pjäs klickar vi på en pjäs if (!validMovesToDraw.contains(clickedCoordinate)) { Piece selectedPiece = pieces[clickedCoordinate.x][clickedCoordinate.y]; - - if (selectedPiece != null && selectedPiece.isWhite() == whitesTurn) - validMovesToDraw.addAll(selectedPiece.validMoves(pieces, true)); - else - validMovesToDraw = new ArrayList<>(); // Snabbare än .clear - + toDoIfNoPreviousPieceSelected(selectedPiece); } else validMovesToDraw = new ArrayList<>(); // Snabbare än .clear getParent().repaint(); } + protected abstract void toDoIfNoPreviousPieceSelected(Piece selectedPiece); + /** * Få status över brädet * * @return SCHACK, SCHACKMATT, PATT, NORMAL */ - private SchackState getSchackState() { + protected SchackState getSchackState() { List allValidMoves = getMoves(whitesTurn); List opposingAttacks = getAttacks(!whitesTurn); boolean weCanMove = !allValidMoves.isEmpty(); diff --git a/src/main/java/com/billenius/schack/boards/NetworkBoard.java b/src/main/java/com/billenius/schack/boards/NetworkBoard.java new file mode 100644 index 0000000..ae16fbf --- /dev/null +++ b/src/main/java/com/billenius/schack/boards/NetworkBoard.java @@ -0,0 +1,168 @@ +package com.billenius.schack.boards; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Font; +import java.io.EOFException; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Inet4Address; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; + +import javax.swing.DefaultListModel; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; + +import com.billenius.schack.BasicMove; +import com.billenius.schack.Move; +import com.billenius.schack.SchackState; +import com.billenius.schack.pieces.Piece; + +public final class NetworkBoard extends Board implements Runnable { + public final static int PORT = 1339; + private final Socket socket; + private ServerSocket serverSocket = null; + private final ObjectInputStream inputStream; + private final ObjectOutputStream outputStream; + private final Thread inputListener; + private Boolean myColor = null; + + public NetworkBoard(DefaultListModel listModel) throws IOException { + super(listModel); + String[] options = { "Opponent connects to me", "I'am connecting to the opponent" }; + int choosenOption = JOptionPane.showOptionDialog(null, + "Are you going to connect to the opponent or the reverse?", + "Schack: Networking", + JOptionPane.DEFAULT_OPTION, + JOptionPane.INFORMATION_MESSAGE, + null, + options, + options[0]); + + // Nu ska vi bli en Server + if (choosenOption == 0) { + String ip = Inet4Address.getLocalHost().getHostAddress(); + + final JFrame frame = new JFrame("Schack: Networking"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel panel = new JPanel(new BorderLayout()); + panel.setPreferredSize(new Dimension(600, 200)); + + JLabel loading = new JLabel( + "Waiting for opponent to connect...
Listening on " + ip + ":" + PORT + ""); + loading.setFont(new Font("Cantarell", Font.PLAIN, 24)); + loading.setHorizontalAlignment(JLabel.CENTER); + + panel.add(loading, BorderLayout.CENTER); + frame.add(panel); + frame.pack(); + frame.setVisible(true); + serverSocket = new ServerSocket(PORT); + this.socket = serverSocket.accept(); + // myColor = new Random().nextBoolean(); + myColor = true; // VIT + frame.setVisible(false); + + // Get input/output stream + System.out.println("Getting inputstream"); + inputStream = new ObjectInputStream(socket.getInputStream()); + System.out.println("Getting outputstream"); + outputStream = new ObjectOutputStream(socket.getOutputStream()); + } + // Nu ska vi bli en klient + else { + String ip = JOptionPane.showInputDialog(null, + "What's the IP of your opponent?", + "Schack: Networking", + JOptionPane.QUESTION_MESSAGE); + if (ip.equals("")) + ip = "localhost"; + this.socket = new Socket(ip, 1339); + myColor = false; // SVART + + // Get input/output stream + System.out.println("Getting outputstream"); + outputStream = new ObjectOutputStream(socket.getOutputStream()); + System.out.println("Getting inputstream"); + inputStream = new ObjectInputStream(socket.getInputStream()); + } + inputListener = new Thread(this); + inputListener.start(); + } + + @Override + protected void makeMove(Move move) { + try { + turnCount++; + moveList.addElement(move); + move.movedPiece.move(pieces, move.to); + System.out.println("repainting"); + getParent().repaint(); + System.out.println("Sending move to opponent"); + outputStream.writeObject(new BasicMove(move)); + System.out.println("Move sent"); + + } catch (Exception e) { + e.printStackTrace(); + } + + } + + @Override + protected void toDoIfNoPreviousPieceSelected(Piece selectedPiece) { + if (selectedPiece != null && selectedPiece.isWhite() == myColor) + validMovesToDraw.addAll(selectedPiece.validMoves(pieces, true)); + } + + @Override + public void run() { + try { + while (true) { + BasicMove basicMove = (BasicMove) inputStream.readObject(); + Move move = new Move(pieces[basicMove.from.x][basicMove.from.y], basicMove); + System.out.println("Got move"); + moveList.addElement(move); + turnCount++; + + System.out.println("Moving piece"); + move.movedPiece.move(pieces, move.to); + System.out.println("Repainting"); + getParent().repaint(); + + SchackState state = getSchackState(); + switch (state) { + case SCHACK: + JOptionPane.showMessageDialog(this, "Du står i schack"); + break; + case SCHACKMATT: + case PATT: + String stateStr = state.toString(); + String msg = stateStr.charAt(0) + stateStr.substring(1, stateStr.length()).toLowerCase(); + int choice = JOptionPane.showConfirmDialog(this, msg + "\nVill du starta om?"); + + if (choice == JOptionPane.YES_OPTION) + try { + restartGame(); + } catch (IOException ex) { + } + + break; + default: + } + + } + } catch (EOFException | SocketException e) { + JOptionPane.showMessageDialog(this, "Lost connection to opponent"); + } catch (Exception e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(this, e); + } + + } + +} diff --git a/src/main/java/com/billenius/schack/boards/SameBoard.java b/src/main/java/com/billenius/schack/boards/SameBoard.java new file mode 100644 index 0000000..5df047f --- /dev/null +++ b/src/main/java/com/billenius/schack/boards/SameBoard.java @@ -0,0 +1,57 @@ +package com.billenius.schack.boards; + +import java.io.IOException; +import java.util.ArrayList; + +import javax.swing.DefaultListModel; +import javax.swing.JOptionPane; + +import com.billenius.schack.Move; +import com.billenius.schack.SchackState; +import com.billenius.schack.pieces.Piece; + +public final class SameBoard extends Board { + + public SameBoard(DefaultListModel listModel) throws IOException { + super(listModel); + } + + @Override + protected void makeMove(Move move) { + moveList.addElement(move); + move.movedPiece.move(pieces, move.to); + turnCount++; + whitesTurn = !whitesTurn; + + SchackState state = getSchackState(); + switch (state) { + case SCHACK: + JOptionPane.showMessageDialog(this, "Du står i schack"); + break; + case SCHACKMATT: + case PATT: + String stateStr = state.toString(); + String msg = stateStr.charAt(0) + stateStr.substring(1, stateStr.length()).toLowerCase(); + int choice = JOptionPane.showConfirmDialog(this, msg + "\nVill du starta om?"); + + if (choice == JOptionPane.YES_OPTION) + try { + restartGame(); + } catch (IOException ex) { + } + + break; + default: + } + } + + @Override + protected void toDoIfNoPreviousPieceSelected(Piece selectedPiece) { + if (selectedPiece != null && selectedPiece.isWhite() == whitesTurn) + validMovesToDraw.addAll(selectedPiece.validMoves(pieces, true)); + else + validMovesToDraw = new ArrayList<>(); // Snabbare än .clear + + } + +} diff --git a/src/main/java/com/billenius/schack/pieces/Piece.java b/src/main/java/com/billenius/schack/pieces/Piece.java index 843c7cf..202e785 100644 --- a/src/main/java/com/billenius/schack/pieces/Piece.java +++ b/src/main/java/com/billenius/schack/pieces/Piece.java @@ -9,7 +9,7 @@ import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; -import com.billenius.schack.Board; +import com.billenius.schack.boards.Board; public abstract class Piece { @@ -26,40 +26,23 @@ public abstract class Piece { * SPECIAL RULÖES APPLY TO THE KING, (ITS GOOD TO BE THE KING:) */ public boolean supremeRuler = false; - /** - * Bild av pjäsen som ritas ut på bärdet - */ - protected BufferedImage icon; /** * Nödvändigt för rockad */ protected boolean moved = false; + protected BufferedImage pieceIcon; public Piece(boolean white, Point startingPosition) throws IOException { this.isWhite = white; this.position = startingPosition; - setPieceIcon(); + this.pieceIcon = getPieceIcon(); } public Piece(boolean white) { this.isWhite = white; } - /** - * Ladda in pjäsbild från paketet img - * - * @param className - * @throws IOException ifall det inte finns någon bild på pjäsen - */ - private void setPieceIcon() throws IOException { - String className = this.getClass().getSimpleName(); - String colorName = this.isWhite() ? "White" : "Black"; - String fileName = colorName + className + ".png"; - InputStream is = getClass().getResourceAsStream("/com/billenius/img/" + fileName); - icon = ImageIO.read(is); - } - /** * Ger tillbaks alla ställen pjäsen kan gå till * @@ -82,14 +65,22 @@ public abstract class Piece { return validMoves(pieces, false); } + private BufferedImage getPieceIcon() throws IOException { + String colorName = isWhite() ? "White" : "Black"; + String path = "/com/billenius/img/" + colorName + getClass().getSimpleName() + ".png"; + InputStream inputStream = getClass().getResourceAsStream(path); + return ImageIO.read(inputStream); + } + /** * Ritar ut pjäsen baserat på den ihågkommna positionen * * @param g2 */ public void draw(Graphics2D g2) { + g2.drawImage( - icon, + getIcon(), position.x * Board.SIZE_OF_TILE, position.y * Board.SIZE_OF_TILE, null); @@ -211,6 +202,13 @@ public abstract class Piece { return this.getClass().getSimpleName() + "{" + "position=" + position + ", isWhite=" + isWhite + '}'; } + public boolean equals(Piece otherPiece) { + return getClass().getName().equals(otherPiece.getClass().getName()) + && isWhite() == otherPiece.isWhite() + && supremeRuler == otherPiece.supremeRuler && moved == otherPiece.moved + && position.equals(otherPiece.position); + } + /** * * @return true ifall pjäsen är vit @@ -229,7 +227,7 @@ public abstract class Piece { } public BufferedImage getIcon() { - return this.icon; + return this.pieceIcon; } }