码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 1691 Chinese Chess

时间:2014-10-29 07:05:06      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:style   blog   io   color   os   ar   使用   java   for   

严格按规则实现、使用多态加异常来简化代码逻辑

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 Piece
108 {
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     @Override
144     public String toString()
145     {
146         String simpleName = getClass().getSimpleName().replaceAll("Piece", "");
147         if (player.getColor() == PlayerColor.RED)
148             return simpleName;
149         else
150             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 Piece
191 {
192 
193     public PieceKing(Player player)
194     {
195         super(player);
196     }
197 
198     @Override
199     public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException
200     {
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 Piece
215 {
216 
217     public PieceMandarins(Player player)
218     {
219         super(player);
220     }
221 
222     @Override
223     public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException
224     {
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 Piece
241 {
242 
243     public PieceElephants(Player player)
244     {
245         super(player);
246     }
247 
248     @Override
249     public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException
250     {
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 Piece
270 {
271 
272     public PieceKnights(Player player)
273     {
274         super(player);
275     }
276 
277     @Override
278     public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException
279     {
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 Piece
302 {
303 
304     public PieceRooks(Player player)
305     {
306         super(player);
307     }
308 
309     @Override
310     public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException
311     {
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 Piece
334 {
335 
336     public PieceCannons(Player player)
337     {
338         super(player);
339     }
340 
341     @Override
342     public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException
343     {
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         else
364         {
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 Piece
382 {
383 
384     public PiecePawns(Player player)
385     {
386         super(player);
387     }
388 
389     @Override
390     public void checkMove(Board board, int startRow, int startColumn, int endRow, int endColumn) throws ChessException
391     {
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         else
408         {
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 PieceFactory
423 {
424     public Piece createPiece(Player playerRed, Player playerBlack, int value)
425     {
426         if (value == 0)
427             return null;
428         Player currentPlayer;
429         if (value <= 7)
430             currentPlayer = playerRed;
431         else
432         {
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 Game
459 {
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 = 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             try
516             {
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 ChessException
533     {
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 ChessException
541     {
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 ChessException
554     {
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 ChessException
561     {
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 ChessException
571     {
572         board.getCell(startRow, startColumn).checkMove(board, startRow, startColumn, endRow, endColumn);
573     }
574 
575     private void checkFaceToFace() throws ChessException
576     {
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             try
598             {
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 block
607                 //                e.printStackTrace();
608             }
609         return false;
610     }
611 
612     public void moveOneStep(int startRow, int startColumn, int endRow, int endColumn)
613             throws ChessException
614     {
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 Main
654 {
655     public static void main(String args[]) throws Exception
656     {
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             else
668                 System.out.println(String.format("Case %d: Illegal move on step %d", caseIndex, result));
669 
670         }
671     }
672 }

 

HDU 1691 Chinese Chess

标签:style   blog   io   color   os   ar   使用   java   for   

原文地址:http://www.cnblogs.com/gwhahaha/p/4058463.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!