import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Checkers extends JApplet { private char[][] board = new char[8][8]; private char turn; private JButton[] boardButtons; private int numPlayers; private char human; private int startRow; private int startCol; private boolean startDone; private int toRow; private int toCol; private boolean hasAnotherJump; public void init() { Container container = getContentPane(); container.setLayout( new GridLayout( 8, 8 ) ); boardButtons = new JButton[64]; for (int i=0; i<8; i++) for (int j=0; j<8; j++) { boardButtons[i*8+j] = new JButton( "" ); boardButtons[i*8+j].setFont( new Font( "Courier", Font.BOLD, 20 ) ); ButtonHandler myButtonHandler = new ButtonHandler(); boardButtons[i*8+j].addActionListener( myButtonHandler ) ; container.add( boardButtons[i*8+j] ); } } private class ButtonHandler implements ActionListener { public void actionPerformed( ActionEvent event ) { int i=0; while ( event.getSource() != boardButtons[i] ) i++; int row, col; row = i / 8; col = i % 8; if ( numPlayers==1 && human=='r') { //flipped board row = 7 - row; col = 7 - col; } if ( ! startDone ) { if ( checkStartMove( row, col ) ) { startRow = row; startCol = col; startDone = true; } } else if ( checkToMove( row, col ) ) { toRow = row; toCol = col; make_move(); if ( ! hasAnotherJump ) { startDone = false; if (turn == 'r') { turn = 'b'; showStatus( "Black to play" ); } else { turn = 'r'; showStatus( "Red to play" ); } } } } } public void start() { String s = JOptionPane.showInputDialog( "2 people or 1? 2 or [1])" ); if ( s.equals( "2" ) ) numPlayers = 2; else { numPlayers = 1; String first = JOptionPane.showInputDialog( "You red or black? ([r] or b)" ); if ( first.equals("") || first.charAt(0)=='r' ) human = 'r'; else human = 'b'; } initializeBoard(); display(); turn = 'r'; //red always plays first showStatus( "Red plays first" ); } public void paint( Graphics g ) { super.paint( g ); } public void display() { if ( numPlayers==1 && human=='r' ) //flip so red is at bottom for (int i=0; i<8; i++) for (int j=0; j<8; j++) if ( board[i][j] == 'r' ) boardButtons[(7-i)*8+(7-j)].setBackground( Color.RED ); else if ( board[i][j] == 'b' ) boardButtons[(7-i)*8+(7-j)].setBackground( Color.BLACK ); else boardButtons[(7-i)*8+(7-j)].setBackground( Color.GRAY ); else for (int i=0; i<8; i++) for (int j=0; j<8; j++) if ( board[i][j] == 'r' ) boardButtons[i*8+j].setBackground( Color.RED ); else if ( board[i][j] == 'b' ) boardButtons[i*8+j].setBackground( Color.BLACK ); else boardButtons[i*8+j].setBackground( Color.GRAY ); repaint(); } private boolean checkStartMove( int frow, int fcol ) { boolean bad_coords; String coord_error=""; Set jumps = new HashSet(); find_jumps(jumps); //debug: //System.out.println("Jumps:"); //for (Iterator i=jumps.iterator(); i.hasNext(); ) // System.out.println(i.next()); bad_coords = false; if (Character.toUpperCase(board[frow][fcol]) != Character.toUpperCase(turn)) { bad_coords = true; coord_error = "not yours"; } else if ((frow==0 || fcol==7 || Character.toUpperCase(board[frow-1][fcol+1])== Character.toUpperCase(turn)) && (frow==0 || fcol==0 || Character.toUpperCase(board[frow-1][fcol-1])== Character.toUpperCase(turn)) && (frow==7 || fcol==7 || Character.toUpperCase(board[frow+1][fcol+1])== Character.toUpperCase(turn)) && (frow==7 || fcol==0 || Character.toUpperCase(board[frow+1][fcol-1])== Character.toUpperCase(turn))) { bad_coords = true; coord_error = "surrounded"; } else if ((turn=='r' && board[frow][fcol]!='R' && ((frow==7 || fcol==7 || Character.toUpperCase(board[frow+1][fcol+1])=='R') || (Character.toUpperCase(board[frow+1][fcol+1])=='B' && (frow==6 || fcol==6 || board[frow+2][fcol+2]!=' '))) && ((frow==7 || fcol==0 || Character.toUpperCase(board[frow+1][fcol-1])=='R') || (Character.toUpperCase(board[frow+1][fcol-1])=='B' && (frow==6 || fcol==1 || board[frow+2][fcol-2]!=' ')))) || (turn=='b' && board[frow][fcol]!='B' && ((frow==0 || fcol==7 || Character.toUpperCase(board[frow-1][fcol+1])=='B') || (Character.toUpperCase(board[frow-1][fcol+1])=='R' && (frow==1 || fcol==6 || board[frow-2][fcol+2]!=' '))) && ((frow==0 || fcol==0 || Character.toUpperCase(board[frow-1][fcol-1])=='B') || (Character.toUpperCase(board[frow-1][fcol-1])=='R' && (frow==1 || fcol==1 || board[frow-2][fcol-2]!=' '))))){ bad_coords = true; coord_error = "no move forward"; } else if (!jumps.isEmpty()) { if (!jumps.contains(Integer.toString(frow)+" "+Integer.toString(fcol))) { bad_coords = true; coord_error = "must do available jump"; } } if ( bad_coords ) { JOptionPane.showMessageDialog( null, coord_error ); return false; } else return true; } private boolean checkToMove( int trow, int tcol ) { boolean bad_coords; String coord_error=""; Set jumps = new HashSet(); int frow = startRow; //easy to modify from original code... int fcol = startCol; find_jumps(jumps); bad_coords = false; if ((turn=='r' && board[frow][fcol]!='R' && trow<=frow) || (turn=='b' && board[frow][fcol]!='B' && trow>=frow)) { bad_coords = true; coord_error = "not move forward"; } else if (board[trow][tcol] != ' ') { bad_coords = true; coord_error = "not empty"; } //jump attempt but not over other player else if (Math.abs(trow-frow)==2 && ((turn=='b' && Character.toUpperCase(board[(trow+frow)/2][(tcol+fcol)/2]) !='R') || (turn=='r' && Character.toUpperCase(board[(trow+frow)/2][(tcol+fcol)/2]) !='B'))) { bad_coords = true; coord_error = "bad jump"; } //not a jump and move is not +-1 row and col from frow and fcol else if (Math.abs(trow-frow)!=2 && (Math.abs(trow-frow)!=1 || Math.abs(tcol-fcol)!=1)) { bad_coords = true; coord_error = "bad move"; } else if (!jumps.isEmpty()) { //a jump From was selected if (Math.abs(trow-frow) != 2) { //but not taken bad_coords = true; coord_error = "jump must be taken"; } } if ( bad_coords ) { JOptionPane.showMessageDialog( null, coord_error ); return false; } else return true; } private void make_move() { int frow=startRow, fcol=startCol, trow=toRow, tcol=toCol; Set jumps = new HashSet(); find_jumps(jumps); hasAnotherJump = false; //the offcial positions int from_cell = frow*4 + (int)Math.ceil((fcol+1)/2.0); int to_cell = trow*4 + (int)Math.ceil((tcol+1)/2.0); //System.out.println(from_cell+"-"+to_cell); boolean kinged_this_play = false; if (trow==7 && board[frow][fcol]=='r') { //becomes king board[trow][tcol] = 'R'; kinged_this_play = true; //so if jumped here, must stop even if jump available } else if (trow==0 && board[frow][fcol]=='b') { //becomes king board[trow][tcol] = 'B'; kinged_this_play = true; } else board[trow][tcol] = board[frow][fcol]; board[frow][fcol] = ' '; if (Math.abs(trow-frow) == 2) { //jumped board[(trow+frow)/2][(tcol+fcol)/2] = ' '; if (has_jump(trow,tcol) && !kinged_this_play) { hasAnotherJump = true; JOptionPane.showMessageDialog( null, "You have another jump" ); frow = trow; //from here fcol = tcol; startRow = trow; //from here startCol = tcol; //so this jump is in set: jumps.add(Integer.toString(frow)+" "+Integer.toString(fcol)); } else hasAnotherJump = false; } display(); } private boolean has_jump(int frow, int fcol) { if (((turn=='r' && Character.toUpperCase(board[frow][fcol])=='R' && ((frow<6 && fcol<6 && Character.toUpperCase(board[frow+1][fcol+1])=='B' && board[frow+2][fcol+2]==' ') || (frow<6 && fcol>1 && Character.toUpperCase(board[frow+1][fcol-1])=='B' && board[frow+2][fcol-2]==' '))) || (turn=='r' && board[frow][fcol]=='R' //backwards && ((frow>1 && fcol<6 && Character.toUpperCase(board[frow-1][fcol+1])=='B' && board[frow-2][fcol+2]==' ') || (frow>1 && fcol>1 && Character.toUpperCase(board[frow-1][fcol-1])=='B' && board[frow-2][fcol-2]==' ')))) || ((turn=='b' && Character.toUpperCase(board[frow][fcol])=='B' && ((frow>1 && fcol>1 && Character.toUpperCase(board[frow-1][fcol-1])=='R' && board[frow-2][fcol-2]==' ') || (frow>1 && fcol<6 && Character.toUpperCase(board[frow-1][fcol+1])=='R' && board[frow-2][fcol+2]==' '))) || (turn=='b' && board[frow][fcol]=='B' //backwards && ((frow<6 && fcol<6 && Character.toUpperCase(board[frow+1][fcol+1])=='R' && board[frow+2][fcol+2]==' ') || (frow<6 && fcol>1 && Character.toUpperCase(board[frow+1][fcol-1])=='R' && board[frow+2][fcol-2]==' '))))) return true; else return false; } private void find_jumps(Set s) { for (int i=0; i<8; i++) for (int j=0; j<8; j++) if (has_jump(i,j)){ s.add(Integer.toString(i)+" "+Integer.toString(j)); //debug: //System.out.println(Integer.toString(i)+" "+Integer.toString(j)); } } private void initializeBoard() { for (int i=0; i<8; i++) for (int j=0; j<8; j++) if (((i==0 || i==2) && j%2==1) || (i==1 && j%2==0)) board[i][j] = 'r'; else if (((i==5 || i==7) && j%2==0) || (i==6 && j%2==1)) board[i][j] = 'b'; else board[i][j] = ' '; } public String toString() { StringBuffer B = new StringBuffer(); for (int i=0; i<8; i++) { for (int j=0; j<8; j++) B.append(board[i][j]); B.append('\n'); } B.append(turn); B.append('\n'); return B.toString(); } //nested test class /* public static class Play { public static void main(String[] args) { if (args.length==0 || (args.length==1 && !args[0].equals("2")) || (args.length==2 && (!args[1].equals("r") && !args[1].equals("b")))) { System.out.println("Usage: Play {1 r|b}|2"); System.exit(1); } Checkers game = new Checkers(); if (args.length == 1) game.play(2); else game.play(1,args[1].charAt(0)); } } */ } /* //all input here. a row, col private boolean get_coords(String from_or_to, int[] coords, String coord_error) { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String line; System.out.println(coord_error); System.out.println(turn+" turn to play"); System.out.print(from_or_to+"Row (1-8): "); try { line = in.readLine(); coords[0] = Integer.parseInt(line); } catch (NumberFormatException e) { System.out.println("Invalid input, not a number"); return false; } //so don't need throws IOException (from readLine) for method catch (IOException e) { System.out.println("catch Exception"); return false; } System.out.print(from_or_to+"Col (1-8): "); try { line = in.readLine(); coords[1] = Integer.parseInt(line); } catch (NumberFormatException e) { System.out.println("Invalid input, not a number"); return false; } catch (IOException e) { System.out.println("catch Exception"); return false; } return true; } */ /* private void file_dump() { String fname = "saveboard"; try { PrintWriter outf = new PrintWriter(new FileWriter(fname)); String line; for (int i=0; i<8; i++) { for (int j=0; j<8; j++) outf.print(board[i][j]); outf.println(); } outf.println(turn); outf.close(); } catch (IOException e) { //so method doesn't need to throw IOException of readLine } } */ /* private void file_initialize() { String fname = "initboard"; try { BufferedReader inf = new BufferedReader(new FileReader(fname)); String line; for (int i=0; i<8; i++) { line = inf.readLine(); //debug: file must be 8x8 chars //System.out.println("line length="+line.length()); for (int j=0; j<8; j++) board[i][j] = line.charAt(j); } inf.close(); } catch (IOException e) { //so method doesn't need to throw IOException of readLine } } */ /* //all output here. change to awt later... private void display() { System.out.println(" 1 2 3 4 5 6 7 8"); System.out.println(" -----------------"); for (int i=0; i<8; i++) { System.out.print(i+1+"|"); for (int j=0; j<8; j++) System.out.print(board[i][j]+"|"); System.out.println(); System.out.println(" -----------------"); } } */