/* Chess game, by [REDACTED]
* written for [REDACTED]
* [REDACTED]
* (c) 2013
*
* All code is original, pretty much all of it is pretty sloppy.
*
* GRAND EXPLANATIONS OF METHODS:
*
* Chess(): Sets size and makes the board obviously. Creates
* ContentPane.
* CreateTitlePanel(): Creates the word "Chess" at the top.
* CreateBoardPanel(): Uses the 2D Array Board to create an 8x8
* grid that holds all the buttons. Sets the
* actionCommand according to this four character
* code: <color><piece><row><column>
* CreateInstructionPanel(): Creates the instruction panel and all
* the game-effecting buttons.
* actionPerformed(): Makes the buttons work, but more importantly,
* divides user clicks into "piece1" and "piece2",
* piece1 being the first click they clicked and
* piece2 being the second one, then calls the
* methods to make sure the move is legal and,
* if it is, goes about changing it. Then, it
* checks if there's a pawn promotion, if anyone
* won, etc etc.
* rules(): Clicking the rules button calls this. All it does is explains
* how to move, castle etc.
* backHandler(): If you click the back button this calls. It resets the
* board to it's previous position using the storeBoard
* 3D Array
* fowardHandler(): The opposite. If you go undo going back this will
* move you up the storeBoard array.
* checkSide(): Makes sure you're moving the correct color. Prevents
* anyone from going twice.
* CheckDir(): Makes sure the piece is the right direction. Bishops
* can't go straight etc etc.
* CheckCol(): Makes sure the piece pathing is clear, nothing is
* in the way.
* Castle(): Handles castling.
* verify(): Changes the board array if the move is legal. Also stores
* the board configuration in storeBoard in case you want to
* go back.
* makeChanges(): Redraws the board.
* CheckWon(): Checks if any side is missing its king.
* CheckPromo(): Checks if a pawn managed to get to the opposite side.
* promo(int, int): Promotes a pawn by changing its ID in the board
* array.
* winMessage(String): Tells you you won if you won.
* initialFill(): Sets up the board to start. Adds all the IDs on the
* 3D Arrays in the correct places.
* main(String[]): Creates the board and sets it up, sets the color to
* white to start the game.
*
* BOARD IDS:
* They are in the format <color><piece>. Here's the characters:
*
* W: White
* B: Black
*
* P: Pawn
* R: Rook
* H: Knight (Horse)
* B: Bishop
* Q: Queen
* K: King
*
* piece1 and piece2 are in a similar format, but the 3rd character
* is the row and the 4th is the column. Numbers go from the
* upper left, so the upper left hand corner is 0,0 and the
* lower right hand corner is 7,7.
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class Chess extends JFrame implements ActionListener {
public static char color;
public static String[][] board = new String[8][8];
public static String piece1 = "";
public static String piece2 = "";
public static String[][][] storeBoard = new String[8][8][1000];
public static int curLoc = 0;
public static int storedLoc = 0;
public static boolean overFlow = true;
public Container contentPane;
public JPanel boardPanel;
public JPanel instructionPanel;
public Chess() {
super();
contentPane = new Container();
setSize(800, 800);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Chess");
contentPane = getContentPane();
contentPane.setBackground(Color.white);
contentPane.setLayout(new BorderLayout());
createTitlePanel();
createBoardPanel();
createInstructionPanel();
}
public void createTitlePanel() {
Font fontType = new Font("Georgia", Font.BOLD, 50);
JPanel titlePanel = new JPanel();
titlePanel.setLayout(new FlowLayout());
titlePanel.setBackground(Color.white);
JLabel label1 = new JLabel("Chess");
label1.setFont(fontType);
label1.setForeground(Color.black);
titlePanel.add(label1);
contentPane.add(titlePanel, BorderLayout.NORTH);
}
public void createBoardPanel() {
boardPanel = new JPanel();
boardPanel.setLayout(new GridLayout(8,8));
boardPanel.setBackground(Color.white);
for(int r=0;r<8;r++)
for(int c=0;c<8;c++){
ImageIcon image;
if(board[r][c].equals("BP"))
image = new ImageIcon("blackpawn.png");
else if(board[r][c].equals("BR"))
image = new ImageIcon("blackrook.png");
else if(board[r][c].equals("BH"))
image = new ImageIcon("blackknight.png");
else if(board[r][c].equals("BB"))
image = new ImageIcon("blackbishop.png");
else if(board[r][c].equals("BQ"))
image = new ImageIcon("blackqueen.png");
else if(board[r][c].equals("BK"))
image = new ImageIcon("blackking.png");
else if(board[r][c].equals("WP"))
image = new ImageIcon("whitepawn.png");
else if(board[r][c].equals("WR"))
image = new ImageIcon("whiterook.png");
else if(board[r][c].equals("WH"))
image = new ImageIcon("whiteknight.png");
else if(board[r][c].equals("WB"))
image = new ImageIcon("whitebishop.png");
else if(board[r][c].equals("WQ"))
image = new ImageIcon("whitequeen.png");
else if(board[r][c].equals("WK"))
image = new ImageIcon("whiteking.png");
else image = new ImageIcon("");
JButton button = new JButton();
button.setIcon(image);
button.addActionListener(this);
button.setBackground(Color.white);
button.setActionCommand(board[r][c]+r+c);
boardPanel.add(button);
}
contentPane.add(boardPanel, BorderLayout.CENTER);
}
public void createInstructionPanel(){
Font fontType = new Font("Georgia", Font.BOLD, 17);
instructionPanel = new JPanel();
instructionPanel.setLayout(new BorderLayout());
instructionPanel.setBackground(Color.white);
JPanel topPanel = new JPanel();
topPanel.setLayout(new GridLayout(1,2));
topPanel.setBackground(Color.white);
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new GridLayout(1,3));
bottomPanel.setBackground(Color.white);
if(color=='B'){
JLabel label = new JLabel("Black turn. " +
"Pick piece and destination.");
label.setFont(fontType);
label.setForeground(Color.black);
topPanel.add(label);
}
else {
JLabel label = new JLabel
("White turn. Pick piece and destination.");
label.setFont(fontType);
label.setForeground(Color.black);
topPanel.add(label);
}
JButton rulesButton = new JButton("How to Play");
rulesButton.setFont(fontType);
rulesButton.addActionListener(this);
rulesButton.setBackground(Color.white);
topPanel.add(rulesButton);
JButton clearButton = new JButton
("Clear last click.");
clearButton.setFont(fontType);
clearButton.addActionListener(this);
clearButton.setBackground(Color.white);
bottomPanel.add(clearButton);
JButton backButton = new JButton("Go back one move.");
backButton.setFont(fontType);
backButton.addActionListener(this);
backButton.setBackground(Color.white);
bottomPanel.add(backButton);
JButton fowardButton = new JButton("Go foward one move.");
fowardButton.setFont(fontType);
fowardButton.addActionListener(this);
fowardButton.setBackground(Color.white);
bottomPanel.add(fowardButton);
instructionPanel.add(topPanel, BorderLayout.NORTH);
instructionPanel.add(bottomPanel, BorderLayout.SOUTH);
contentPane.add(instructionPanel, BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent event) {
if(event.getActionCommand().equals("How to Play"))
rules();
else if(event.getActionCommand().equals
("Clear last click.")){
piece1 = "";
piece2 = "";
}
else if(event.getActionCommand().equals
("Go back one move.")) {
if(curLoc>0 || !overFlow) backHandler();
}
else if(event.getActionCommand().equals
("Go foward one move.")) {
if(curLoc<storedLoc) fowardHandler();
}
else {
if(piece1.isEmpty()) piece1 = event.getActionCommand();
else piece2 = event.getActionCommand();
if(piece1.length()>0 && piece2.length()>0) {
if(giveUp()) System.exit(0);
if((piece1!=piece2 && checkSide() && checkDir()
&& checkCol()) || castle()) {
if(!castle()) verify();
if(color=='B') color = 'W';
else color = 'B';
makeChanges();
checkPromo();
makeChanges();
String won = checkWon();
if(!won.equals("nope")) {
winMessage(won);
System.exit(0);
}
}
piece1 = "";
piece2 = "";
}
}
}
public static void rules() {
JOptionPane.showMessageDialog(null,"How to play David's Chess:" +
"\nClick a piece and where to move it to move." +
"\nTo castle, click the king and the rook\n" +
"when there is no spaces between them and\n" +
"neither piece has moved.\n\n" +
"Clear last click will resolve most problems.");
}
public void backHandler() {
if(curLoc==0 && overFlow) {
curLoc=1000;
overFlow=false;
}
else curLoc--;
for(int r=0;r<8;r++)
for(int c=0;c<8;c++)
board[r][c]=storeBoard[r][c][curLoc];
if(color=='B') color = 'W';
else color = 'B';
makeChanges();
}
public void fowardHandler() {
if(curLoc==1000 && storedLoc>1000){
curLoc=0;
overFlow=true;
}
else curLoc++;
for(int r=0;r<8;r++)
for(int c=0;c<8;c++)
board[r][c]=storeBoard[r][c][curLoc];
if(color=='B') color = 'W';
else color = 'B';
makeChanges();
}
public static boolean giveUp() {
if(piece1.equals(piece2) &&
piece1.charAt(0)==color &&
piece1.charAt(1)=='K'){
String[] choices = {"Yes","No"};
int choice = JOptionPane.showOptionDialog
(null, "Really give up?","Chess", 0, 3,
null, choices, null);
if(choice == 0) return true;
}
return false;
}
public static boolean checkSide() {
return color==piece1.charAt(0);
}
public static boolean checkDir() {
//rook
if(piece1.charAt(1)=='R')
if(piece1.charAt(2)==piece2.charAt(2)
|| piece1.charAt(3)==piece2.charAt(3))
return true;
//horsey
if(piece1.charAt(1)=='H'){
if(Math.abs((int)(piece1.charAt(2))-
(int)(piece2.charAt(2)))==2 &&
Math.abs((int)(piece1.charAt(3))
-(int)(piece2.charAt(3)))==1)
return true;
if(Math.abs((int)(piece1.charAt(3))-
(int)(piece2.charAt(3)))==2 &&
Math.abs((int)(piece1.charAt(2))
-(int)(piece2.charAt(2)))==1)
return true;
}
//bishop
if(piece1.charAt(1)=='B'){
if(Math.abs((int)(piece1.charAt(2))-
(int)(piece2.charAt(2)
))==Math.abs((int)(piece1.charAt(3))
-(int)(piece2.charAt(3))))
return true;
}
//queen
if(piece1.charAt(1)=='Q'){
if(Math.abs((int)(piece1.charAt(2))-
(int)(piece2.charAt(2)
))==Math.abs((int)(piece1.charAt(3))
-(int)(piece2.charAt(3))))
return true;
if(piece1.charAt(2)==piece2.charAt(2)
|| piece1.charAt(3)==piece2.charAt(3))
return true;
}
//king
if(piece1.charAt(1)=='K'){
if(Math.abs((int)(piece1.charAt(2))
-(int)(piece2.charAt(2)))<=1
&& Math.abs((int)(piece1.charAt(3))
-(int)(piece2.charAt(3)))<=1)
return true;
}
//pawn
if(piece1.charAt(1)=='P'){
if(piece1.charAt(2)==piece2.charAt(2)) return false;
if(Math.abs((int)(piece1.charAt(2))
-(int)(piece2.charAt(2)))==1
&& piece1.charAt(3)==(int)
(piece2.charAt(3)) &&
piece2.charAt(0)==' ')
return true;
else if(Math.abs((int)(piece1.charAt(2))
-(int)(piece2.charAt(2)))==2
&& piece1.charAt(3)==(int)
(piece2.charAt(3)) &&
(piece1.charAt(2)=='6'
|| piece1.charAt(2)=='1' &&
piece2.charAt(0)==' '))
return true;
char opColor;
if(color=='W') opColor = 'B';
else opColor='W';
if(Math.abs((int)(piece1.charAt(2))
-(int)(piece2.charAt(2)))==1
&& Math.abs((int)(piece1.charAt(3))
-(int)(piece2.charAt(3)))==1
&& piece2.charAt(0)==opColor)
return true;
}
return false;
}
public static boolean checkCol() {
//knight
if(piece1.charAt(1)=='H'){
if(piece2.charAt(0)!=color)
return true;
else return false;
}
//horizontal check
else if(piece1.charAt(2)==piece2.charAt(2)) {
int row = (int)(piece1.charAt(2))-48;
int cLow = Math.min((int)(piece1.charAt(3))-48,
(int)(piece2.charAt(3))-48);
int cHigh = Math.max((int)(piece1.charAt(3))-48,
(int)(piece2.charAt(3))-48);
for(int i=cLow;i<=cHigh;i++)
if(board[row][i].charAt(0)==color &&
!board[row][i].equals
(piece1.substring(0,2)))
return false;
}
//vertical check
else if(piece1.charAt(3)==piece2.charAt(3)) {
int col = (int)(piece1.charAt(3))-48;
int rLow = Math.min((int)(piece1.charAt(2))-48,
(int)(piece2.charAt(2))-48);
int rHigh = Math.max((int)(piece1.charAt(2))-48,
(int)(piece2.charAt(2))-48);
for(int i=rLow;i<=rHigh;i++)
if(board[i][col].charAt(0)==color &&
!board[i][col].equals
(piece1.substring(0,2)))
return false;
}
else if(piece1.charAt(2)==piece2.charAt(2)) {
int row = (int)(piece1.charAt(2))-48;
int cLow = Math.min((int)(piece1.charAt(3))-48,
(int)(piece2.charAt(3))-48);
int cHigh = Math.max((int)(piece1.charAt(3))-48,
(int)(piece2.charAt(3))-48);
for(int i=cLow;i<=cHigh;i++)
if(board[row][i].charAt(0)==color &&
!board[row][i].equals
(piece1.substring(0,2)))
return false;
}
//diagonal check
else {
int r1 = piece1.charAt(2)-48;
int c1 = piece1.charAt(3)-48;
int r2 = piece1.charAt(2)-48;
int c2 = piece2.charAt(2)-48;
if(piece1.charAt(2)>piece2.charAt(2) &&
piece1.charAt(3)>piece2.charAt(3)) {
while(r1>=r2 && c1>=c2) {
if(board[r1][c1].charAt(0)==color &&
!board[r1][c1].equals
(piece1.substring(0,2)))
return false;
r1--;
c1--;
}
}
if(piece1.charAt(2)>piece2.charAt(2) &&
piece1.charAt(3)<piece2.charAt(3)) {
while(r1>=r2 && c1<=c2) {
if(board[r1][c1].charAt(0)==color &&
!board[r1][c1].equals
(piece1.substring(0,2)))
return false;
r1--;
c1++;
}
}
if(piece1.charAt(2)<piece2.charAt(2) &&
piece1.charAt(3)<piece2.charAt(3)) {
while(r1<=r2 && c1<=c2) {
if(board[r1][c1].charAt(0)==color &&
!board[r1][c1].equals
(piece1.substring(0,2)))
return false;
r1++;
c1++;
}
}
if(piece1.charAt(2)<piece2.charAt(2) &&
piece1.charAt(3)>piece2.charAt(3)) {
while(r1<=r2 && c1>=c2) {
if(board[r1][c1].charAt(0)==color &&
!board[r1][c1].equals
(piece1.substring(0,2)))
return false;
r1++;
c1--;
}
}
}
return true;
}
public boolean castle() {
String kingPiece = "";
String rookPiece = "";
if(piece1.charAt(1)=='K') kingPiece = piece1;
if(piece2.charAt(1)=='K') kingPiece = piece2;
if(piece1.charAt(1)=='R') rookPiece = piece1;
if(piece2.charAt(1)=='R') rookPiece = piece2;
if(kingPiece.isEmpty() || rookPiece.isEmpty()) return false;
//white side
if(kingPiece.charAt(0)=='W' && rookPiece.charAt(0)=='W')
if(kingPiece.equals("WK74")){
if(rookPiece.equals("WR77"))
if(board[7][5].equals(" ") &&
board[7][6].equals(" ")){
board[7][5]="WR";
board[7][6]="WK";
board[7][7]=" ";
board[7][4]=" ";
return true;
}
if(rookPiece.equals("WR70"))
if(board[7][1].equals(" ")
&& board[7][2].equals(" ")
&& board[7][3].equals(" ")){
board[7][3]="WR";
board[7][2]="WK";
board[7][4]=" ";
board[7][0]=" ";
return true;
}
}
//black side
if(kingPiece.charAt(0)=='B' && rookPiece.charAt(0)=='B')
if(kingPiece.equals("BK04")){
if(rookPiece.equals("BR07"))
if(board[0][5].equals(" ") &&
board[0][6].equals(" ")){
board[0][5]="BR";
board[0][6]="BK";
board[0][7]=" ";
board[0][4]=" ";
return true;
}
if(rookPiece.equals("BR00"))
if(board[0][1].equals(" ")
&& board[0][2].equals(" ")
&& board[0][3].equals(" ")){
board[0][3]="BR";
board[0][2]="BK";
board[0][4]=" ";
board[0][0]=" ";
return true;
}
}
makeChanges();
return false;
}
public static void verify() {
int c1 = (int)(piece1.charAt(2))-48;
int r1 = (int)(piece1.charAt(3))-48;
int c2 = (int)(piece2.charAt(2))-48;
int r2 = (int)(piece2.charAt(3))-48;
board[c2][r2]=board[c1][r1];
board[c1][r1]=" ";
curLoc++;
storedLoc++;
if(curLoc>1000) {
overFlow = true;
curLoc=0;
}
for(int r=0;r<8;r++)
for(int c=0;c<8;c++)
storeBoard[r][c][curLoc]=board[r][c];
}
public void makeChanges() {
contentPane.remove(boardPanel);
contentPane.remove(instructionPanel);
createBoardPanel();
createInstructionPanel();
contentPane.add(boardPanel, BorderLayout.CENTER);
contentPane.add(instructionPanel, BorderLayout.SOUTH);
contentPane.validate();
}
public static String checkWon() {
int wKing = 0;
int bKing = 0;
for(int r=0;r<board.length;r++)
for(int c=0;c<board.length;c++)
if(board[r][c].charAt(1)=='K') {
if(board[r][c].charAt(0)=='B') bKing++;
else wKing++;
}
if(wKing==0) return "black";
else if(bKing==0) return "white";
else return "nope";
}
public void checkPromo() {
for(int c=0;c<8;c++) {
if(board[0][c].equals("WP"))
promo(0,c);
if(board[7][c].equals("BP"))
promo(7,c);
}
}
public void promo(int r, int c) {
System.out.println("Promotion time");
String[] choices = {"Queen","Knight","Rook","Bishop","Pawn"};
int choice = JOptionPane.showOptionDialog(null,
"What piece would you like to promote into?",
"Chess", 0, 3, null, choices, null);
char pCol = board[r][c].charAt(0);
switch(choice)
{
case 0:board[r][c]=String.valueOf(pCol)+"Q";break;
case 1:board[r][c]=String.valueOf(pCol)+"H";break;
case 2:board[r][c]=String.valueOf(pCol)+"R";break;
case 3:board[r][c]=String.valueOf(pCol)+"B";break;
case 4:JOptionPane.showMessageDialog
(null,"Why would you do that?");
break;
}
}
public static void winMessage(String won) {
JOptionPane.showMessageDialog
(null,"Congratulations "+won+", you win!");
}
public static void initialFill(){
for(int c=0;c<8;c++){
board[1][c]="BP";
board[2][c]=" ";
board[3][c]=" ";
board[4][c]=" ";
board[5][c]=" ";
board[6][c]="WP";
}
for(int c=0;c<8;c++){
if(c==0 || c==7){
board[0][c]="BR";
board[7][c]="WR";
}
if(c==1 || c==6){
board[0][c]="BH";
board[7][c]="WH";
}
if(c==2 || c==5){
board[0][c]="BB";
board[7][c]="WB";
}
if(c==3){
board[0][c]="BQ";
board[7][c]="WQ";
}
if(c==4){
board[0][c]="BK";
board[7][c]="WK";
}
}
for(int r=0;r<8;r++)
for(int c=0;c<8;c++)
storeBoard[r][c][curLoc]=board[r][c];
}
public static void main(String[] args) {
color = 'W';
initialFill();
Chess chess = new Chess();
chess.setVisible(true);
}
}