diff --git a/GITCOMMANDS.md b/GITCOMMANDS.md new file mode 100644 index 0000000..38a2424 --- /dev/null +++ b/GITCOMMANDS.md @@ -0,0 +1,22 @@ +#### Branch. Lag alltid en ny branch hver gang du jobber med noe nytt. +- git branch // Viser de tilgjengelige branchene +- git checkout -b // lager ny branch +- git branch -d // sletter branch + +#### Navn på branch +- Kun små bokstaver og "-" indikerer mellomrom +- initialler/navn-på-branch +- Eksempel: hnl/oppdatere-readme + +#### Hvordan pulle(hente) endringer. Gjøres hver gang man skal jobbe. +- git status +- git switch main +- git pull +- git switch <ønsket branch> +- git main //sørge for at din branch er oppdatert med main + +#### Hvordan pushe endringer. +- git add . // legger til endringer i staging area +- git commit -m “Hva du har gjort” // lagrer add endringene i den lokale git historien din. +- git push -u origin //sender de lokale endringene i git historien til de eksterne repositoriet. Nå kan andre hente endringene. Husk å lage en pull request. Bare git push hvis man har pushet branchen før. +- Lag en pull request på github hvor du spør en annen om å godkjenne hva du har gjort diff --git a/Model/Bishop.java b/Model/Bishop.java new file mode 100644 index 0000000..4940dfe --- /dev/null +++ b/Model/Bishop.java @@ -0,0 +1,46 @@ +package Model; + +// Bishop.java +public class Bishop extends Piece { + + public Bishop(Color color, int row, int col) { + super(color, row, col, color == Color.WHITE ? "resources/white_bishop.png" : "resources/black_bishop.png"); + } + + @Override + public boolean isValidMove(int startRow, int startCol, int endRow, int endCol, Board board) { + int rowDiff = Math.abs(endRow - startRow); + int colDiff = Math.abs(endCol - startCol); + + if (rowDiff != colDiff) { + return false; // Bishops move diagonally + } + + // Check for obstructions in the path + int rowStep = (endRow > startRow) ? 1 : -1; + int colStep = (endCol > startCol) ? 1 : -1; + int row = startRow + rowStep; + int col = startCol + colStep; + + while (row != endRow) { + if (board.getPiece(row, col) != null) { + return false; // Path is blocked + } + row += rowStep; + col += colStep; + } + + // Check if the destination square has a piece of the same color + Piece destinationPiece = board.getPiece(endRow, endCol); + if (destinationPiece != null && destinationPiece.getColor() == getColor()) { + return false; + } + + return true; + } + + @Override + public PieceType getType() { + return PieceType.BISHOP; + } +} \ No newline at end of file diff --git a/Model/Board.java b/Model/Board.java new file mode 100644 index 0000000..9e16507 --- /dev/null +++ b/Model/Board.java @@ -0,0 +1,90 @@ +package Model; + +// Board.java +public class Board { + private Piece[][] board; + private static final int BOARD_SIZE = 8; + + public Board() { + board = new Piece[BOARD_SIZE][BOARD_SIZE]; + initializeBoard(); + } + + public void initializeBoard() { + // Initialize white pieces + board[7][0] = new Rook(Piece.Color.WHITE, 7, 0); + board[7][1] = new Knight(Piece.Color.WHITE, 7, 1); + board[7][2] = new Bishop(Piece.Color.WHITE, 7, 2); + board[7][3] = new Queen(Piece.Color.WHITE, 7, 3); + board[7][4] = new King(Piece.Color.WHITE, 7, 4); + board[7][5] = new Bishop(Piece.Color.WHITE, 7, 5); + board[7][6] = new Knight(Piece.Color.WHITE, 7, 6); + board[7][7] = new Rook(Piece.Color.WHITE, 7, 7); + for (int i = 0; i < 8; i++) { + board[6][i] = new Pawn(Piece.Color.WHITE, 6, i); + } + + // Initialize black pieces + board[0][0] = new Rook(Piece.Color.BLACK, 0, 0); + board[0][1] = new Knight(Piece.Color.BLACK, 0, 1); + board[0][2] = new Bishop(Piece.Color.BLACK, 0, 2); + board[0][3] = new Queen(Piece.Color.BLACK, 0, 3); + board[0][4] = new King(Piece.Color.BLACK, 0, 4); + board[0][5] = new Bishop(Piece.Color.BLACK, 0, 5); + board[0][6] = new Knight(Piece.Color.BLACK, 0, 6); + board[0][7] = new Rook(Piece.Color.BLACK, 0, 7); + for (int i = 0; i < 8; i++) { + board[1][i] = new Pawn(Piece.Color.BLACK, 1, i); + } + + // Initialize empty squares + for (int row = 2; row < 6; row++) { + for (int col = 0; col < 8; col++) { + board[row][col] = null; + } + } + } + + public Piece getPiece(int row, int col) { + if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE) { + return null; // Out of bounds + } + return board[row][col]; + } + + public void setPiece(int row, int col, Piece piece) { + board[row][col] = piece; + } + + public void movePiece(int startRow, int startCol, int endRow, int endCol) { + Piece piece = getPiece(startRow, startCol); + if (piece != null) { + board[endRow][endCol] = piece; + board[startRow][startCol] = null; + piece.setRow(endRow); // Update the piece's position + piece.setCol(endCol); + } + } + + public static int getBoardSize(){ + return BOARD_SIZE; + } + + public void printBoard() { + for (int row = 0; row < BOARD_SIZE; row++) { + System.out.print(8 - row + " |"); // Print row number for better readability + + for (int col = 0; col < BOARD_SIZE; col++) { + Piece piece = getPiece(row, col); + if (piece == null) { + System.out.print(" . "); // Empty square + } else { + System.out.print(" " + piece + " "); // Print piece representation + } + } + System.out.println("|"); + } + System.out.println(" --------------------------------"); + System.out.println(" a b c d e f g h"); // Print column letters + } +} \ No newline at end of file diff --git a/Model/Game.java b/Model/Game.java new file mode 100644 index 0000000..7427a27 --- /dev/null +++ b/Model/Game.java @@ -0,0 +1,112 @@ +package Model; + +// Game.java +import java.util.Scanner; + +public class Game { + private Board board; + private Player player1; + private Player player2; + private Player currentPlayer; + private boolean gameOver; + + public Game(String player1Name, String player2Name) { + board = new Board(); + player1 = new Player(player1Name, Piece.Color.WHITE); + player2 = new Player(player2Name, Piece.Color.BLACK); + currentPlayer = player1; + gameOver = false; + } + + public void startGame() { + Scanner scanner = new Scanner(System.in); + + while (!gameOver) { + board.printBoard(); + System.out.println(currentPlayer.getName() + "'s turn (" + currentPlayer.getColor() + ")"); + System.out.print("Enter move (e.g., 'a2 a4'): "); + String moveStr = scanner.nextLine(); + + if (moveStr.equalsIgnoreCase("quit")) { + System.out.println("Game ended."); + break; + } + + try { + Move move = parseMove(moveStr); + + if (isValidMove(move)) { + executeMove(move); + switchTurn(); + } else { + System.out.println("Invalid move. Try again."); + } + } catch (IllegalArgumentException e) { + System.out.println("Invalid move format. Use 'a2 a4' format."); + } + } + + scanner.close(); + } + + private Move parseMove(String moveStr) { + String[] parts = moveStr.split(" "); + if (parts.length != 2) { + throw new IllegalArgumentException("Invalid move format"); + } + + String startSq = parts[0].trim().toLowerCase(); + String endSq = parts[1].trim().toLowerCase(); + + int startCol = startSq.charAt(0) - 'a'; + int startRow = 8 - Integer.parseInt(startSq.substring(1)); // Assuming row input is 1-8 + int endCol = endSq.charAt(0) - 'a'; + int endRow = 8 - Integer.parseInt(endSq.substring(1)); + + Piece movedPiece = board.getPiece(startRow, startCol); + Piece capturedPiece = board.getPiece(endRow, endCol); + + if (movedPiece == null) { + throw new IllegalArgumentException("No piece at starting square."); + } + return new Move(startRow, startCol, endRow, endCol, movedPiece, capturedPiece); + } + + private boolean isValidMove(Move move) { + int startRow = move.getStartRow(); + int startCol = move.getStartCol(); + int endRow = move.getEndRow(); + int endCol = move.getEndCol(); + Piece piece = move.getMovedPiece(); + + if (piece.getColor() != currentPlayer.getColor()) { + System.out.println("Not your piece."); + return false; + } + + if (endRow < 0 || endRow >= Board.getBoardSize() || endCol < 0 || endCol >= Board.getBoardSize()) { + System.out.println("Out of bounds move."); + return false; + } + + return piece.isValidMove(startRow, startCol, endRow, endCol, board); + } + + private void executeMove(Move move) { + int startRow = move.getStartRow(); + int startCol = move.getStartCol(); + int endRow = move.getEndRow(); + int endCol = move.getEndCol(); + Piece piece = move.getMovedPiece(); + + board.movePiece(startRow, startCol, endRow, endCol); + + //TODO: Implement promotion logic + + //Check for game over conditions (checkmate, stalemate) - not implemented in this example + } + + private void switchTurn() { + currentPlayer = (currentPlayer == player1) ? player2 : player1; + } +} \ No newline at end of file diff --git a/Model/King.java b/Model/King.java new file mode 100644 index 0000000..fb70fc4 --- /dev/null +++ b/Model/King.java @@ -0,0 +1,65 @@ +package Model; + +// King.java +public class King extends Piece { + + private boolean hasMoved; // Flag to track if the King has moved (for castling) + + public King(Color color, int row, int col) { + super(color, row, col, color == Color.WHITE ? "resources/white_king.png" : "resources/black_king.png"); + this.hasMoved = false; + } + + public boolean hasMoved() { + return hasMoved; + } + + public void setHasMoved(boolean hasMoved) { + this.hasMoved = hasMoved; + } + + @Override + public boolean isValidMove(int startRow, int startCol, int endRow, int endCol, Board board) { + int rowDiff = Math.abs(endRow - startRow); + int colDiff = Math.abs(endCol - startCol); + + if (rowDiff > 1 || colDiff > 1) { + //Check for castling + if (!hasMoved && rowDiff == 0 && colDiff == 2){ + //Check that the spaces are empty + int direction = (endCol > startCol) ? 1 : -1; + for (int col = startCol + direction; col != endCol; col += direction){ + if (board.getPiece(startRow, col) != null){ + return false; + } + } + + //Check that the rook is there and hasn't moved + int rookCol = (direction == 1) ? 7 : 0; + Piece rook = board.getPiece(startRow, rookCol); + if (rook instanceof Rook){ + Rook realRook = (Rook) rook; + //TODO: Implement hasMoved for rook + return true; + } + return false; + } + return false; // King can only move one square in any direction + } + + // Check if the destination square has a piece of the same color + Piece destinationPiece = board.getPiece(endRow, endCol); + if (destinationPiece != null && destinationPiece.getColor() == getColor()) { + return false; + } + + //TODO: Add Check checking logic + + return true; + } + + @Override + public PieceType getType() { + return PieceType.KING; + } +} \ No newline at end of file diff --git a/Model/Knight.java b/Model/Knight.java new file mode 100644 index 0000000..8d55172 --- /dev/null +++ b/Model/Knight.java @@ -0,0 +1,32 @@ +package Model; + +// Knight.java +public class Knight extends Piece { + + public Knight(Color color, int row, int col) { + super(color, row, col, color == Color.WHITE ? "resources/white_knight.png" : "resources/black_knight.png"); + } + + @Override + public boolean isValidMove(int startRow, int startCol, int endRow, int endCol, Board board) { + int rowDiff = Math.abs(endRow - startRow); + int colDiff = Math.abs(endCol - startCol); + + if (!((rowDiff == 2 && colDiff == 1) || (rowDiff == 1 && colDiff == 2))) { + return false; // Knights move in an L-shape + } + + // Check if the destination square has a piece of the same color + Piece destinationPiece = board.getPiece(endRow, endCol); + if (destinationPiece != null && destinationPiece.getColor() == getColor()) { + return false; + } + + return true; + } + + @Override + public PieceType getType() { + return PieceType.KNIGHT; + } +} \ No newline at end of file diff --git a/Model/Main.java b/Model/Main.java new file mode 100644 index 0000000..e13adb9 --- /dev/null +++ b/Model/Main.java @@ -0,0 +1,9 @@ +package Model; + +// Main.java +public class Main { + public static void main(String[] args) { + Game game = new Game("Alice", "Bob"); + game.startGame(); + } +} \ No newline at end of file diff --git a/Model/Move.java b/Model/Move.java new file mode 100644 index 0000000..eb88b0c --- /dev/null +++ b/Model/Move.java @@ -0,0 +1,53 @@ +package Model; + +// Move.java +public class Move { + private int startRow; + private int startCol; + private int endRow; + private int endCol; + private Piece movedPiece; + private Piece capturedPiece; //Optional + + public Move(int startRow, int startCol, int endRow, int endCol, Piece movedPiece, Piece capturedPiece) { + this.startRow = startRow; + this.startCol = startCol; + this.endRow = endRow; + this.endCol = endCol; + this.movedPiece = movedPiece; + this.capturedPiece = capturedPiece; + } + + public Move(int startRow, int startCol, int endRow, int endCol, Piece movedPiece) { + this.startRow = startRow; + this.startCol = startCol; + this.endRow = endRow; + this.endCol = endCol; + this.movedPiece = movedPiece; + this.capturedPiece = null; + } + + public int getStartRow() { + return startRow; + } + + public int getStartCol() { + return startCol; + } + + public int getEndRow() { + return endRow; + } + + public int getEndCol() { + return endCol; + } + + public Piece getMovedPiece() { + return movedPiece; + } + + public Piece getCapturedPiece() { + return capturedPiece; + } +} \ No newline at end of file diff --git a/Model/Pawn.java b/Model/Pawn.java new file mode 100644 index 0000000..25d8bc7 --- /dev/null +++ b/Model/Pawn.java @@ -0,0 +1,53 @@ +package Model; + +// Pawn.java +public class Pawn extends Piece { + + public Pawn(Color color, int row, int col) { + super(color, row, col, color == Color.WHITE ? "resources/white_pawn.png" : "resources/black_pawn.png"); + } + + @Override + public boolean isValidMove(int startRow, int startCol, int endRow, int endCol, Board board) { + int rowDiff = endRow - startRow; + int colDiff = Math.abs(endCol - startCol); + Color color = getColor(); + + if (colDiff > 1) { + return false; // Can only move one column to capture + } + + if (color == Color.WHITE) { + if (rowDiff > 0) return false; // White pawns move up (decreasing row number) + if (rowDiff == 0) return false; // White pawns move up (decreasing row number) + + if (colDiff == 0) { // Moving straight + if (rowDiff == -1 && board.getPiece(endRow, endCol) == null) return true; // One square forward + + if (startRow == 6 && rowDiff == -2 && board.getPiece(endRow, endCol) == null && board.getPiece(endRow + 1, endCol) == null) { + //Two squares from start + return true; + } + } else { // Capturing diagonally + if (rowDiff == -1 && colDiff == 1 && board.getPiece(endRow, endCol) != null && board.getPiece(endRow, endCol).getColor() == Color.BLACK) return true; // Capture + } + } else { // Black pawn + if (rowDiff < 0) return false; // Black pawns move down (increasing row number) + if (rowDiff == 0) return false; + + if (colDiff == 0) { // Moving straight + if (rowDiff == 1 && board.getPiece(endRow, endCol) == null) return true; // One square forward + if (startRow == 1 && rowDiff == 2 && board.getPiece(endRow, endCol) == null && board.getPiece(endRow - 1, endCol) == null) return true; // Two squares from start + } else { // Capturing diagonally + if (rowDiff == 1 && colDiff == 1 && board.getPiece(endRow, endCol) != null && board.getPiece(endRow, endCol).getColor() == Color.WHITE) return true; // Capture + } + } + + return false; + } + + @Override + public PieceType getType() { + return PieceType.PAWN; + } +} \ No newline at end of file diff --git a/Model/Piece.java b/Model/Piece.java new file mode 100644 index 0000000..d2e5eaf --- /dev/null +++ b/Model/Piece.java @@ -0,0 +1,75 @@ +package Model; + +// Piece.java +import java.awt.Image; +import javax.swing.ImageIcon; + +public abstract class Piece { + private Color color; + private int row; + private int col; + private String imagePath; // Path to the image file (e.g., "resources/white_pawn.png") + + + public Piece(Color color, int row, int col, String imagePath) { + this.color = color; + this.row = row; + this.col = col; + this.imagePath = imagePath; + } + + public Color getColor() { + return color; + } + + public int getRow() { + return row; + } + + public int getCol() { + return col; + } + + public void setRow(int row) { + this.row = row; + } + + public void setCol(int col) { + this.col = col; + } + + public String getImagePath() { + return imagePath; + } + + public Image getImage() { + ImageIcon icon = new ImageIcon(getClass().getClassLoader().getResource(imagePath)); + return icon.getImage(); + } + + // Abstract method to define valid moves for each piece type + public abstract boolean isValidMove(int startRow, int startCol, int endRow, int endCol, Board board); + + public abstract PieceType getType(); + + + public enum Color { + WHITE, + BLACK + } + + public enum PieceType { + PAWN, + ROOK, + KNIGHT, + BISHOP, + QUEEN, + KING + } + + + @Override + public String toString() { + return color.toString().charAt(0) + getType().toString().substring(0, 1); // e.g., WP for White Pawn + } +} \ No newline at end of file diff --git a/Model/Player.java b/Model/Player.java new file mode 100644 index 0000000..ce6654e --- /dev/null +++ b/Model/Player.java @@ -0,0 +1,19 @@ +package Model; + +public class Player { + private String name; + private Piece.Color color; + + public Player(String name, Piece.Color color) { + this.name = name; + this.color = color; + } + + public String getName() { + return name; + } + + public Piece.Color getColor() { + return color; + } +} \ No newline at end of file diff --git a/Model/Queen.java b/Model/Queen.java new file mode 100644 index 0000000..bcf6284 --- /dev/null +++ b/Model/Queen.java @@ -0,0 +1,74 @@ +package Model; + +// Queen.java +public class Queen extends Piece { + + public Queen(Color color, int row, int col) { + super(color, row, col, color == Color.WHITE ? "resources/white_queen.png" : "resources/black_queen.png"); + } + + @Override + public boolean isValidMove(int startRow, int startCol, int endRow, int endCol, Board board) { + // Queen combines Rook and Bishop movement + + // Rook-like movement + if (startRow == endRow || startCol == endCol) { + // Check for obstructions (same as Rook) + if (startRow == endRow) { // Horizontal movement + int step = (endCol > startCol) ? 1 : -1; + for (int col = startCol + step; col != endCol; col += step) { + if (board.getPiece(startRow, col) != null) { + return false; // Path is blocked + } + } + } else { // Vertical movement + int step = (endRow > startRow) ? 1 : -1; + for (int row = startRow + step; row != endRow; row += step) { + if (board.getPiece(row, startCol) != null) { + return false; // Path is blocked + } + } + } + + // Check if the destination square has a piece of the same color + Piece destinationPiece = board.getPiece(endRow, endCol); + if (destinationPiece != null && destinationPiece.getColor() == getColor()) { + return false; + } + return true; + } + + // Bishop-like movement + int rowDiff = Math.abs(endRow - startRow); + int colDiff = Math.abs(endCol - startCol); + + if (rowDiff == colDiff) { + // Check for obstructions (same as Bishop) + int rowStep = (endRow > startRow) ? 1 : -1; + int colStep = (endCol > startCol) ? 1 : -1; + int row = startRow + rowStep; + int col = startCol + colStep; + + while (row != endRow) { + if (board.getPiece(row, col) != null) { + return false; // Path is blocked + } + row += rowStep; + col += colStep; + } + // Check if the destination square has a piece of the same color + Piece destinationPiece = board.getPiece(endRow, endCol); + if (destinationPiece != null && destinationPiece.getColor() == getColor()) { + return false; + } + return true; + } + + return false; + } + + @Override + public PieceType getType() { + return PieceType.QUEEN; + } +} \ No newline at end of file diff --git a/Model/Rook.java b/Model/Rook.java new file mode 100644 index 0000000..a0d3efc --- /dev/null +++ b/Model/Rook.java @@ -0,0 +1,46 @@ +package Model; + +// Rook.java +public class Rook extends Piece { + + public Rook(Color color, int row, int col) { + super(color, row, col, color == Color.WHITE ? "resources/white_rook.png" : "resources/black_rook.png"); + } + + @Override + public boolean isValidMove(int startRow, int startCol, int endRow, int endCol, Board board) { + if (startRow != endRow && startCol != endCol) { + return false; // Rooks move horizontally or vertically + } + + // Check for obstructions in the path + if (startRow == endRow) { // Horizontal movement + int step = (endCol > startCol) ? 1 : -1; + for (int col = startCol + step; col != endCol; col += step) { + if (board.getPiece(startRow, col) != null) { + return false; // Path is blocked + } + } + } else { // Vertical movement + int step = (endRow > startRow) ? 1 : -1; + for (int row = startRow + step; row != endRow; row += step) { + if (board.getPiece(row, startCol) != null) { + return false; // Path is blocked + } + } + } + + // Check if the destination square has a piece of the same color + Piece destinationPiece = board.getPiece(endRow, endCol); + if (destinationPiece != null && destinationPiece.getColor() == getColor()) { + return false; + } + + return true; + } + + @Override + public PieceType getType() { + return PieceType.ROOK; + } +} \ No newline at end of file