JAVA期末大作业 中国跳棋
PS:这学期期末成绩差不多出完了,接下来会陆续把这学期课程中的代码陆续扔到这里来以便后人****,同时自己也留个纪念。
本学期选了java选修,期末大作业面向GitHub编程写了个中国跳棋。代码中还有写小bug,不过懒得调了...
update:github
1.游戏介绍
中国跳棋,简称跳棋,是一种可以让二至六人一起玩的棋,棋盘为六角星形状,棋子一般分为六种颜色,每种颜色有10或15枚棋子(或弹珠),每一位玩家占一个角,执一种颜色的棋子,如果玩的人数较,也能每人执两种颜色的棋子玩。
游戏规则如下:
先将一种颜色的棋子按规则全部放在一个角上,各人循顺时针或逆时针方向轮流走子,每次只能动一枚棋子,全部棋子先到达对角那一边的为赢家。棋子有两种走法:
1)一枚棋子移动到相邻六格其中一格。
2)“搭桥”:自己的棋子(A)同一条直线上还有一枚棋子(B),不限属于哪一方,大家之间没有任何棋子阻隔。如果B的另一方也没有棋子阻隔,A就可以跳到B的相反方向,而且和两枚棋子原来的距离一样。跳跃可以一直进行下去,直到没有前进的路径为止。如果有循环情况,可在任意一处停下。
2.项目介绍
1)本跳棋project支持两人、四人、六人跳棋对战
2)具有计时功能,可显示当前时间,同时也可判断当前玩家是否超时
3)游戏可暂停
4)可保存当前局面,从本地打开已有文件(文件I/O)
3.游戏界面
4.工程布局(太懒了直接把所有class写在了一个文件里)
5.代码
1 import java.awt.Color; 2 import java.awt.Font; 3 import java.awt.Image; 4 import java.awt.event.ActionEvent; 5 import java.awt.event.ActionListener; 6 import java.awt.event.KeyEvent; 7 import java.awt.event.MouseAdapter; 8 import java.awt.event.MouseEvent; 9 import java.io.File; 10 import java.io.FileNotFoundException; 11 import java.io.IOException; 12 import java.io.PrintWriter; 13 import java.text.SimpleDateFormat; 14 import java.util.Date; 15 import java.util.Scanner; 16 17 import javax.imageio.ImageIO; 18 import javax.management.MBeanOperationInfo; 19 import javax.swing.ImageIcon; 20 import javax.swing.JFileChooser; 21 import javax.swing.JFrame; 22 import javax.swing.JLabel; 23 import javax.swing.JLayeredPane; 24 import javax.swing.JMenu; 25 import javax.swing.JMenuBar; 26 import javax.swing.JMenuItem; 27 import javax.swing.JOptionPane; 28 29 30 31 public class ChineseChecker { 32 33 public static MyFrame myFrame; 34 public static int numberOfPlayers; //游戏玩家的数量 35 public static boolean numbersDone = false;//游戏玩家数量是否设定完毕 36 public static boolean gameStatus = false;//游戏状态(是否暂停) 37 public static char[] series = new char[6];//六种棋子 38 public static int currentIndex = 0;//当前下标 39 public static String pieceToMove;//将要移动的棋子 40 public static int []piecePos;//记录棋子位置 41 public static boolean isPieceToMoveAcquired = false;//是否已经选中将要移动的棋子 42 public static boolean isTheStartingOfTheGame = false;//游戏是否开始 43 public static boolean isPositionToGoToAcquired = false;//将要去的位置是否设定完毕 44 public static int[] posToGoTo; 45 public static boolean isANewGame = false; 46 47 public static void main(String[] args) { 48 // TODO Auto-generated method stub 49 myFrame = new MyFrame();//实例化窗口 50 myFrame.setSize(710, 870);//设置窗口大小 51 myFrame.setVisible(true);//窗口可见 52 Pieces pieces = new Pieces();//实例化棋子类 53 54 /**等待设定游戏玩家数量**/ 55 while(!numbersDone){ 56 try { 57 Thread.sleep(500); 58 } catch (InterruptedException e) { 59 // TODO Auto-generated catch block 60 e.printStackTrace(); 61 } 62 } 63 numbersDone = false; 64 65 /* 66 * 游戏分为双人对战,四人对战和六人对战 67 */ 68 switch (numberOfPlayers) { 69 case 2: 70 series[0] = 'D';series[1] = 'A'; 71 break; 72 case 4: 73 series[0] = 'F';series[1] = 'B';series[2] = 'C';series[3] = 'E'; 74 break; 75 case 6: 76 series[0] = 'F';series[1] = 'A';series[2] = 'B';series[3] = 'C';series[4] = 'D';series[5] = 'E'; 77 break; 78 default: 79 break; 80 } 81 //pieces.init(); 82 myFrame.init(series); 83 initPlayers(series); 84 85 pieces.init(); 86 87 /**一旦玩家数量设定完成,游戏开始**/ 88 isTheStartingOfTheGame = true; 89 90 while (true) { 91 Trace.isSkipped = false; 92 93 Trace.nextStep(); 94 95 //展示当前玩家 96 myFrame.showCurrent(); 97 myFrame.showCurrentPlayer(); 98 MyFrame.timer = new Timer(); 99 100 101 while (!isPositionToGoToAcquired) { 102 103 if (MyFrame.timer.listen() <= 0) {//如果玩家超时 104 if (isPieceToMoveAcquired) //如果将要移动的的棋子设定过 105 PieceActionListener.clearPossiblePos();//清除之前的可能移动到的合法位置标记 106 pieceToMove = series[currentIndex] + "0"; 107 piecePos = Pieces.getPiecePos("A0 "); 108 posToGoTo = piecePos ; 109 Services.msg("Player " + series[currentIndex] + " time exceeded!");//提示玩家超时 110 break; 111 } 112 if (Trace.isSkipped)//如果已经跳过了,就退出 113 break; 114 try { 115 Thread.sleep(0500); 116 } catch (InterruptedException e) { 117 // TODO Auto-generated catch block 118 e.printStackTrace(); 119 } 120 } 121 if (Trace.isSkipped) continue;//如果已经跳过了,就到下一次循环 122 isPositionToGoToAcquired = false; 123 if (isANewGame) { 124 isANewGame = false; 125 continue; 126 } 127 /*记录轨迹 */ 128 Pieces.moveAward(pieceToMove, piecePos, posToGoTo); 129 Trace.recordStep(pieceToMove, piecePos, posToGoTo); 130 131 /*判断是否出现胜利者*/ 132 for (int order = 0; order < numberOfPlayers; order++) { 133 if (isWinner(series[order])) { 134 Services.msg("Player " + series[order] + " wins!"); 135 System.exit(0); 136 } 137 } 138 Trace.step = Trace.step + 1; 139 } 140 } 141 142 public static void setNumber(int number){//设定游戏玩家数量 143 ChineseChecker.numbersDone = true; 144 ChineseChecker.gameStatus = true; 145 ChineseChecker.numberOfPlayers = number; 146 ChineseChecker.myFrame.mNewGame.setEnabled(false); 147 } 148 149 public static void initPlayers(char[] players) {//初始化players 150 for (char player : players) { 151 if (player == 0) 152 return; 153 int[][] initPositions = myFrame.zoneOfPlayer[player - 'A']; 154 for (int index = 0; index < 10; index++) { 155 Pieces.cell[initPositions[index][0]][initPositions[index][1]] = "" + player + index + " "; 156 } 157 } 158 } 159 160 public static boolean isWinner(char player) {//判断player是否已经获胜 161 char opponentPlayer = player < 'D' ? (char) ((int) player + 3) : (char) ((int) player - 3); 162 163 int[][] positionsBelongedToThePlayer = MyFrame.zoneOfPlayer[opponentPlayer - 'A']; 164 165 for (int index = 0; index < 10; index++) { 166 int[] position = positionsBelongedToThePlayer[index]; 167 if (Pieces.cell[position[0]][position[1]].charAt(0) != player) 168 return false; 169 } 170 return true; 171 } 172 173 } 174 175 class MyFrame extends JFrame{ 176 177 public Image image; 178 179 public ImageIcon imgBoard; 180 public static JLayeredPane panel; 181 public static JLabel lblBoard,lblPlayer,lblTime,lblCurrent; 182 public JMenuBar menuBar; 183 public JMenu mControl = new JMenu("control"), 184 mNewGame = new JMenu("New Game"); 185 public JMenuItem mTwoPlayers = new JMenuItem("Two players"), 186 mFourPlayers = new JMenuItem("Four players"), 187 mSixPlayers = new JMenuItem("Six players"), 188 mExit = new JMenuItem("Exit", KeyEvent.VK_X), 189 mPauseGame = new JMenuItem("Pause Game", KeyEvent.VK_P), 190 mOpen = new JMenuItem("Open",KeyEvent.VK_O), 191 mSave = new JMenuItem("Save",KeyEvent.VK_S); 192 public JLabel[][] pieces = new JLabel[6][10]; 193 public static final int[][][] zoneOfPlayer = { 194 {{5, 1}, {5, 2}, {6, 2}, {5, 3}, {6, 3}, {7, 3}, {5, 4}, {6, 4}, {7, 4}, {8, 4}}, 195 {{1, 5}, {2, 6}, {2, 5}, {3, 7}, {3, 6}, {3, 5}, {4, 8}, {4, 7}, {4, 6}, {4, 5}}, 196 {{5, 13}, {6, 13}, {5, 12}, {7, 13}, {6, 12}, {5, 11}, {8, 13}, {7, 12}, {6, 11}, {5, 10}}, 197 {{13, 17}, {13, 16}, {12, 16}, {13, 15}, {12, 15}, {11, 15}, {13, 14}, {12, 14}, {11, 14}, {10, 14}}, 198 {{17, 13}, {16, 12}, {16, 13}, {15, 11}, {15, 12}, {15, 13}, {14, 10}, {14, 11}, {14, 12}, {14, 13}}, 199 {{13, 5}, {12, 5}, {13, 6}, {11, 5}, {12, 6}, {13, 7}, {10, 5}, {11, 6}, {12, 7}, {13, 8}}}; 200 public static Timer timer; 201 public MyFrame(){ 202 203 imgBoard = new ImageIcon("Board.jpg"); 204 lblTime = new JLabel(); 205 lblTime.setForeground(Color.BLUE); 206 lblTime.setFont(new Font("黑体", Font.BOLD, 20)); 207 lblTime.setBounds(50, 50, 280, 30); 208 209 lblCurrent = new JLabel("当前玩家"); 210 lblCurrent.setFont(new Font("当前玩家", 20, 20)); 211 lblCurrent.setBounds(40, 80, 200, 30); 212 213 lblBoard = new JLabel(imgBoard); 214 lblBoard.setBounds(0, 20, 685, 800); 215 216 lblPlayer = new JLabel(new ImageIcon()); 217 lblPlayer.setBounds(50, 100, 50, 50); 218 219 panel = new JLayeredPane(); 220 panel.add(lblBoard,JLayeredPane.DEFAULT_LAYER); 221 panel.add(lblPlayer, JLayeredPane.MODAL_LAYER); 222 panel.add(lblTime, JLayeredPane.MODAL_LAYER); 223 224 225 setLayeredPane(panel); 226 227 mControl.setMnemonic(KeyEvent.VK_C); 228 mControl.add(mOpen); 229 mControl.add(mSave); 230 mControl.add(mNewGame); 231 mControl.add(mPauseGame); 232 233 mNewGame.add(mTwoPlayers); 234 mNewGame.add(mFourPlayers); 235 mNewGame.add(mSixPlayers); 236 237 menuBar = new JMenuBar(); 238 menuBar.add(mControl); 239 setJMenuBar(menuBar); 240 241 /**设置两个玩家、四个玩家或六个玩家**/ 242 mTwoPlayers.addActionListener(new ActionListener() { 243 @Override 244 public void actionPerformed(ActionEvent e) { 245 // TODO Auto-generated method stub 246 ChineseChecker.setNumber(2); 247 } 248 }); 249 mFourPlayers.addActionListener(new ActionListener() { 250 @Override 251 public void actionPerformed(ActionEvent e) { 252 // TODO Auto-generated method stub 253 ChineseChecker.setNumber(4); 254 } 255 }); 256 mSixPlayers.addActionListener(new ActionListener() { 257 @Override 258 public void actionPerformed(ActionEvent e) { 259 // TODO Auto-generated method stub 260 ChineseChecker.setNumber(6); 261 } 262 }); 263 /**暂停游戏**/ 264 mPauseGame.addActionListener(new ActionListener() { 265 @Override 266 public void actionPerformed(ActionEvent e) { 267 // TODO Auto-generated method stub 268 ChineseChecker.gameStatus = false; 269 } 270 }); 271 272 mOpen.addActionListener(new ActionListener() {//打开已保存过的游戏 273 @Override 274 public void actionPerformed(ActionEvent arg0) { 275 JFileChooser chooser = new JFileChooser(); 276 chooser.showOpenDialog(null); 277 278 try { 279 File file = chooser.getSelectedFile(); 280 if (file == null) { 281 throw new Exception("FileNotExisted"); 282 } 283 Scanner scanner = new Scanner(file); 284 String[] temp = scanner.nextLine().split(","); 285 int num = Integer.parseInt(temp[0]); 286 char cur = temp[1].charAt(0); 287 int curIndex = Integer.parseInt(temp[2]); 288 int step = Integer.parseInt(temp[3]); 289 290 ChineseChecker.numbersDone = true; 291 if (!(ChineseChecker.numberOfPlayers == num) && !ChineseChecker.isTheStartingOfTheGame) 292 throw new Exception("PlayersNumberUnmatched"); 293 ChineseChecker.numberOfPlayers = num; 294 System.out.println(num); 295 ChineseChecker.currentIndex = curIndex; 296 ChineseChecker.series[curIndex] = cur; 297 Trace.step = step; 298 //Diagram.getDiagram().init(); 299 300 while (!ChineseChecker.isTheStartingOfTheGame) { 301 } 302 while (scanner.hasNext()) { 303 in(scanner.nextLine()); 304 } 305 ChineseChecker.myFrame.mNewGame.setEnabled(false); 306 ChineseChecker.isANewGame = true; 307 ChineseChecker.isPositionToGoToAcquired = true; 308 } catch (FileNotFoundException e) { 309 // e.printStackTrace(); 310 } catch (Exception e) { 311 Services.msg("Import failed: " + e.getMessage()); 312 } 313 } 314 315 public void in(String line) { 316 String[] temp = line.split(","); 317 String piece = temp[0] + " "; 318 int i = Integer.parseInt(temp[1]), j = Integer.parseInt(temp[2]); 319 int player = piece.charAt(0) - 65; 320 int index = piece.charAt(1) - 48; 321 Pieces.pieces[player][index][0] = i; 322 Pieces.pieces[player][index][1] = j; 323 Pieces.cell[i][j] = piece; 324 int[] pos = {i, j}; 325 ChineseChecker.myFrame.move(piece,pos); 326 } 327 }); 328 329 mSave.addActionListener(new ActionListener() {//保存当前游戏 330 331 @Override 332 public void actionPerformed(ActionEvent arg0) { 333 JFileChooser chooser = new JFileChooser(); 334 chooser.showOpenDialog(null); 335 File file = chooser.getSelectedFile(); 336 337 PrintWriter writer; 338 try { 339 writer = new PrintWriter(file); 340 writer.write(new Output().s); 341 writer.close(); 342 } catch (FileNotFoundException e) { 343 // e.printStackTrace(); 344 } catch (Exception e) { 345 Services.msg("Export failed!"); 346 } 347 } 348 349 class Output { 350 String s = ""; 351 352 Output() { 353 out(); 354 } 355 356 void out() { 357 int num = ChineseChecker.numberOfPlayers; 358 System.out.println(num); 359 int[] position; 360 s += num; 361 char cur = ChineseChecker.series[ChineseChecker.currentIndex]; 362 s += "," + cur; 363 int curIndex = ChineseChecker.currentIndex; 364 s += "," + curIndex; 365 int step = Trace.step; 366 s += "," + step; 367 char[][] player = {null, null, {'A', 'D'}, {'A', 'C', 'E'}, 368 {'B', 'C', 'E', 'F'}, null, 369 {'A', 'B', 'C', 'D', 'E', 'F'}}; 370 for (int i = 0; i < 10; i++) { 371 for (char j : player[num]) { 372 position = Pieces.getPiecePos(j - 65, i); 373 s += "\n" + j + i + "," + position[0] + "," + position[1]; 374 } 375 } 376 } 377 } 378 }); 379 380 TimerThread timerThread = new TimerThread("Timer"); 381 timerThread.start(); 382 383 } 384 385 public void showCurrent() { 386 panel.add(lblCurrent, JLayeredPane.MODAL_LAYER); 387 } 388 389 public void move(String pieceToMove, int[] targetPosition) { 390 char playerOnTheMove = pieceToMove.charAt(0); 391 int index = pieceToMove.charAt(1) - '0'; 392 int x = Map.map[targetPosition[0]][targetPosition[1]][0]; 393 int y = Map.map[targetPosition[0]][targetPosition[1]][1]; 394 395 pieces[playerOnTheMove - 'A'][index].setBounds(x, y, 39, 39); 396 } 397 398 public void init(char[] playerSeries) { 399 for (char player : playerSeries) { 400 if (player == 0) 401 return; 402 initPlayer(player); 403 } 404 } 405 406 private void initPlayer(char player) { 407 for (int pieceIndex = 0; pieceIndex < 10; pieceIndex++) { 408 initPiece(player, pieceIndex); 409 } 410 } 411 412 private void initPiece(char player, int pieceIndex) { 413 //Image image = 414 Map myMap = new Map(); 415 int playerIndex = player - 'A'; 416 int[] pieceSeries = zoneOfPlayer[player - 'A'][pieceIndex]; 417 int x = myMap.map[pieceSeries[0]][pieceSeries[1]][0]; 418 int y = myMap.map[pieceSeries[0]][pieceSeries[1]][1]; 419 420 pieces[playerIndex][pieceIndex] = new JLabel(new ImageIcon("Piece_" + player + ".PNG")); 421 pieces[playerIndex][pieceIndex] 422 .addMouseListener(new PieceActionListener("" + player + pieceIndex)); 423 424 pieces[playerIndex][pieceIndex].setBounds(x, y, 39, 39); 425 panel.add(pieces[playerIndex][pieceIndex], JLayeredPane.MODAL_LAYER); 426 } 427 428 public static void showCurrentPlayer() { 429 430 lblPlayer.setIcon(new ImageIcon("Piece_" + ChineseChecker.series[ChineseChecker.currentIndex] + ".PNG")); 431 panel.repaint(); 432 } 433 434 435 class TimerThread extends Thread { 436 TimerThread(String name) { 437 super(name); 438 } 439 440 @Override 441 public void run() { 442 while (true) { 443 lblTime.setText(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date())); 444 panel.repaint(); 445 try { 446 Thread.sleep(0500); 447 } catch (InterruptedException e) { 448 e.printStackTrace(); 449 } 450 } 451 } 452 } 453 454 } 455 456 class Map {//map记录棋盘上每个点在myFrame中的坐标 457 //map[i][j][0]表示点(i,j)在棋盘中的横坐标,map[i][j][1]表示点(i,j)在棋盘中的纵坐标 458 public static int [][][] map = new int[18][18][2]; 459 public Map(){//计算各点坐标,并将其存入map中 460 for (int i = 5; i <= 5; i++) 461 setSinglePosition(i, 1, 325 + 51 * (i - 5), 780 + 0 * (i - 5)); 462 for (int i = 5; i <= 6; i++) 463 setSinglePosition(i, 2, 325 - 28 + 54 * (i - 5), 780 - 47); 464 for (int i = 5; i <= 7; i++) 465 setSinglePosition(i, 3, 325 - 28 * 2 + 54 * (i - 5), 780 - 47*2); 466 for (int i = 5; i <= 8; i++) 467 setSinglePosition(i, 4, 325 - 28 * 3 + 54 * (i - 5), 780 - 47*3); 468 for (int i = 1; i <= 13; i++) 469 setSinglePosition(i, 5, 0 + 28 * 0 + 54 * (i - 1), 780 - 47*4); 470 for (int i = 2; i <= 13; i++) 471 setSinglePosition(i, 6, 0 + 28 * 1 + 54 * (i - 2), 780 - 47*5); 472 for (int i = 3; i <= 13; i++) 473 setSinglePosition(i, 7, 0 + 28 * 2 + 54 * (i - 3), 780 - 47*6); 474 for (int i = 4; i <= 13; i++) 475 setSinglePosition(i, 8, 0 + 28 * 3 + 54 * (i - 4), 780 - 47*7); 476 for (int i = 5; i <= 13; i++) 477 setSinglePosition(i, 9, 0 + 28 * 4 + 54 * (i - 5), 780 - 47*8); 478 for (int i = 5; i <= 14; i++) 479 setSinglePosition(i, 10, 0 + 28 * 3 + 54 * (i - 5), 780 - 47*9); 480 for (int i = 5; i <= 15; i++) 481 setSinglePosition(i, 11, 0 + 28 * 2 + 54 * (i - 5), 780 - 47*10); 482 for (int i = 5; i <= 16; i++) 483 setSinglePosition(i, 12, 0 + 28 * 1 + 54 * (i - 5), 780 - 47*11); 484 for (int i = 5; i <= 17; i++) 485 setSinglePosition(i, 13, 0 + 28 * 0 + 54 * (i - 5), 780 - 47*12); 486 for (int i = 10; i <= 13; i++) 487 setSinglePosition(i, 14, 325 - 28 * 3 + 54 * (i - 10), 780 - 47*13); 488 for (int i = 11; i <= 13; i++) 489 setSinglePosition(i, 15, 325 - 28 * 2 + 54 * (i - 11),780 - 47*14); 490 for (int i = 12; i <= 13; i++) 491 setSinglePosition(i, 16, 325 - 28 * 1 + 54 * (i - 12), 780 - 47*15); 492 for (int i = 13; i <= 13; i++) 493 setSinglePosition(i, 17, 325 - 28 * 0 + 54 * (i - 13), 780 - 47*16); 494 } 495 public void setSinglePosition(int i,int j,double x,double y){ 496 map[i][j][0] = (int)x; 497 map[i][j][1] = (int)y; 498 } 499 } 500 501 class Pieces {//棋子类 502 public static int [][][] pieces = new int [6][10][2]; 503 public static String [][] cell = new String[20][20]; 504 public final static String EMPTY_MARK = "** "; 505 public final static String OUTSIDE_MARK = " "; 506 public final static String SPACE_MARK = " "; 507 508 public Pieces(){ 509 510 for (int i = 1; i <= 17; i++) 511 for (int j = 1; j <= 17; j++) 512 cell[i][j]= OUTSIDE_MARK;//初始化认为所有cell都在棋盘外 513 514 /**将所有在棋盘内的cell标记为EMPTY_MARK**/ 515 for (int j = 1; j <= 4; j++) 516 for (int i = 5; i <= j + 4; i++) 517 cell[i][j]= EMPTY_MARK; 518 for (int j = 5; j <= 8; j++) 519 for (int i = j - 4; i <= 13; i++) 520 cell[i][j]= EMPTY_MARK; 521 for (int j = 9; j <= 13; j++) 522 for (int i = 5; i <= j + 4; i++) 523 cell[i][j]= EMPTY_MARK; 524 for (int j = 14; j <= 17; j++) 525 for (int i = j - 4; i <= 13; i++) 526 cell[i][j]= EMPTY_MARK; 527 } 528 public void init(){//初始化 529 for (int i = 1;i <= 17;++i){ 530 for (int j = 1;j <= 17;++j){ 531 if (cell[i][j].charAt(0) >= 65 && cell[i][j].charAt(0) <= 70){ 532 setPosition(cell[i][j],i,j); 533 } 534 } 535 } 536 } 537 538 public void setPosition(String s,int x,int y){ 539 int player = s.charAt(0) - 65; 540 int index = s.charAt(1) -48; 541 pieces[player][index][0] = x; 542 pieces[player][index][1] = y; 543 } 544 545 public static void setPiecePos(String piece, int[] value) { 546 int player = piece.charAt(0) - 65; 547 int index = piece.charAt(1) - 48; 548 pieces[player][index] = value; 549 } 550 551 public static int[] getPiecePos(String piece) { 552 int player = piece.charAt(0) - 65; 553 int index = piece.charAt(1) - 48; 554 return new int[]{pieces[player][index][0], pieces[player][index][1]}; 555 } 556 557 public static int[] getPiecePos(int player, int index) { 558 return new int[]{pieces[player][index][0], pieces[player][index][1]}; 559 } 560 561 public static void moveAward(String piece, int[] prevPos, int[] postPos) {//前进 562 setPiecePos(piece, postPos); 563 cell[prevPos[0]][prevPos[1]] = EMPTY_MARK; 564 cell[postPos[0]][postPos[1]] = piece + SPACE_MARK; 565 } 566 567 public static class Next { 568 569 570 public static int[][] getPossiblePosition(String pieceToMove) { 571 /** 572 * get all possible positions via adjacent hop/distant/consecutive hops. 573 */ 574 int[] piecePosition = Pieces.getPiecePos(pieceToMove); 575 int[][] possiblePosition = distantHopping(piecePosition); 576 577 578 cell[piecePosition[0]][piecePosition[1]] = " "; 579 // apply Breadth-First-Search to accomplish consecutive hops 580 for (int k = 0; possiblePosition[k][0] != 0; k++) { 581 int[][] recursion = distantHopping(possiblePosition[k]); 582 possiblePosition = Services.concatTwoArrays(possiblePosition, recursion); 583 } 584 possiblePosition = Services.concatTwoArrays(possiblePosition, adjacentHopping(piecePosition)); 585 586 cell[piecePosition[0]][piecePosition[1]] = pieceToMove; 587 return possiblePosition; 588 } 589 590 public static int getPossiblePositionCount(String pieceToMove) { 591 int count = 0; 592 int[][] possiblePosition = getPossiblePosition(pieceToMove); 593 594 for (int k = 0; possiblePosition[k][0] != 0; k++) { 595 count++; 596 } 597 return count; 598 } 599 600 private static int[][] adjacentHopping(int[] piecePosition) { 601 602 int[][] possiblePositions = new int[100][2]; 603 int pointer = 0; 604 int[] displacementAdjacent = {-1, 0, 1}; 605 // (-1,-1)(-1,0)(0,-1)(0,1)(1,0)(1,1) 606 607 for (int i : displacementAdjacent) { 608 for (int j : displacementAdjacent) { 609 // check whether the adjacent position is empty 610 String current = cell[piecePosition[0] + i][piecePosition[1] + j]; 611 if (current == EMPTY_MARK && i != -j) { 612 possiblePositions[pointer][0] = piecePosition[0] + i; 613 possiblePositions[pointer][1] = piecePosition[1] + j; 614 pointer++; 615 } 616 } 617 } 618 return possiblePositions; 619 } 620 621 private static int[][] distantHopping(int[] piecePosition) { 622 int[][] possiblePos = new int[100][2]; 623 int[] displacement = {-1, 0, 1}; 624 // stores possible direction 625 626 for (int x : displacement) { 627 for (int y : displacement) { 628 possiblePos = Services.concatTwoArrays(possiblePos, 629 distantHoppingForOneDirection(x, y, piecePosition, true)); 630 } 631 } 632 633 return possiblePos; 634 } 635 636 public static boolean isPosInsideDiagram(String position) { 637 return !(position == OUTSIDE_MARK || position == null); 638 } 639 640 private static int[][] distantHoppingForOneDirection(int x, int y, 641 int[] piecePos, boolean isDistantHoppingDisabled) { 642 /* 643 * x: indicates up or down moveAward in x direction. y: indicates up or down 644 * moveAward in x direction 645 */ 646 int[][] possiblePos = new int[100][2]; 647 int[] displacement = (isDistantHoppingDisabled)?new int[]{1}:new int[]{1, 2, 3, 4, 5, 6, 7, 8}; 648 // stores possible displacements of coordinates in each direction 649 int pointer = 0; 650 boolean isDeadDirection; 651 652 for (int i : displacement) { 653 // avoid illegal direction 654 if (x * y == -1) 655 continue; 656 // avoid array index out of bound 657 boolean isiInside = (x == 0) || ((x == -1) ? piecePos[0] > 1 + 1 : piecePos[0] < 17 - 1); 658 boolean isjInside = (y == 0) || ((y == -1) ? piecePos[1] > 1 + 1 : piecePos[1] < 17 - 1); 659 boolean isInside = isiInside 660 && isjInside 661 && isPosInsideDiagram(cell[piecePos[0] + i * 2 * x - 1 * x][piecePos[1] + i* 2 * y - 1 * y]) 662 && isPosInsideDiagram(cell[piecePos[0] + i * 2 * x][piecePos[1] + i * 2 * y]); 663 if (!isInside) 664 break; 665 boolean isAvailable = (isDeadDirection = !(cell[piecePos[0] + i * x][piecePos[1] + i * y] == EMPTY_MARK) 666 && cell[piecePos[0] + i * 2 * x][ piecePos[1] + i * 2 * y] == EMPTY_MARK); 667 668 label1: 669 if (isAvailable) { 670 // position between object position and hopped piece 671 // ought to be empty 672 for (int ii = i + 1; ii < 2 * i; ii++) { 673 if (cell[piecePos[0] + ii * x][piecePos[1] + ii * y] != EMPTY_MARK) { 674 isDeadDirection = true; 675 break label1; 676 } 677 } 678 possiblePos[pointer][0] = piecePos[0] + i * 2 * x; 679 possiblePos[pointer][1] = piecePos[1] + i * 2 * y; 680 pointer++; 681 } 682 683 if (isDeadDirection) 684 break; 685 } 686 return possiblePos; 687 } 688 689 } 690 } 691 692 class PieceActionListener extends MouseAdapter{//棋子事件侦听 693 private final static ImageIcon imgPossiblePosition = new ImageIcon("Piece_Transparant.PNG"); 694 private static boolean isPieceSelected; 695 private static JLabel[] lblPossible = new JLabel[50]; 696 private int[][] possiblePos = new int[50][2]; 697 private String piece; 698 699 public PieceActionListener(String piece) { 700 this.piece = piece + " "; 701 } 702 703 public static void clearPossiblePos() {//清空可能到达的位置 704 for (int index = 0; lblPossible[index] != null; index++) { 705 ChineseChecker.myFrame.panel.remove(lblPossible[index]); 706 } 707 ChineseChecker.myFrame.repaint(); 708 isPieceSelected = false; 709 } 710 711 @Override 712 public void mouseClicked(MouseEvent arg0) {//鼠标点击事件处理 713 if (ChineseChecker.series[ChineseChecker.currentIndex] != piece.charAt(0)) 714 return; 715 if (!ChineseChecker.gameStatus) 716 return; 717 718 clearPossiblePos(); 719 showPossiblePos(); 720 isPieceSelected = true; 721 ChineseChecker.pieceToMove = piece.substring(0, 2); 722 ChineseChecker.piecePos = new int[]{Pieces.pieces[piece.charAt(0) - 65][piece.charAt(1) - 48][0], 723 Pieces.pieces[piece.charAt(0) - 65][piece.charAt(1) - 48][1]}; 724 ChineseChecker.isPieceToMoveAcquired = true; 725 } 726 727 @Override 728 public void mouseEntered(MouseEvent arg0) {//鼠标移动事件处理 729 if (!ChineseChecker.gameStatus) 730 return; 731 if (ChineseChecker.series[ChineseChecker.currentIndex] != piece.charAt(0)) 732 return; 733 if (isPieceSelected) 734 return; 735 showPossiblePos(); 736 } 737 738 @Override 739 public void mouseExited(MouseEvent arg0) {//鼠标挪开事件处理 740 if (isPieceSelected) 741 return; 742 for (int k = 0; lblPossible[k] != null; k++) { 743 ChineseChecker.myFrame.panel.remove(lblPossible[k]); 744 ChineseChecker.myFrame.repaint(); 745 } 746 } 747 748 public void showPossiblePos() {//展示可能到达的位置 749 possiblePos = Pieces.Next.getPossiblePosition(piece); 750 for (int k = 0; k < possiblePos.length && possiblePos[k][0] != 0; k++) { 751 lblPossible[k] = new JLabel(imgPossiblePosition); 752 lblPossible[k].addMouseListener(new PossiblePositionListener(piece, 753 possiblePos[k])); 754 ChineseChecker.myFrame.panel.add(lblPossible[k], JLayeredPane.MODAL_LAYER); 755 int[] positionInCanvas = Map.map[possiblePos[k][0]][possiblePos[k][1]]; 756 lblPossible[k].setBounds(positionInCanvas[0], positionInCanvas[1], 39, 39); 757 } 758 } 759 } 760 761 class PossiblePositionListener extends MouseAdapter { 762 763 public static String piece; 764 public int[] position = new int[2]; 765 public final static String EMPTY_MARK = "** "; 766 public final static String OUTSIDE_MARK = " "; 767 public final static String SPACE_MARK = " "; 768 PossiblePositionListener(String piece, int[] position) { 769 this.piece = piece; 770 this.position = position; 771 } 772 773 @Override 774 public void mouseClicked(MouseEvent arg0) { 775 if (!ChineseChecker.gameStatus) 776 return; 777 778 Pieces.cell[Pieces.getPiecePos(piece)[0]][Pieces.getPiecePos(piece)[1]] = EMPTY_MARK; 779 Pieces.cell[position[0]][position[1]] = piece + SPACE_MARK; 780 781 ChineseChecker.myFrame.move(piece, position); 782 PieceActionListener.clearPossiblePos(); 783 ChineseChecker.posToGoTo = position; 784 ChineseChecker.isPositionToGoToAcquired = true; 785 } 786 787 } 788 789 class Services { 790 791 public static void msg(String content) { 792 JOptionPane.showMessageDialog(null, content, "Chinese Checkers", 793 JOptionPane.INFORMATION_MESSAGE); 794 } 795 796 public static String in(String content) { 797 return JOptionPane.showInputDialog(null, content, "Chinese Checkers", 798 JOptionPane.INFORMATION_MESSAGE); 799 } 800 801 802 public static int[][] concatTwoArrays(int[][] targetArray, int[][] temporaryArray) { 803 /** combine two 2D arrays into one. */ 804 int pointer = 0;// point to the operating index of a1 805 while (targetArray[pointer][0] != 0) { 806 pointer++; 807 } 808 for (int j = 0; ; j++) { 809 boolean isRepeated = false; 810 if (temporaryArray[j][0] == 0) 811 break; 812 for (int i = 0; i < pointer; i++) 813 if (temporaryArray[j][0] == targetArray[i][0] && temporaryArray[j][1] == targetArray[i][1]) { 814 isRepeated = true; 815 break; 816 } 817 if (!isRepeated) 818 targetArray[pointer++] = temporaryArray[j]; 819 } 820 return targetArray; 821 } 822 } 823 824 class Timer { 825 826 private long startingTime; 827 private long interruptedTime; 828 private boolean paused; 829 830 public Timer() { 831 this.startingTime = System.currentTimeMillis(); 832 } 833 834 public long listen() { 835 if (paused) 836 return (30000 - interruptedTime + startingTime) / 1000; 837 long cur = System.currentTimeMillis(); 838 return (30000 - cur + startingTime) / 1000; 839 } 840 841 public void pause() { 842 this.interruptedTime = System.currentTimeMillis(); 843 this.paused = true; 844 } 845 } 846 847 class Trace { 848 849 public static final int MAX_STACK_SIZE = 1000; 850 public static int step = 1; 851 public static boolean isSkipped; 852 public static String[] pieceStack = new String[MAX_STACK_SIZE]; 853 public static int[][] prevPosStack = new int[MAX_STACK_SIZE][2]; 854 public static int[][] postPosStack = new int[MAX_STACK_SIZE][2]; 855 856 public boolean isSkipped() { 857 return isSkipped; 858 } 859 860 public static void recordStep(String piece, int[] prev, int[] post) { 861 pieceStack[step] = piece; 862 prevPosStack[step] = prev; 863 postPosStack[step] = post; 864 } 865 866 public static void nextStep() { 867 ChineseChecker.currentIndex= Trace.step % ChineseChecker.numberOfPlayers; 868 } 869 }