首页 > 代码库 > HDU 1691 Chinese Chess
HDU 1691 Chinese Chess
严格按规则实现、使用多态加异常来简化代码逻辑
Player类表示玩家
存储身份信息和持有棋子信息
Board类表示棋盘
可以通过坐标得到棋子
Piece类表示棋子
存储位置信息和持有人信息
各个棋子的实现提供对棋子走法的支持
Game类控制程序逻辑
具体见代码
1 package acm.hdu.p1691; 2 3 import java.io.FileInputStream; 4 import java.util.ArrayList; 5 import java.util.List; 6 import java.util.Scanner; 7 8 @SuppressWarnings("serial") 9 class ChessException extends Exception 10 { 11 public ChessException(String message) 12 { 13 super(message); 14 } 15 } 16 17 enum PlayerColor 18 { 19 RED, BLACK 20 } 21 22 class Player 23 { 24 private PlayerColor color; 25 private Board board; 26 private List<Piece> pieces = new ArrayList<Piece>(); 27 28 public Player(PlayerColor color) 29 { 30 this.color = color; 31 } 32 33 public PlayerColor getColor() 34 { 35 return color; 36 } 37 38 public void setBoard(Board board) 39 { 40 this.board = board; 41 } 42 43 public void addPiece(Piece piece) 44 { 45 this.pieces.add(piece); 46 } 47 48 public void removePiece(Piece piece) 49 { 50 this.pieces.remove(piece); 51 } 52 53 public List<Piece> getPieces() 54 { 55 return pieces; 56 } 57 58 public Piece getKing() 59 { 60 for (Piece piece : pieces) 61 if (piece instanceof PieceKing) 62 return piece; 63 return null; 64 } 65 } 66 67 class Board 68 { 69 private Piece pieces[][]; 70 71 public Board() 72 { 73 pieces = new Piece[10][9]; 74 } 75 76 public void setCell(int row, int column, Piece piece) 77 { 78 pieces[row - 1][column - 1] = piece; 79 } 80 81 public Piece getCell(int row, int column) 82 { 83 return pieces[row - 1][column - 1]; 84 } 85 86 @Override 87 public String toString() 88 { 89 String result = ""; 90 91 result += String.format("%2s", ""); 92 for (int column = 1; column <= 9; column++) 93 result += String.format("%12s", column); 94 result += "\n"; 95 96 for (int row = 1; row <= 10; row++) 97 { 98 result += String.format("%2s", row); 99 for (int column = 1; column <= 9; column++)100 result += (String.format("%12s", getCell(row, column)));101 result += "\n";102 }103 return result;104 }105 }106 107 abstract class Piece108 {109 private Player player;110 private int currentRow;111 private int currentColumn;112 113 public Piece(Player player)114 {115 this.player = player;116 }117 118 public Player getPlayer()119 {120 return player;121 }122 123 public int getCurrentRow()124 {125 return currentRow;126 }127 128 public void setCurrentRow(int currentRow)129 {130 this.currentRow = currentRow;131 }132 133 public int getCurrentColumn()134 {135 return currentColumn;136 }137 138 public void setCurrentColumn(int currentColumn)139 {140 this.currentColumn = currentColumn;141 }142 143 @Override144 public String toString()145 {146 String simpleName = getClass().getSimpleName().replaceAll("Piece", "");147 if (player.getColor() == PlayerColor.RED)148 return simpleName;149 else150 return String.format("[%s]", simpleName);151 }152 153 public boolean isCrossRiver(int row, int column)154 {155 switch (player.getColor())156 {157 case RED:158 return row <= 5;159 default:160 return row >= 6;161 }162 }163 164 public boolean isLeavePalace(int row, int column)165 {166 int minRow, maxRow;167 int minColumn = 4, maxColumn = 6;168 switch (player.getColor())169 {170 case RED:171 minRow = 8;172 maxRow = 10;173 break;174 default:175 minRow = 1;176 maxRow = 3;177 break;178 }179 if (row < minRow || row > maxRow)180 return true;181 if (column < minColumn || column > maxColumn)182 return true;183 return false;184 }185 186 public abstract void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn)187 throws ChessException;188 }189 190 class PieceKing extends Piece191 {192 193 public PieceKing(Player player)194 {195 super(player);196 }197 198 @Override199 public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException200 {201 //基本走法202 {203 if (Math.abs(startRow - endRow) + Math.abs(startColumn - endColumn) != 1)204 throw new ChessException("checkMove PieceKing Basic");205 }206 //离开老窝207 {208 if (isLeavePalace(endRow, endColumn))209 throw new ChessException("checkMove PieceKing LeavePalace");210 }211 }212 }213 214 class PieceMandarins extends Piece215 {216 217 public PieceMandarins(Player player)218 {219 super(player);220 }221 222 @Override223 public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException224 {225 //基本走法226 {227 if (Math.abs(startRow - endRow) != Math.abs(startColumn - endColumn))228 throw new ChessException("checkMove PieceMandarins Basic");229 if (Math.abs(startRow - endRow) != 1)230 throw new ChessException("checkMove PieceMandarins Basic");231 }232 //离开老窝233 {234 if (isLeavePalace(endRow, endColumn))235 throw new ChessException("checkMove PieceMandarins LeavePalace");236 }237 }238 }239 240 class PieceElephants extends Piece241 {242 243 public PieceElephants(Player player)244 {245 super(player);246 }247 248 @Override249 public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException250 {251 //基本走法252 {253 if (Math.abs(startRow - endRow) != 2 || Math.abs(startColumn - endColumn) != 2)254 throw new ChessException("checkMove PieceElephants Basic");255 }256 //阻挡257 {258 if (board.getCell((startRow + endRow) / 2, (startColumn + endColumn) / 2) != null)259 throw new ChessException("checkMove PieceElephants Block");260 }261 //过河262 {263 if (isCrossRiver(endRow, endColumn))264 throw new ChessException("checkMove PieceElephants River");265 }266 }267 }268 269 class PieceKnights extends Piece270 {271 272 public PieceKnights(Player player)273 {274 super(player);275 }276 277 @Override278 public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException279 {280 //基本走法281 {282 boolean flag1 = (Math.abs(startRow - endRow) == 2 && Math.abs(startColumn - endColumn) == 1);283 boolean flag2 = (Math.abs(startRow - endRow) == 1 && Math.abs(startColumn - endColumn) == 2);284 if (!flag1 && !flag2)285 throw new ChessException("checkMove PieceKnights Basic");286 }287 //阻挡288 {289 if (startRow + 2 == endRow && board.getCell(startRow + 1, startColumn) != null)290 throw new ChessException("checkMove PieceKnights Block");291 if (startRow - 2 == endRow && board.getCell(startRow - 1, startColumn) != null)292 throw new ChessException("checkMove PieceKnights Block");293 if (startColumn + 2 == endColumn && board.getCell(startRow, startColumn + 1) != null)294 throw new ChessException("checkMove PieceKnights Block");295 if (startColumn - 2 == endColumn && board.getCell(startRow, startColumn - 1) != null)296 throw new ChessException("checkMove PieceKnights Block");297 }298 }299 }300 301 class PieceRooks extends Piece302 {303 304 public PieceRooks(Player player)305 {306 super(player);307 }308 309 @Override310 public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException311 {312 //基本走法313 {314 if (startRow != endRow && startColumn != endColumn)315 throw new ChessException("checkMove PieceRooks Basic");316 }317 318 //阻挡319 {320 if (startColumn == endColumn)321 for (int row = Math.min(startRow, endRow) + 1; row <= Math.max(startRow, endRow) - 1; row++)322 if (board.getCell(row, startColumn) != null)323 throw new ChessException("checkMove PieceRooks Block");324 if (startRow == endRow)325 for (int column = Math.min(startColumn, endColumn) + 1; column <= Math.max(startColumn, endColumn) - 1; column++)326 if (board.getCell(startRow, column) != null)327 throw new ChessException("checkMove PieceRooks Block");328 }329 330 }331 }332 333 class PieceCannons extends Piece334 {335 336 public PieceCannons(Player player)337 {338 super(player);339 }340 341 @Override342 public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException343 {344 //基本走法345 {346 if (startRow != endRow && startColumn != endColumn)347 throw new ChessException("checkMove PieceCannons Basic");348 }349 350 //阻挡(若目标为空)351 if (board.getCell(endRow, endColumn) == null)352 {353 if (startColumn == endColumn)354 for (int row = Math.min(startRow, endRow) + 1; row <= Math.max(startRow, endRow) - 1; row++)355 if (board.getCell(row, startColumn) != null)356 throw new ChessException("checkMove PieceCannons Block");357 if (startRow == endRow)358 for (int column = Math.min(startColumn, endColumn) + 1; column <= Math.max(startColumn, endColumn) - 1; column++)359 if (board.getCell(startRow, column) != null)360 throw new ChessException("checkMove PieceCannons Block");361 }362 //阻挡(若目标不为空)363 else364 {365 int blockCount = 0;366 if (startColumn == endColumn)367 for (int row = Math.min(startRow, endRow) + 1; row <= Math.max(startRow, endRow) - 1; row++)368 if (board.getCell(row, startColumn) != null)369 blockCount++;370 if (startRow == endRow)371 for (int column = Math.min(startColumn, endColumn) + 1; column <= Math.max(startColumn, endColumn) - 1; column++)372 if (board.getCell(startRow, column) != null)373 blockCount++;374 if (blockCount != 1)375 throw new ChessException("checkMove PieceCannons Block " + blockCount);376 }377 378 }379 }380 381 class PiecePawns extends Piece382 {383 384 public PiecePawns(Player player)385 {386 super(player);387 }388 389 @Override390 public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException391 {392 //基本走法(未过河)393 if (!isCrossRiver(startRow, startColumn))394 {395 //步数396 if (Math.abs(startRow - endRow) + Math.abs(startColumn - endColumn) != 1)397 throw new ChessException("checkMove PiecePawns Basic Not Cross River");398 //方向399 if (startColumn != endColumn)400 throw new ChessException("checkMove PiecePawns Basic Not Cross River");401 if (getPlayer().getColor() == PlayerColor.RED && startRow < endRow)402 throw new ChessException("checkMove PiecePawns Basic Not Cross River");403 if (getPlayer().getColor() == PlayerColor.BLACK && startRow > endRow)404 throw new ChessException("checkMove PiecePawns Basic Not Cross River");405 }406 //基本走法(已过河)407 else408 {409 //步数410 if (Math.abs(startRow - endRow) + Math.abs(startColumn - endColumn) != 1)411 throw new ChessException("checkMove PiecePawns Basic Crossed River");412 //方向413 if (getPlayer().getColor() == PlayerColor.RED && startRow < endRow)414 throw new ChessException("checkMove PiecePawns Basic Crossed River");415 if (getPlayer().getColor() == PlayerColor.BLACK && startRow > endRow)416 throw new ChessException("checkMove PiecePawns Basic Crossed River");417 }418 }419 420 }421 422 class PieceFactory423 {424 public Piece createPiece(Player playerRed, Player playerBlack, int value)425 {426 if (value =http://www.mamicode.com/= 0)427 return null;428 Player currentPlayer;429 if (value <= 7)430 currentPlayer = playerRed;431 else432 {433 currentPlayer = playerBlack;434 value -= 7;435 }436 switch (value)437 {438 case 1:439 return new PieceKing(currentPlayer);440 case 2:441 return new PieceMandarins(currentPlayer);442 case 3:443 return new PieceElephants(currentPlayer);444 case 4:445 return new PieceKnights(currentPlayer);446 case 5:447 return new PieceRooks(currentPlayer);448 case 6:449 return new PieceCannons(currentPlayer);450 case 7:451 return new PiecePawns(currentPlayer);452 default:453 return null;454 }455 }456 }457 458 class Game459 {460 private Board board;461 private Player[] players;462 private Player playerRed, playerBlack;463 private int currentPlayerIndex;464 465 public Game()466 {467 board = new Board();468 playerRed = new Player(PlayerColor.RED);469 playerBlack = new Player(PlayerColor.BLACK);470 players = new Player[] { playerRed, playerBlack };471 for (int i = 0; i < 2; i++)472 players[i].setBoard(board);473 }474 475 public void init(Scanner cin)476 {477 for (int row = 1; row <= 10; row++)478 for (int column = 1; column <= 9; column++)479 {480 int value =http://www.mamicode.com/ cin.nextInt();481 Piece piece = new PieceFactory().createPiece(playerRed, playerBlack, value);482 board.setCell(row, column, piece);483 if (piece != null)484 {485 piece.setCurrentRow(row);486 piece.setCurrentColumn(column);487 piece.getPlayer().addPiece(piece);488 }489 }490 // System.out.println("init ok");491 // System.out.println(board);492 493 }494 495 public int play(Scanner cin)496 {497 int n = cin.nextInt();498 int k = cin.nextInt();499 int errorStep = -1;500 currentPlayerIndex = k;501 502 for (int step = 1; step <= n; step++)503 {504 int startRow = cin.nextInt();505 int startColumn = cin.nextInt();506 int endRow = cin.nextInt();507 int endColumn = cin.nextInt();508 // System.out.println("Move Step : " + step);509 // System.out.println("Command : " + startRow + " " + startColumn + " " + endRow + " " + endColumn);510 if (errorStep != -1)511 {512 // System.out.println("Errored!");513 continue;514 }515 try516 {517 moveOneStep(startRow, startColumn, endRow, endColumn);518 }519 catch (ChessException e)520 {521 errorStep = step;522 // System.err.println("Move Step : " + step + " Error!");523 // System.err.println(e);524 }525 // System.out.println(board);526 currentPlayerIndex = 1 - currentPlayerIndex;527 }528 529 return errorStep;530 }531 532 private void checkGameOver() throws ChessException533 {534 for (Player player : players)535 if (player.getKing() == null)536 throw new ChessException("checkGameOver " + player.getColor());537 }538 539 private void checkCoordinates(int startRow, int startColumn, int endRow, int endColumn)540 throws ChessException541 {542 if (startRow < 1 || startRow > 10)543 throw new ChessException("checkCoordinates startRow");544 if (startColumn < 1 || startColumn > 9)545 throw new ChessException("checkCoordinates startColumn");546 if (endRow < 1 || endRow > 10)547 throw new ChessException("checkCoordinates endRow");548 if (endColumn < 1 || endColumn > 9)549 throw new ChessException("checkCoordinates endColumn");550 }551 552 private void checkEmpty(int startRow, int startColumn, int endRow, int endColumn)553 throws ChessException554 {555 if (board.getCell(startRow, startColumn) == null)556 throw new ChessException("checkEmpty " + board.getCell(startRow, startColumn));557 }558 559 private void checkOwner(int startRow, int startColumn, int endRow, int endColumn)560 throws ChessException561 {562 Player currentPlayer = players[currentPlayerIndex];563 if (board.getCell(startRow, startColumn).getPlayer() != currentPlayer)564 throw new ChessException("checkOwner " + board.getCell(startRow, startColumn));565 if (board.getCell(endRow, endColumn) != null && board.getCell(endRow, endColumn).getPlayer() == currentPlayer)566 throw new ChessException("checkOwner " + board.getCell(startRow, startColumn));567 }568 569 private void checkMove(int startRow, int startColumn, int endRow, int endColumn)570 throws ChessException571 {572 board.getCell(startRow, startColumn).checkMove(board, startRow, startColumn, endRow, endColumn);573 }574 575 private void checkFaceToFace() throws ChessException576 {577 if (playerRed.getKing() == null || playerBlack.getKing() == null)578 return;579 if (playerRed.getKing().getCurrentColumn() != playerBlack.getKing().getCurrentColumn())580 return;581 boolean exist = false;582 for (int row = playerBlack.getKing().getCurrentRow() + 1; row <= playerRed.getKing().getCurrentRow() - 1; row++)583 if (board.getCell(row, playerBlack.getKing().getCurrentColumn()) != null)584 exist = true;585 if (!exist)586 throw new ChessException("checkFaceToFace ");587 }588 589 private boolean isGameOver()590 {591 return (playerRed.getKing() == null || playerBlack.getKing() == null);592 }593 594 private boolean isCheckmate()595 {596 for (Piece piece : players[1 - currentPlayerIndex].getPieces())597 try598 {599 piece.checkMove(board, piece.getCurrentRow(), piece.getCurrentColumn(),600 players[currentPlayerIndex].getKing().getCurrentRow()601 , players[currentPlayerIndex].getKing().getCurrentColumn());602 return true;603 }604 catch (ChessException e)605 {606 // TODO Auto-generated catch block607 // e.printStackTrace();608 }609 return false;610 }611 612 public void moveOneStep(int startRow, int startColumn, int endRow, int endColumn)613 throws ChessException614 {615 //判断游戏结束616 checkGameOver();617 //记录是否处于将军状态618 boolean isCheckmateBefore = isCheckmate();619 //判断坐标是否合法620 checkCoordinates(startRow, startColumn, endRow, endColumn);621 //判断起始位置是否为空622 checkEmpty(startRow, startColumn, endRow, endColumn);623 //判断所有者624 checkOwner(startRow, startColumn, endRow, endColumn);625 //判断移动626 checkMove(startRow, startColumn, endRow, endColumn);627 628 //移动629 {630 Piece pieceStart = board.getCell(startRow, startColumn);631 Piece pieceEnd = board.getCell(endRow, endColumn);632 if (pieceEnd != null)633 pieceEnd.getPlayer().removePiece(pieceEnd);634 board.setCell(endRow, endColumn, pieceStart);635 board.setCell(startRow, startColumn, null);636 pieceStart.setCurrentRow(endRow);637 pieceStart.setCurrentColumn(endColumn);638 }639 640 //如果游戏结束641 if (isGameOver())642 return;643 //判断是否脱离将军状态644 boolean isCheckmateAfter = isCheckmate();645 if (isCheckmateBefore && isCheckmateAfter)646 throw new ChessException("is checkmate ");647 //判断老将对面648 checkFaceToFace();649 650 }651 }652 653 public class Main654 {655 public static void main(String args[]) throws Exception656 {657 // System.setIn(new FileInputStream("input2"));658 Scanner cin = new Scanner(System.in);659 int caseCount = cin.nextInt();660 for (int caseIndex = 1; caseIndex <= caseCount; caseIndex++)661 {662 Game game = new Game();663 game.init(cin);664 int result = game.play(cin);665 if (result == -1)666 System.out.println(String.format("Case %d: Legal move", caseIndex));667 else668 System.out.println(String.format("Case %d: Illegal move on step %d", caseIndex, result));669 670 }671 }672 }
HDU 1691 Chinese Chess
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。