首页 > 代码库 > 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