Ändra från egotripp till egodipp

This commit is contained in:
2022-12-10 00:02:23 +01:00
parent 3e5bd56780
commit 161e5700c3
30 changed files with 205 additions and 205 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

View File

@@ -0,0 +1,24 @@
package com.limone.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);
}
}

View File

@@ -0,0 +1,20 @@
package com.limone.schack;
import java.awt.Point;
import com.limone.schack.pieces.Piece;
public class Move extends BasicMove {
public Piece movedPiece;
public Move(Piece piece, Point from, Point to) {
super(from, to);
this.movedPiece = piece;
}
public Move(Piece piece, BasicMove basicMove) {
super(basicMove.from, basicMove.to);
this.movedPiece = piece;
}
}

View File

@@ -0,0 +1,25 @@
package com.limone.schack;
import java.awt.Component;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
public class PieceRenderer extends JLabel implements ListCellRenderer<Move> {
@Override
public Component getListCellRendererComponent(JList<? extends Move> list, Move move, int index,
boolean isSelected,
boolean cellHasFocus) {
BufferedImage image = move.movedPiece.getIcon();
ImageIcon ii = new ImageIcon(image.getScaledInstance(40, 40, java.awt.Image.SCALE_SMOOTH));
setIcon(ii);
setText(move.toString());
return this;
}
}

View File

@@ -0,0 +1,167 @@
package com.limone.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;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.UIManager;
import com.formdev.flatlaf.FlatLightLaf;
import com.limone.schack.boards.Board;
import com.limone.schack.boards.NetworkBoard;
import com.limone.schack.boards.SameBoard;
/**
*
* @author Love Billenius & Simon Hansson
*/
public class Schack {
final JFrame frame;
// Förlåt mig fader för jag kommer synda
public final static Map<String, BufferedImage> pieceIcons = new HashMap<>();
public Schack() throws IOException {
// Set theme
try {
if (UIManager.getSystemLookAndFeelClassName()
.equals("javax.swing.plaf.metal.MetalLookAndFeel"))
UIManager.setLookAndFeel(new FlatLightLaf());
else
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} 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<Move> 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);
// Might throw an IOException if the icon of the Pieces isn't embedded correctly
// final Board board = new BlistModeloard(listModel);
// Logger
final JList<Move> jlist = new JList<>(listModel);
jlist.setVisible(true);
jlist.setCellRenderer(new PieceRenderer());
JScrollPane scrollPane = new JScrollPane(jlist);
// scrollPane.setPreferredSize(new Dimension(120, 700));
JPanel logPanel = new JPanel(new BorderLayout());
logPanel.setPreferredSize(new Dimension(120, 800));
JLabel infoText = new JLabel("Moves");
infoText.setFont(new Font("Cantarell", Font.PLAIN, 18));
infoText.setHorizontalAlignment(JLabel.CENTER);
logPanel.add(infoText, BorderLayout.NORTH);
logPanel.add(scrollPane, BorderLayout.CENTER);
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setDividerLocation(800);
splitPane.setLeftComponent(board);
splitPane.setRightComponent(logPanel);
frame.setContentPane(splitPane);
frame.getContentPane().addMouseListener(board);
// Create menu
final JMenuBar menuBar = new JMenuBar();
final JMenu gameMenu = new JMenu("Game");
final JMenu connectMenu = new JMenu("Connect");
final JMenuItem askForRemi = new JMenuItem("Ask for remi");
final JMenuItem surrender = new JMenuItem("Surrender");
final JMenuItem showIP = new JMenuItem("Show IP");
final JMenuItem connectToOpponent = new JMenuItem("Connect to opponent");
askForRemi.addActionListener((ActionEvent ae) -> {
String whosWantingRemi = board.isWhitesTurn() ? "Vit" : "Svart";
int choice = JOptionPane.showConfirmDialog(board, whosWantingRemi + " erbjuder remi\nAccepterar du?");
if (choice == JOptionPane.YES_OPTION) {
choice = JOptionPane.showConfirmDialog(board, "Lika\nStarta om?");
if (choice == JOptionPane.YES_OPTION) {
try {
board.restartGame();
} catch (IOException ex) {
}
}
}
});
surrender.addActionListener((ActionEvent ae) -> {
String whosGivingUp = board.isWhitesTurn() ? "Vit" : "Svart";
int choice = JOptionPane.showConfirmDialog(board, whosGivingUp + " har gett upp\nStarta om?");
if (choice == JOptionPane.YES_OPTION) {
try {
board.restartGame();
} catch (IOException ex) {
}
}
});
showIP.addActionListener((ActionEvent ae) -> {
try {
String ip = Inet4Address.getLocalHost().toString();
JOptionPane.showMessageDialog(null, "IP: " + ip);
} catch (HeadlessException | UnknownHostException e) {
}
});
connectToOpponent.addActionListener((ActionEvent ae) -> {
String opponentIP = JOptionPane.showInputDialog(null, "What's your opponents IP?");
System.out.println("opponents ip: " + opponentIP);
});
// Add the menu stuff
frame.setJMenuBar(menuBar);
menuBar.add(gameMenu);
menuBar.add(connectMenu);
gameMenu.add(askForRemi);
gameMenu.add(surrender);
connectMenu.add(showIP);
connectMenu.add(connectToOpponent);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) throws IOException {
new Schack();
}
}

View File

@@ -0,0 +1,9 @@
package com.limone.schack;
/**
*
* @author love
*/
public enum SchackState {
SCHACK, SCHACKMATT, PATT, NORMAL, REMI
}

View File

@@ -0,0 +1,228 @@
package com.limone.schack.boards;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JPanel;
import com.limone.schack.Move;
import com.limone.schack.SchackState;
import com.limone.schack.pieces.Bishop;
import com.limone.schack.pieces.Horse;
import com.limone.schack.pieces.King;
import com.limone.schack.pieces.Pawn;
import com.limone.schack.pieces.Piece;
import com.limone.schack.pieces.Queen;
import com.limone.schack.pieces.Rook;
public abstract class Board extends JPanel implements MouseListener {
public static final int SIZE_OF_TILE = 100;
protected Piece[][] pieces = new Piece[8][8];
protected List<Point> validMovesToDraw = new ArrayList<>();
private Point previouslyClickedPoint = new Point();
private final Color moveableColor = new Color(255, 191, 0);
short turnCount = 0;
protected boolean whitesTurn = true;
protected DefaultListModel<Move> moveList;
public Board(DefaultListModel<Move> listModel) throws IOException {
this.pieces = getPieces();
setPreferredSize(new Dimension(800, 800));
this.moveList = listModel;
}
/**
* Nollställ brädet
*
* @throws IOException
*/
public void restartGame() throws IOException {
this.pieces = getPieces();
this.whitesTurn = true;
getParent().repaint();
}
private Piece[][] getPieces() throws IOException {
Piece[][] piecesRet = {
{ new Rook(false, new Point(0, 0)), null, null, null, null, null, null,
new Rook(true, new Point(0, 7)) },
{ new Horse(false, new Point(1, 0)), null, null, null, null, null, null,
new Horse(true, new Point(1, 7)) },
{ new Bishop(false, new Point(2, 0)), null, null, null, null, null, null,
new Bishop(true, new Point(2, 7)) },
{ new Queen(false, new Point(3, 0)), null, null, null, null, null, null,
new Queen(true, new Point(3, 7)) },
{ new King(false, new Point(4, 0)), null, null, null, null, null, null,
new King(true, new Point(4, 7)) },
{ new Bishop(false, new Point(5, 0)), null, null, null, null, null, null,
new Bishop(true, new Point(5, 7)) },
{ new Horse(false, new Point(6, 0)), null, null, null, null, null, null,
new Horse(true, new Point(6, 7)) },
{ new Rook(false, new Point(7, 0)), null, null, null, null, null, null,
new Rook(true, new Point(7, 7)) }
};
// Sätt ut bönder
for (int i = 0; i < pieces.length; i++) {
piecesRet[i][1] = new Pawn(false, new Point(i, 1));
piecesRet[i][6] = new Pawn(true, new Point(i, 6));
}
return piecesRet;
}
@Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
drawSquares(g2);
// Måla alla ställen man kan gå till
g2.setColor(moveableColor);
for (Point validMove : validMovesToDraw) {
if (validMove == null) {
continue;
}
g2.fillOval(validMove.x * SIZE_OF_TILE, validMove.y * SIZE_OF_TILE, SIZE_OF_TILE, SIZE_OF_TILE);
}
// Måla alla pjäser
for (Piece[] pieceArr : pieces)
for (Piece piece : pieceArr) {
if (piece == null) {
continue;
}
piece.draw(g2);
}
}
private void drawSquares(Graphics2D g2) {
g2.setBackground(Color.WHITE);
g2.setColor(Color.DARK_GRAY);
for (int i = 0; i < 8; i += 2)
for (int j = 0; j < 8; j += 2) {
g2.fillRect(i * SIZE_OF_TILE, j * SIZE_OF_TILE, SIZE_OF_TILE, SIZE_OF_TILE);
g2.fillRect((i + 1) * SIZE_OF_TILE, (j + 1) * SIZE_OF_TILE, SIZE_OF_TILE, SIZE_OF_TILE);
}
}
protected abstract void makeMove(Move move);
@Override
public void mousePressed(MouseEvent mouseEvent) {
final int mouseCoordinateX = (int) (mouseEvent.getX() / SIZE_OF_TILE);
final int mouseCoordinateY = (int) (mouseEvent.getY() / SIZE_OF_TILE);
final Point clickedCoordinate = new Point(mouseCoordinateX, mouseCoordinateY);
// Ifall vi har tryckt på en pjäs och sedan ska gå dit
if (validMovesToDraw.contains(clickedCoordinate)) {
Piece selectedPiece = pieces[previouslyClickedPoint.x][previouslyClickedPoint.y];
if (selectedPiece == null) {
validMovesToDraw.clear();
return;
}
Move move = new Move(selectedPiece, selectedPiece.position, clickedCoordinate);
makeMove(move);
} else {
previouslyClickedPoint = new Point(clickedCoordinate);
validMovesToDraw = new ArrayList<>(); // Snabbare än .clear
}
// 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];
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
*/
protected SchackState getSchackState() {
List<Point> allValidMoves = getMoves(whitesTurn);
List<Point> opposingAttacks = getAttacks(!whitesTurn);
boolean weCanMove = !allValidMoves.isEmpty();
boolean inSchack = false;
for (Point attack : opposingAttacks) {
final Piece attacked = pieces[attack.x][attack.y];
if (attacked == null)
continue;
if (attacked.supremeRuler) {
inSchack = true;
validMovesToDraw = new ArrayList<>(); // Snabbare än .clear
getParent().repaint();
if (weCanMove)
return SchackState.SCHACK;
else
return SchackState.SCHACKMATT;
}
}
if (!inSchack && !weCanMove)
return SchackState.PATT;
return SchackState.NORMAL;
}
private List<Point> getMoves(boolean whiteMovesAreWanted) {
List<Point> allValidMoves = new ArrayList<>();
for (Piece[] pieceArr : pieces)
for (Piece piece : pieceArr) {
if (piece == null || whiteMovesAreWanted != piece.isWhite())
continue;
allValidMoves.addAll(piece.validMoves(pieces, true));
}
return allValidMoves;
}
public List<Point> getAttacks(boolean whiteAttacksAreWanted) {
List<Point> attacks = new ArrayList<>();
for (Piece[] pieceArr : pieces)
for (Piece piece : pieceArr) {
if (piece == null || whiteAttacksAreWanted != piece.isWhite())
continue;
attacks.addAll(piece.validAttacks(pieces, true));
}
return attacks;
}
public boolean isWhitesTurn() {
return whitesTurn;
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent mouseEvent) {
}
}

View File

@@ -0,0 +1,168 @@
package com.limone.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.limone.schack.BasicMove;
import com.limone.schack.Move;
import com.limone.schack.SchackState;
import com.limone.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<Move> 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(
"<html>Waiting for opponent to connect...<br/>Listening on <i>" + ip + ":" + PORT + "</i></html>");
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);
}
}
}

View File

@@ -0,0 +1,57 @@
package com.limone.schack.boards;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;
import com.limone.schack.Move;
import com.limone.schack.SchackState;
import com.limone.schack.pieces.Piece;
public final class SameBoard extends Board {
public SameBoard(DefaultListModel<Move> 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
}
}

View File

@@ -0,0 +1,21 @@
package com.limone.schack.pieces;
import java.awt.Point;
import java.io.IOException;
import java.util.List;
public class Bishop extends LongWalkers {
public Bishop(boolean isWhite, Point startingPosition) throws IOException {
super(isWhite, startingPosition);
}
@Override
public List<Point> validMoves(Piece[][] pieces, boolean allowedToRecurse) {
return getMoves(
new int[][] { { -1, -1 }, { 1, 1 }, { -1, 1 }, { 1, -1 } },
pieces,
allowedToRecurse);
}
}

View File

@@ -0,0 +1,29 @@
package com.limone.schack.pieces;
import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Horse extends Piece {
public Horse(boolean isWhite, Point startingPosition) throws IOException {
super(isWhite, startingPosition);
}
@Override
public List<Point> validMoves(Piece[][] pieces, boolean allowedToRecurse) {
List<Point> movable = new ArrayList<>();
for (int dx : new int[] { -2, -1, 1, 2 }) {
for (int direction : new int[] { -1, 1 }) {
int stepLength = (3 - Math.abs(dx)),
dy = direction * stepLength;
Point potentialMove = new Point(this.position.x + dx, this.position.y + dy);
addMovesIfCan(potentialMove, movable, pieces, allowedToRecurse);
}
}
return movable;
}
}

View File

@@ -0,0 +1,101 @@
package com.limone.schack.pieces;
import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public final class King extends Piece {
public King(boolean isWhite, Point startingPosition) throws IOException {
super(isWhite, startingPosition);
supremeRuler = true;
}
/**
* Få en ArrayList med möjliga rockader
*
* @param pieces
* @return
*/
private List<Point> getCastlingIfPossible(Piece[][] pieces) {
List<Point> possibleCastling = new ArrayList<>();
if (this.isMoved()) {
return possibleCastling;
}
boolean[] somethingBetweenOrSchackOnTheWay = new boolean[2]; // Vänster, höger
int leftModifier = -1, rightModifier = 1;
for (int modifier : new int[] { leftModifier, rightModifier }) {
for (int loopX = this.position.x + modifier; loopX > 0 && loopX < 7; loopX += modifier) {
if (pieces[loopX][this.position.y] != null || isInSchack(pieces, new Point(loopX, this.position.y))) {
somethingBetweenOrSchackOnTheWay[(modifier == leftModifier) ? 0 : 1] = true;
break;
}
}
}
leftModifier = 0;
rightModifier = 1;
for (int direction : new int[] { leftModifier, rightModifier }) {
if (!somethingBetweenOrSchackOnTheWay[direction]) {
Piece possibleRook = pieces[direction == leftModifier ? 0 : 7][this.position.y];
if (possibleRook != null && !possibleRook.isMoved()) {
possibleCastling.add(new Point(direction == leftModifier ? 2 : 6, this.position.y));
}
}
}
return possibleCastling;
}
/**
* Gör en rockad
*
* @param pieces
* @param shouldGoToLeftSide avgör ifall rockaden är åt vänster håll
*/
private void castle(Piece[][] pieces, boolean shouldGoToLeftSide) {
Piece rook = pieces[shouldGoToLeftSide ? 0 : 7][this.position.y];
Piece king = this;
// Null där de stod
pieces[king.position.x][king.position.y] = null;
pieces[rook.position.x][rook.position.y] = null;
// Uppdatera internt minne
king.position.x = shouldGoToLeftSide ? 2 : 6;
rook.position.x = shouldGoToLeftSide ? 3 : 5;
// Uppdatera brädet
pieces[king.position.x][king.position.y] = king;
pieces[rook.position.x][rook.position.y] = rook;
}
@Override
public void move(Piece[][] pieces, Point toMove) {
if (Math.abs(position.x - toMove.x) == 2) {
boolean goToLeftSide = toMove.x < 5;
castle(pieces, goToLeftSide);
} else {
super.move(pieces, toMove);
}
}
@Override
public List<Point> validMoves(Piece[][] pieces, boolean allowedToRecurse) {
List<Point> movable = new ArrayList<>();
for (int loopX = -1; loopX < 2; loopX++) {
for (int loopY = -1; loopY < 2; loopY++) {
if (loopY == 0 && loopX == 0) {
continue;
}
addMovesIfCan(new Point(this.position.x + loopX, this.position.y + loopY), movable, pieces,
allowedToRecurse);
}
}
if (allowedToRecurse && !isInSchack(pieces)) {
movable.addAll(getCastlingIfPossible(pieces));
}
return movable;
}
}

View File

@@ -0,0 +1,49 @@
package com.limone.schack.pieces;
import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public abstract class LongWalkers extends Piece {
public LongWalkers(boolean isWhite, Point startingPosition) throws IOException {
super(isWhite, startingPosition);
}
/**
* Generell metod för att generera möjliga drag för LongWalkers
*
* @param directions vilka håll. Exempel:
*
* <pre>
* {@code
* new int[][] { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } }
* }</pre>
*
* för att gå
* som ett torn
*
* @param pieces
* @param allowedToRecurse
* @return
*/
List<Point> getMoves(int[][] directions, Piece[][] pieces, boolean allowedToRecurse) {
List<Point> movable = new ArrayList<>();
for (int[] xy : directions) {
int loopX = this.position.x, loopY = this.position.y;
while (loopX + xy[0] >= 0 && loopX + xy[0] <= 7 && loopY + xy[1] >= 0 && loopY + xy[1] <= 7) {
loopX += xy[0];
loopY += xy[1];
boolean shouldBreak = addMovesIfCan(new Point(loopX, loopY), movable, pieces, allowedToRecurse);
if (shouldBreak) {
break;
}
}
}
return movable;
}
}

View File

@@ -0,0 +1,149 @@
package com.limone.schack.pieces;
import java.awt.HeadlessException;
import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
public class Pawn extends Piece {
public Pawn(boolean isWhite, Point startingPosition) throws IOException {
super(isWhite, startingPosition);
}
/**
* Ger tillbaks alla ställen pjäsen kan attackera
*
* @param pieces
* @param shouldNotCareIfAttackSpaceIsEmptyOrNot Ifall man ska kolla ifall
* det är något i möjliga
* attackrutor ifall
* @return Alla lämpliga attackMoves
*/
@Override
public List<Point> validAttacks(Piece[][] pieces, boolean shouldNotCareIfAttackSpaceIsEmptyOrNot) {
List<Point> movable = new ArrayList<>();
// Kolla ifall vi kan ta någon
for (int pawnX : new int[] { -1, 1 }) {
// Position vi kollar just nu, snett upp åt höger & vänster
Point pos = new Point(this.position.x + pawnX, this.position.y + (this.isWhite() ? -1 : 1));
if (pos.x < 0 || pos.x > 7 || pos.y < 0 || pos.y > 7)
continue;
Piece piece = pieces[pos.x][pos.y];
if (piece == null || piece.isWhite() != this.isWhite()
|| (shouldNotCareIfAttackSpaceIsEmptyOrNot && piece.isWhite() != this.isWhite()))
movable.add(pos);
}
return movable;
}
@Override
public List<Point> validMoves(Piece[][] pieces, boolean allowedToRecurse) {
List<Point> movable = new ArrayList<>();
// Om bonden har gått en gång, får gå 1 steg, annars 2
final int upTo = this.isMoved() ? 1 : 2;
// Kolla om man kan gå rakt frak
for (int pawnDY = 1; pawnDY <= upTo; pawnDY++) {
final Point pos = new Point(this.position.x, this.position.y + (this.isWhite() ? -pawnDY : pawnDY));
boolean shouldBreak = addMovesIfCan(pos, movable, pieces, allowedToRecurse);
if (shouldBreak)
break;
}
// Kolla ifall vi kan ta någon
for (int pawnX : new int[] { -1, 1 }) {
// Position vi kollar just nu, snett upp åt höger & vänster
final Point pos = new Point(this.position.x + pawnX, this.position.y + (this.isWhite() ? -1 : 1));
movable.addAll(addAttackMovesIfCan(pos, pieces));
}
return movable;
}
// Känns som det här skulle kunnat vara i validMoves, men nu är det såhär
/**
* Ifall det är en pjäs som står här och den inte är samma färg som oss,
* lägg till i listan
*
* @param pos
* @param movable
* @param pieces
*/
private List<Point> addAttackMovesIfCan(Point pos, Piece[][] pieces) {
List<Point> movable = new ArrayList<>();
// Se till att vi inte är utanför brädet
if (pos.x >= pieces.length || pos.x < 0 || pos.y >= pieces[0].length || pos.y < 0)
return movable;
final Piece potentialEnemy = pieces[pos.x][pos.y];
// Ifall det är tomt här, gör ingenting
if (potentialEnemy != null && potentialEnemy.isWhite() != this.isWhite()) {
if (!isInSchack(pieces, pos)) {
movable.add(pos);
}
}
return movable;
}
@Override
protected boolean addMovesIfCan(Point pos, List<Point> movable, Piece[][] pieces, boolean allowedToRecurse) {
if (pos.x < 0 || pos.x > 7 || pos.y < 0 || pos.y > 7)
return false;
Piece pieceToCheck = pieces[pos.x][pos.y];
if (pieceToCheck == null) {
if (!isInSchack(pieces, pos))
movable.add(pos);
return false;
}
return true;
}
@Override
public void move(Piece[][] pieces, Point toMove) {
super.move(pieces, toMove);
// Check if the pawn has moved to the end and should be transformed
if (this.position.y == 0 && this.isWhite()
|| this.position.y == 7 && !this.isWhite())
transform(pieces);
}
private void transform(Piece[][] pieces) throws HeadlessException {
String[] transformations = { "Queen", "Rook", "Bishop", "Horse" };
int choosenTransformations = JOptionPane.showOptionDialog(null,
"What do you want to the pawn to transform into?",
"Pawn about to transform",
JOptionPane.DEFAULT_OPTION,
JOptionPane.INFORMATION_MESSAGE,
null,
transformations,
transformations[0]);
try {
switch (choosenTransformations) {
case 0:
pieces[position.x][position.y] = new Queen(this.isWhite(), this.position);
break;
case 1:
pieces[position.x][position.y] = new Rook(this.isWhite(), this.position);
break;
case 2:
pieces[position.x][position.y] = new Bishop(this.isWhite(), this.position);
break;
default:
pieces[position.x][position.y] = new Horse(this.isWhite(), this.position);
break;
}
} catch (IOException ioe) {
System.out.println(ioe);
}
}
}

View File

@@ -0,0 +1,233 @@
package com.limone.schack.pieces;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import com.limone.schack.boards.Board;
public abstract class Piece {
/**
* Variabel som alltid bör vara samma värde som pjäsen är i brädes av
* Piece[][]
*/
public Point position;
/**
* Sant ifall pjäsens färg är vit, falskt ifall den är svart
*/
private final boolean isWhite;
/**
* SPECIAL RULÖES APPLY TO THE KING, (ITS GOOD TO BE THE KING:)
*/
public boolean supremeRuler = false;
/**
* 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;
this.pieceIcon = getPieceIcon();
}
public Piece(boolean white) {
this.isWhite = white;
}
/**
* Ger tillbaks alla ställen pjäsen kan gå till
*
* @param pieces
* @param allowedToRecurse
* @return
*/
public abstract List<Point> validMoves(Piece[][] pieces, boolean allowedToRecurse);
/**
* Ger tillbaks alla ställen pjäsen kan attackera
*
* @param pieces
* @param shouldNotCareIfAttackSpaceIsEmptyOrNot För bönder ifall den ska
* kolla ifall det är något i
* möjliga attackrutor ifall
* @return Alla lämpliga attackMoves
*/
public List<Point> validAttacks(Piece[][] pieces, boolean shouldNotCareIfAttackSpaceIsEmptyOrNot) {
return validMoves(pieces, false);
}
private BufferedImage getPieceIcon() throws IOException {
String colorName = isWhite() ? "White" : "Black";
String path = "/com/limone/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(
getIcon(),
position.x * Board.SIZE_OF_TILE,
position.y * Board.SIZE_OF_TILE,
null);
}
/**
* Flyttar pjäsen till toMove och tar bort det som tidigare var där
*
* @param pieces
* @param toMove
*/
public void move(Piece[][] pieces, Point toMove) {
// Gör ingenting ifall vi är utanför brädet
if (toMove.x >= pieces.length || toMove.y < 0 || position.x >= pieces[0].length || position.y < 0) {
return;
}
pieces[toMove.x][toMove.y] = this;
pieces[position.x][position.y] = null;
this.position = new Point(toMove);
this.moved = true;
}
/**
* Lägg till move ifall det går, alltså inte är schack där
*
* @param pos Drag att lägga till ifall det går
* @param movable Lägger till drag i denna ArrayList
* @param pieces Piece[][] över brädet
* @param allowedToRecurse Behövs för att inte gå in i en evig loop där
*
* <pre>{@code addMovesIfCan -> isInSchack -> validMoves -> getCastlingIfPossible(King) -> isInSchack}</pre>
*
* @return true ifall man inte kan gå längre i denna riktning
*/
protected boolean addMovesIfCan(Point pos, List<Point> movable, Piece[][] pieces, boolean allowedToRecurse) {
// Ifall vi är utanför brädet ge tillbaka false
if (pos.x > 7 || pos.x < 0 || pos.y > 7 || pos.y < 0)
return false;
Piece pieceToCheck = pieces[pos.x][pos.y];
// Detta är en tom plats
if (pieceToCheck == null) {
if (!allowedToRecurse || !isInSchack(pieces, pos))
movable.add(pos);
return false;
}
/**
* Ifall det är en pjäs i motståndarlaget här kan vi ta den men inte gå
* längre Ifall det är samma färg som oss betyder det att vi inte kan
* lägga till den
*/
if ((pieceToCheck.isWhite() != this.isWhite())
&& ((allowedToRecurse && !isInSchack(pieces, pos)) || !allowedToRecurse))
movable.add(pos);
return true;
}
/**
* Kolla ifall det är schack vid den här positionen
*
* @param pieces Piece[][] över hela brädet
* @param pos Kollar ifall det är schack om denna Piece flyttar hit
* @return true ifall det är schack
*/
protected boolean isInSchack(Piece[][] pieces, Point pos) {
// Kom ihåg vart vi var
Point previousPosition = new Point(this.position);
// Kom ihåg motståndarpjäs
Piece guyThatsAlreadyHere = pieces[pos.x][pos.y];
// Testa att flytta
pieces[pos.x][pos.y] = this;
pieces[previousPosition.x][previousPosition.y] = null;
this.position = pos;
boolean inSchack = isInSchack(pieces);
// Flytta tillbaka
pieces[previousPosition.x][previousPosition.y] = this;
pieces[pos.x][pos.y] = guyThatsAlreadyHere;
this.position = previousPosition;
return inSchack;
}
/**
* Kolla ifall det är schack
*
* @param pieces Piece[][] över hela brädet
* @return true ifall det är schack
*/
protected boolean isInSchack(Piece[][] pieces) {
List<Point> enemyAttacks = new ArrayList<>();
// Fråga alla pjäser vart de kan gå/ta
for (Piece[] pieceArr : pieces)
for (Piece piece : pieceArr)
if (piece != null && piece.isWhite != this.isWhite())
// Lägg till alla attacker för mostståndaren
enemyAttacks.addAll(piece.validAttacks(pieces, false));
// Kollar ifall kungen står i schack just nu
for (Point enemyAttack : enemyAttacks) {
Piece attackedPiece = pieces[enemyAttack.x][enemyAttack.y];
if (attackedPiece != null && attackedPiece.supremeRuler)
return true;
}
return false;
}
@Override
public String toString() {
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
*/
public boolean isWhite() {
return isWhite;
}
/**
* Kompabilitet med PieceKnownIfMoved
*
* @return false
*/
public boolean isMoved() {
return moved;
}
public BufferedImage getIcon() {
return this.pieceIcon;
}
}

View File

@@ -0,0 +1,20 @@
package com.limone.schack.pieces;
import java.awt.Point;
import java.io.IOException;
import java.util.List;
public class Queen extends LongWalkers {
public Queen(boolean isWhite, Point point) throws IOException {
super(isWhite, point);
}
@Override
public List<Point> validMoves(Piece[][] pieces, boolean allowedToRecurse) {
return getMoves(
new int[][] { { 1, 0 }, { -1, 0 }, { 0, 1 }, { -1, -1 }, { 0, -1 }, { 1, 1 }, { -1, 1 }, { 1, -1 } },
pieces,
allowedToRecurse);
}
}

View File

@@ -0,0 +1,21 @@
package com.limone.schack.pieces;
import java.awt.Point;
import java.io.IOException;
import java.util.List;
public class Rook extends LongWalkers {
public Rook(boolean isWhite, Point startingPosition) throws IOException {
super(isWhite, startingPosition);
}
@Override
public List<Point> validMoves(Piece[][] pieces, boolean allowedToRecurse) {
return getMoves(
new int[][] { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } },
pieces,
allowedToRecurse);
}
}