Reputation: 13
Me and a buddy are making a chess game from scratch using Java for our AP Computer Science class, and we need to get the coordinates for the final square after the mouse is released. .getX()
and .getY()
give us the exact coordinates, but we want the grid coordinate. Like 5,4 or 3,2 (in chess, this would be e4 or c2). The definition classes are all working fine, we just need this part:
System.out.print(e.getX()+" "+e.getY());
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
if (c instanceof JLabel){
Container parent = c.getParent();
parent.remove(0);
parent.add( chessPiece );
}
else {
Container parent = (Container)c;
parent.add( chessPiece );
}
chessPiece.setVisible(true);
}
Full implementation class is below. Thanks in advance!
package Boards;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ChessGame extends JFrame implements MouseListener, MouseMotionListener {
private static final long serialVersionUID = 1L;//Serial ID for unique chess games
JLayeredPane layeredPane;
JPanel chessBoard;
JLabel chessPiece;
int xAdjustment;
int yAdjustment;
public ChessGame(){
Board newGame = new Board();//Instantiate Board object w/ spots
newGame.boardSetUp();
Dimension boardSize = new Dimension(600, 600);//Instantiate Visual representation of Board.
// Use a Layered Pane for this this application
layeredPane = new JLayeredPane();
getContentPane().add(layeredPane);
layeredPane.setPreferredSize(boardSize);
layeredPane.addMouseListener(this);
layeredPane.addMouseMotionListener(this);
//Add a chess board to the Layered Pane
chessBoard = new JPanel();
layeredPane.add(chessBoard, JLayeredPane.DEFAULT_LAYER);
chessBoard.setLayout( new GridLayout(8, 8) );
chessBoard.setPreferredSize( boardSize );
chessBoard.setBounds(0, 0, boardSize.width, boardSize.height);
JLabel Vpiece = new JLabel();
for (int i = 0; i < 64; i++) {
JPanel square = new JPanel( new BorderLayout() );
chessBoard.add( square );
int row = (i / 8);
if (row%2 == 0)
square.setBackground( i % 2 == 0 ? Color.darkGray : Color.white );//Adjusting for First square
else
square.setBackground( i % 2 == 0 ? Color.white : Color.darkGray );//Setting colored boxes for chess board
if(newGame.spotValues[row][i-(row*8)].piece!=null)
{
switch(newGame.spotValues[row][i-(row*8)].piece.name){
case "Bishop":
if(newGame.spotValues[row][i-(row*8)].piece.color.equals("White"))
Vpiece = new JLabel( new ImageIcon("resource/BishopW.png") );
else
Vpiece = new JLabel( new ImageIcon("resource/BishopB.png") );
break;
case "King":
if(newGame.spotValues[row][i-(row*8)].piece.color.equals("White"))
Vpiece = new JLabel( new ImageIcon("resource/KingW.png" ));
else
Vpiece = new JLabel( new ImageIcon("resource/KingB.png" ));
break;
case "Queen":
if(newGame.spotValues[row][i-(row*8)].piece.color.equals("White"))
Vpiece = new JLabel( new ImageIcon("resource/QueenW.png") );
else
Vpiece = new JLabel( new ImageIcon("resource/QueenB.png") );
break;
case "Pawn":
if(newGame.spotValues[row][i-(row*8)].piece.color.equals("White"))
Vpiece = new JLabel( new ImageIcon("resource/PawnW.png") );
else
Vpiece = new JLabel( new ImageIcon("resource/PawnB.png") );
break;
case "Rook":
if(newGame.spotValues[row][i-(row*8)].piece.color.equals("White"))
Vpiece = new JLabel( new ImageIcon("resource/RookW.png") );
else
Vpiece = new JLabel( new ImageIcon("resource/RookB.png") );
break;
case "Knight":
if(newGame.spotValues[row][i-(row*8)].piece.color.equals("White"))
Vpiece = new JLabel( new ImageIcon("resource/KnightW.png") );
else
Vpiece = new JLabel( new ImageIcon("resource/KnightB.png") );
break;
}
JPanel panel = (JPanel)chessBoard.getComponent(i);
panel.add(Vpiece);
}
}
}
public void mousePressed(MouseEvent e){
chessPiece = null;
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
if (c instanceof JPanel)
return; //makes sure no errors are given when pressed on a blank square
Point parentLocation = c.getParent().getLocation(); //parentLocation is mouse pointer
xAdjustment = parentLocation.x - e.getX();
yAdjustment = parentLocation.y - e.getY();
chessPiece = (JLabel)c;
chessPiece.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);
chessPiece.setSize(chessPiece.getWidth(), chessPiece.getHeight());
layeredPane.add(chessPiece, JLayeredPane.DRAG_LAYER);
}
//Move the chess piece around
public void mouseDragged(MouseEvent me) {
if (chessPiece == null) { //checks if square is blank or not
return;
}
chessPiece.setLocation(me.getX() + xAdjustment, me.getY() + yAdjustment);
}
//Drop the chess piece back onto the chess board
public void mouseReleased(MouseEvent e) {
if(chessPiece == null) { //checks if square is blank or not
return;
}
chessPiece.setVisible(false);
/*
* what are we doing below??
*
*
*/
System.out.print(e.getX()+" "+e.getY());
Component c = chessBoard.findComponentAt(e.getX(), e.getY()); //checks to see if there's a new piece at the new location
if (c instanceof JLabel){
Container parent = c.getParent();
parent.remove(0);
parent.add( chessPiece );
}
else {
Container parent = (Container)c;
parent.add( chessPiece );
}
chessPiece.setVisible(true);
}
/*
*
* what are we doing above??
*
*/
public void mouseClicked(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
public void mouseEntered(MouseEvent e){
}
public void mouseExited(MouseEvent e) {
}
public static void main(String[] args) {
JFrame frame = new ChessGame();
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE );
frame.pack();
frame.setResizable(true);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
Upvotes: 1
Views: 1392
Reputation: 285403
As noted in comments, I would use a grid of JLabel, and add and remove icons, and would give my JLabel a client property value that corresponds to the appropriate row and column (file and rank in chess terminology). I would give my ChessBoard class two String constants to use when putting client properties in and when later extracting them:
public static final String RANK = "rank";
public static final String FILE = "file";
You add the properties by simply calling putClientProperty(...)
on the JLabel:
label.putClientProperty(RANK, rank);
label.putClientProperty(FILE, file);
where rank and file are appropriate Strings.
For example, please run this demo program to see what I mean:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class SimpleChess extends JPanel {
private ChessBoard chessBoard = new ChessBoard();
private JTextField rankField = new JTextField(3);
private JTextField fileField = new JTextField(3);
public SimpleChess() {
MyMouse myMouse = new MyMouse();
chessBoard.addMouseListener(myMouse);
rankField.setHorizontalAlignment(SwingConstants.CENTER);
rankField.setFocusable(false);
fileField.setHorizontalAlignment(SwingConstants.CENTER);
fileField.setFocusable(false);
JPanel topPanel = new JPanel();
topPanel.add(new JLabel("Rank:"));
topPanel.add(rankField);
topPanel.add(Box.createHorizontalStrut(40));
topPanel.add(new JLabel("File:"));
topPanel.add(fileField);
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(chessBoard, BorderLayout.CENTER);
}
class MyMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
Component c = chessBoard.getComponentAt(e.getPoint());
if (!(c instanceof JLabel)) {
return;
}
JLabel cell = (JLabel) c;
String rank = (String) cell.getClientProperty(ChessBoard.RANK);
String file = (String) cell.getClientProperty(ChessBoard.FILE);
// icon = cell.getIcon();
rankField.setText(rank);
fileField.setText(file);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Chess");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SimpleChess());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
@SuppressWarnings("serial")
class ChessBoard extends JPanel {
public static final String RANK = "rank";
public static final String FILE = "file";
private static final int ROWS = 8;
private static final int COLS = 8;
private static final Color COLOR_LIGHT = new Color(240, 201, 175);
private static final Color COLOR_DARK = new Color(205, 133, 63);
private static final Dimension CELL_SIZE = new Dimension(60, 60);
private JLabel[][] chessTable = new JLabel[ROWS][COLS];
public ChessBoard() {
// create chess table
setLayout(new GridLayout(ROWS, COLS));
for (int i = 0; i < chessTable.length; i++) {
for (int j = 0; j < chessTable[i].length; j++) {
String rank = String.valueOf((char) ('8' - i));
String file = String.valueOf((char) ('a' + j));
JLabel label = new JLabel();
label.setPreferredSize(CELL_SIZE);
label.setOpaque(true);
Color c = i % 2 == j % 2 ? COLOR_LIGHT : COLOR_DARK;
label.setBackground(c);
label.putClientProperty(RANK, rank);
label.putClientProperty(FILE, file);
chessTable[i][j] = label;
add(label);
}
}
}
}
I was working on a more extensive version, one that moved Icons around, but haven't finished it yet....
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
public class ChessLocation extends JPanel {
public static final String RANK = "rank";
public static final String FILE = "file";
public static final String MOUSE_PRESS = "mouse press";
public static final String PIECE_IMG_PATH = "https://upload.wikimedia.org"
+ "/wikipedia/commons/thumb/b/b2/Chess_Pieces_Sprite.svg"
+ "/320px-Chess_Pieces_Sprite.svg.png"; // for smaller pieces
// + "/640px-Chess_Pieces_Sprite.svg.png"; // for larger pieces
private static final int IMG_ROWS = 2;
private static final int IMG_COLS = 6;
private static final int ROWS = 8;
private static final int COLS = 8;
private static final Color COLOR_LIGHT = new Color(240, 201, 175);
private static final Color COLOR_DARK = new Color(205, 133, 63);
private Map<ChessPiece, Icon> pieceIconMap = new HashMap<>();
private JLabel[][] chessTable = new JLabel[ROWS][COLS];
public ChessLocation(BufferedImage img) {
// get chess images and put into pieceIconMap
int w = img.getWidth() / IMG_COLS;
int h = img.getHeight() / IMG_ROWS;
for (int row = 0; row < IMG_ROWS; row++) {
int y = (row * img.getHeight()) / IMG_ROWS;
for (int col = 0; col < IMG_COLS; col++) {
int x = (col * img.getWidth()) / IMG_COLS;
BufferedImage subImg = img.getSubimage(x, y, w, h);
Icon icon = new ImageIcon(subImg);
PieceColor color = PieceColor.values()[row];
PieceType type = PieceType.values()[col];
ChessPiece chessPiece = new ChessPiece(type, color);
pieceIconMap.put(chessPiece, icon);
}
}
// create chess table
setLayout(new GridLayout(ROWS, COLS));
Dimension pieceSize = new Dimension(w, h);
for (int i = 0; i < chessTable.length; i++) {
for (int j = 0; j < chessTable[i].length; j++) {
String rank = String.valueOf((char) ('8' - i));
String file = String.valueOf((char) ('a' + j));
JLabel label = new JLabel();
label.setPreferredSize(pieceSize);
label.setOpaque(true);
Color c = i % 2 == j % 2 ? COLOR_LIGHT : COLOR_DARK;
label.setBackground(c);
label.putClientProperty(RANK, rank);
label.putClientProperty(FILE, file);
chessTable[i][j] = label;
add(label);
}
}
resetBoard();
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
}
public void resetBoard() {
for (JLabel[] row : chessTable) {
for (JLabel cell : row) {
cell.setIcon(null);
}
}
chessTable[0][0].setIcon(pieceIconMap.get(new ChessPiece(PieceType.ROOK, PieceColor.BLACK)));
chessTable[0][7].setIcon(pieceIconMap.get(new ChessPiece(PieceType.ROOK, PieceColor.BLACK)));
chessTable[7][0].setIcon(pieceIconMap.get(new ChessPiece(PieceType.ROOK, PieceColor.WHITE)));
chessTable[7][7].setIcon(pieceIconMap.get(new ChessPiece(PieceType.ROOK, PieceColor.WHITE)));
chessTable[0][1].setIcon(pieceIconMap.get(new ChessPiece(PieceType.KNIGHT, PieceColor.BLACK)));
chessTable[0][6].setIcon(pieceIconMap.get(new ChessPiece(PieceType.KNIGHT, PieceColor.BLACK)));
chessTable[7][1].setIcon(pieceIconMap.get(new ChessPiece(PieceType.KNIGHT, PieceColor.WHITE)));
chessTable[7][6].setIcon(pieceIconMap.get(new ChessPiece(PieceType.KNIGHT, PieceColor.WHITE)));
chessTable[0][2].setIcon(pieceIconMap.get(new ChessPiece(PieceType.BISHOP, PieceColor.BLACK)));
chessTable[0][5].setIcon(pieceIconMap.get(new ChessPiece(PieceType.BISHOP, PieceColor.BLACK)));
chessTable[7][2].setIcon(pieceIconMap.get(new ChessPiece(PieceType.BISHOP, PieceColor.WHITE)));
chessTable[7][5].setIcon(pieceIconMap.get(new ChessPiece(PieceType.BISHOP, PieceColor.WHITE)));
chessTable[0][3].setIcon(pieceIconMap.get(new ChessPiece(PieceType.QUEEN, PieceColor.BLACK)));
chessTable[0][4].setIcon(pieceIconMap.get(new ChessPiece(PieceType.KING, PieceColor.BLACK)));
chessTable[7][3].setIcon(pieceIconMap.get(new ChessPiece(PieceType.QUEEN, PieceColor.WHITE)));
chessTable[7][4].setIcon(pieceIconMap.get(new ChessPiece(PieceType.KING, PieceColor.WHITE)));
// put in pawns
for (int i = 0; i < PieceColor.values().length; i++) {
PieceColor color = PieceColor.values()[i];
ChessPiece piece = new ChessPiece(PieceType.PAWN, color);
for (int j = 0; j < COLS; j++) {
int row = 6 - 5 * i;
chessTable[row][j].setIcon(pieceIconMap.get(piece));
}
}
}
private class MyMouse extends MouseAdapter {
String rank = "";
String file = "";
Icon icon = null;
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
rank = "";
file = "";
icon = null;
Component c = getComponentAt(e.getPoint());
if (!(c instanceof JLabel)) {
return;
}
JLabel cell = (JLabel) c;
if (cell.getIcon() == null) {
return;
}
rank = (String) cell.getClientProperty(RANK);
file = (String) cell.getClientProperty(FILE);
icon = cell.getIcon();
// cell.setIcon(null);
}
}
private static void createAndShowGui() {
BufferedImage img = null;
try {
URL imgUrl = new URL(PIECE_IMG_PATH);
img = ImageIO.read(imgUrl);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
ChessLocation chessLocation = new ChessLocation(img);
JFrame frame = new JFrame("Chess");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(chessLocation);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
enum PieceColor {
WHITE, BLACK
}
enum PieceType {
KING(100), QUEEN(9), BISHOP(3), KNIGHT(3), ROOK(5), PAWN(1);
private int value;
private PieceType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
class ChessPiece {
private PieceType type;
private PieceColor color;
public ChessPiece(PieceType type, PieceColor color) {
this.type = type;
this.color = color;
}
@Override
public String toString() {
return "ChessPiece [type=" + type + ", color=" + color + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((color == null) ? 0 : color.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ChessPiece other = (ChessPiece) obj;
if (color != other.color)
return false;
if (type != other.type)
return false;
return true;
}
}
Upvotes: 1
Reputation: 826
Java coordinate system starts from the top left corner and coordinates increase as you go down and right. So for any width x height
chess board expected row and column intervals would be something like this:
// X coordinates
A: 0.0 - (width / 8)
B: (width / 8) - (2 * width / 8)
C: (2 * width / 8) - (3 * width / 8)
...
// Y coordinates
8: 0.0 - (width / 8)
7: (width / 8) - (2 * width / 8)
6: (2 * width / 8) - (3 * width / 8)
...
I would suggest you to use Map
. Here, I did not integrate the following snippet into your code. However it basically takes two Double
inputs and outputs a chess board cell, works with any given width and height for the chess board:
import java.util.HashMap;
import java.util.Map;
public class chessCell {
static final int CELL_COUNT = 8;
// Dimensions
static final double HEIGHT = 600;
static final double WIDTH = 600;
static Map<String, String> columnAsLetter = new HashMap<String, String>(){{
put( "8", "a");
put( "7", "b");
put( "6", "c");
put( "5", "d");
put( "4", "e");
put( "3", "f");
put( "2", "g");
put( "1", "h");
}};
static Map<String, String> rows = new HashMap<String, String>(){{
for(int i = 0; i < CELL_COUNT; i++) {
put(Integer.toString(i + 1), (Double.toString(HEIGHT - (i + 1) * HEIGHT / 8 ) + "-" + Double.toString(HEIGHT - i * HEIGHT / 8)));
}
}};
static Map<String, String> columns = new HashMap<String, String>(){{
for(int i = 0; i < CELL_COUNT; i++) {
put(Integer.toString(i + 1), (Double.toString(WIDTH - (i + 1) * WIDTH / 8 ) + "-" + Double.toString(WIDTH - i * WIDTH / 8)));
}
}};
public static String coord2cellName(double x, double y) {
String column = "";
String row = "";
for(int i = rows.size(); i > 0; i--) {
if(x > Double.parseDouble(rows.get(Integer.toString(i)).split("-")[0]) &&
x <= Double.parseDouble(rows.get(Integer.toString(i)).split("-")[1])){
row = Integer.toString(i);
}
if(y > Double.parseDouble(columns.get(Integer.toString(i)).split("-")[0]) &&
y <= Double.parseDouble(columns.get(Integer.toString(i)).split("-")[1])){
column = columnAsLetter.get(Integer.toString(i));
}
}
System.out.println(column + row);
return column + row;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
coord2cellName(125.0, 155.0); // outputs c7
coord2cellName(24.0, 34.0); // outputs a8
coord2cellName(32.0, 88.0); // outputs b8
}
}
getX()
and getY()
should be returning Double
. So I believe once you understand the code above you can easily integrate it into your project. It is not perfect. I didn't handle out-of-board situation. But the essential part works.
Upvotes: 0