奥赛罗(黑白棋)Java实现
奥赛罗是两人在8×8的棋盘上玩的游戏,棋子的一面是白色,另一面是黑色。下棋时,先下的玩家将棋子的白面朝上,后下的玩家将棋子的黑面朝上。玩家交替地将棋子放在棋盘的空位上。在放置棋子时,玩家必须夹住对方的至少一个棋子。当棋子沿横、纵和对角线方向排在一条直线上,并且两端的棋子都是当前玩家的颜色时,称棋子被夹住了,见下图。当玩家下了一步之后,所有被夹住的对方棋子都将被翻过来,从而变为当前玩家的棋子(有可能在一步中夹住多行棋子)。
白色的合法移动
(2,3),(3,3),(3,5),(3,6)
(6,2),(7,3),(7,4),(7,5)
白方下在(7,3)之后的棋盘局面
写一个程序,读入若干奥赛罗游戏。输入的第一行是要处理的游戏个数,每个游戏有棋盘局面及其后所跟的一系列命令组成。
棋盘局面由9行组成,前8行给出了棋盘的当前状态。这8行每行包括8个字符,所有这些字符是如下之一: ‘-’ 表示空格子
‘B’ 表示放有黑色棋子的格子
‘W’ 表示放有白色棋子的格子
第9行是‘B’或‘W’之一,以指出当前游戏者。你可以假定数据是合法格式的。 命令可以是为当前玩家列处所有可能的走步,走一步或退出当前游戏。
每条命令占一行且无空格。命令的格式如下:
1. 为当前游戏者列出所有可能的走步: 命令是‘L’,在命令行的第一列。 程序应检查棋盘并用格式(x, y)打印当前玩家的所有合法走步,这里x代表合法走步的行号,y代表列号。这些走步应当被按行优先顺序打印,也就是说: (1) 如果j大于i,则所有行号是i的合法走步将在所有行号是j的合法走步之前打印; (2) 如果有多于一个的合法走步的行号是i,则这些走步将按列号升序打印。每一个合法走步之间输出没有空格。 (3) 所有的合法走步应当输出在一行上。如果因为当前游戏者不可能夹住任何棋子而不存在合法走步,程序应当打印“No legal move.“信息。
2. 走一步: 命令是‘M’,在命令行的第1列,其后是在第2、3列的两个数字。 这两个数字是放置当前玩家颜色的棋子的格子的行、列号,除非当前游戏者没有合法走步。如果当前玩家没有合法走步,当前游戏者将首先换成另一个游戏者,此走步将是新游戏者的走步。你可以假定此时走步一定是合法的。你应该将变更记录至棋盘,包括加入新棋子和改变所有被夹住棋子的颜色(将棋子翻过来)。走完了此步之后,按 “Black-xx White-yy”的格式(例,Black-1 White-4)打印棋盘上每种颜色的棋子数目,这里xx是棋盘上黑色棋子的数目,yy是棋盘上白色棋子的数目。走完一步后,当前游戏者将换成没有走步的游戏者。
3. 退出当前游戏: 命令是‘Q’,在命令行的第1列。 在这里,用同输入相同的格式打印最后的棋盘局面。这终止了当前游戏的命令输入。 你可以假定命令在语法上是正确的。用一个空行隔开不同游戏的输出,输出中的其他地方不得出现空行。请见下图输入样例与输出样例。
input:
output:
分析:明确了游戏规则写起来就容易,重点是对棋子落点的判断,还有要熟悉对String的操作。
//Main.java package test; import test.Game; /* 请注意: ********************************************************************** *********以下为主类文件中的代码,请根据主类代码编写Game类和Board类******** *****************主类代码已经编写完成并隐藏,无需再次编写**************** ***Game类和Board类已经建好,请同学们点击左上角代码文件后的小三角进行切换*** ********************************************************************** */ import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner myScanner = new Scanner(System.in); int gameRounds = myScanner.nextInt(); for (int i = 0; i < gameRounds; i++) { Game game = new Game(); game.readGame(myScanner); game.process(myScanner); } } }
//Game.java package test; import java.util.Scanner; import test.Board; import java.util.List; import java.util.ArrayList; public class Game { private Board board = new Board(); //棋盘 private char currentPlayer = 'B'; //轮到下棋的一方 static List<String> action = new ArrayList<>(); public void readGame(Scanner scanner) { board.init(0,0); action.clear(); String str; for(int i=0;i<8;i++) { str = scanner.next(); for(int j=0;j<8;j++) board.setboard(i,j,str.charAt(j)); } currentPlayer = scanner.next().charAt(0); str = " "; while(str.charAt(0) != 'Q') { str = scanner.next(); if(str.charAt(0) == 'L') action.add(board.scan(currentPlayer)); else if(str.charAt(0) == 'M') { int x = Integer.parseInt(str.substring(1,2))-1; int y = Integer.parseInt(str.substring(2))-1; if(board.scan(currentPlayer).equals("No legal move.")) { if(currentPlayer == 'W') currentPlayer = 'B'; else currentPlayer = 'W'; //change for once } board.setboard(x,y,currentPlayer); board.refresh(x,y,currentPlayer); //refresh board String record = "Black-"+board.count('b')+" White-"+board.count('w'); action.add(record); if(currentPlayer == 'W') //change again currentPlayer = 'B'; else currentPlayer = 'W'; } } } public void process(Scanner scanner) { for(int i=0;i<action.size();i++) System.out.println(action.get(i)); board.getboard(); } }
//Board.java package test; //import java.util.Scanner; public class Board { //棋盘的数据 private char[][] board = new char[8][8]; private int wnum; private int bnum; private int dire1(int i,int j,char sym) { int flag =0; for(int k=i-1;k>=0;k--) { if(board[k][j] == '-') break; else if(board[k][j] == sym) { if(k == i-1) break; else { flag = 1; break; } } } return flag; } private int dire2(int i,int j,char sym) { int flag =0; for(int k=i+1;k<=7;k++) { if(board[k][j] == '-') break; else if(board[k][j] == sym) { if(k == i+1) break; else { flag = 1; break; } } } return flag; } private int dire3(int i,int j,char sym) { int flag =0; for(int k=j-1;k>=0;k--) { if(board[i][k] == '-') break; else if(board[i][k] == sym) { if(k == j-1) break; else { flag = 1; break; } } } return flag; } private int dire4(int i,int j,char sym) { int flag =0; for(int k=j+1;k<=7;k++) { if(board[i][k] == '-') break; else if(board[i][k] == sym) { if(k == j+1) break; else { flag = 1; break; } } } return flag; } private int dire5(int i,int j,char sym) { int flag =0; for(int k=i-1,l=j-1;k>=0&&l>=0;k--,l--) { if(board[k][l] == '-') break; else if(board[k][l] == sym) { if(k == i-1) break; else { flag = 1; break; } } } return flag; } private int dire6(int i,int j,char sym) { int flag =0; for(int k=i+1,l=j+1;k<=7&&l<=7;k++,l++) { if(board[k][l] == '-') break; else if(board[k][l] == sym) { if(k == i+1) break; else { flag = 1; break; } } } return flag; } private int dire7(int i,int j,char sym) { int flag =0; for(int k=i-1,l=j+1;k>=0&&l<=7;k--,l++) { if(board[k][l] == '-') break; else if(board[k][l] == sym) { if(k == i-1) break; else { flag = 1; break; } } } return flag; } private int dire8(int i,int j,char sym) { int flag =0; for(int k=i+1,l=j-1;k<=7&&l>=0;k++,l--) { if(board[k][l] == '-') break; else if(board[k][l] == sym) { if(k == i+1) break; else { flag = 1; break; } } } return flag; } public void init(int a,int b) { wnum = a; bnum = b; } public void setboard(int x,int y,char c) { if(c == 'B' && board[x][y] != 'W') bnum++; else if(c == 'W' && board[x][y] != 'B') wnum++; else if(c == 'B' && board[x][y] == 'W') { bnum++; wnum--; } else if(c == 'W' && board[x][y] == 'B') { bnum--; wnum++; } board[x][y] = c; } public void getboard() { for(int i=0;i<8;i++) for(int j=0;j<8;j++) { System.out.print(board[i][j]); if(j == 7) System.out.println(); } } public int count(char sym) { if(sym == 'w') return wnum; else return bnum; } public void refresh(int i,int j,char sym) { if(dire1(i,j,sym) == 1) { for(int k=i-1;k>=0;k--) { if(board[k][j] == sym) break; setboard(k,j,sym); refresh(k,j,sym); //deep search } } if(dire2(i,j,sym) == 1) { for(int k=i+1;k<=7;k++) { if(board[k][j] == sym) break; setboard(k,j,sym); refresh(k,j,sym); } } if(dire3(i,j,sym) == 1) { for(int k=j-1;k>=0;k--) { if(board[i][k] == sym) break; setboard(i,k,sym); refresh(i,k,sym); } } if(dire4(i,j,sym) == 1) { for(int k=j+1;k<=7;k++) { if(board[i][k] == sym) break; setboard(i,k,sym); refresh(i,k,sym); } } if(dire5(i,j,sym) == 1) { for(int k=i-1,l=j-1;k>=0&&l>=0;k--,l--) { if(board[k][l] == sym) break; setboard(k,l,sym); refresh(k,l,sym); } } if(dire6(i,j,sym) == 1) { for(int k=i+1,l=j+1;k<=7&&l<=7;k++,l++) { if(board[k][l] == sym) break; setboard(k,l,sym); refresh(k,l,sym); } } if(dire7(i,j,sym) == 1) { for(int k=i-1,l=j+1;k>=0&&l<=7;k--,l++) { if(board[k][l] == sym) break; setboard(k,l,sym); refresh(k,l,sym); } } if(dire8(i,j,sym) == 1) { for(int k=i+1,l=j-1;k<=7&&l>=0;k++,l--) { if(board[k][l] == sym) break; setboard(k,l,sym); refresh(k,l,sym); } } } public String scan(char sym) { String str = ""; for(int i=0;i<8;i++) for(int j=0;j<8;j++) { if(board[i][j] == '-') { if(dire1(i,j,sym) == 1) str += "("+(i+1)+","+(j+1)+")"; else if(dire2(i,j,sym) == 1) str += "("+(i+1)+","+(j+1)+")"; else if(dire3(i,j,sym) == 1) str += "("+(i+1)+","+(j+1)+")"; else if(dire4(i,j,sym) == 1) str += "("+(i+1)+","+(j+1)+")"; else if(dire5(i,j,sym) == 1) str += "("+(i+1)+","+(j+1)+")"; else if(dire6(i,j,sym) == 1) str += "("+(i+1)+","+(j+1)+")"; else if(dire7(i,j,sym) == 1) str += "("+(i+1)+","+(j+1)+")"; else if(dire8(i,j,sym) == 1) str += "("+(i+1)+","+(j+1)+")"; //eight directions } } if(str == "") return "No legal move."; else return str; } }
运行结果: