备忘库模式,用java实现象棋悔棋代码
时间: 2023-07-16 13:14:41 浏览: 183
下面是一个简单的Java代码实现,可以用于象棋中的悔棋功能:
```java
import java.util.Stack;
public class ChessBoard {
private int[][] board; // 棋盘矩阵,0表示空,1表示红棋,2表示黑棋
private Stack<Move> moveStack; // 棋谱栈,用于记录每一步的操作
public ChessBoard() {
board = new int[10][9];
moveStack = new Stack<>();
initialize();
}
// 初始化棋盘
private void initialize() {
// 红方
board[0][0] = board[0][8] = 1;
board[0][1] = board[0][7] = 2;
board[0][2] = board[0][6] = 3;
board[0][3] = board[0][5] = 4;
board[0][4] = 5;
board[2][1] = board[2][7] = 6;
board[3][0] = board[3][2] = board[3][4] = board[3][6] = 7;
board[3][8] = board[3][6] = board[3][4] = board[3][2] = 7;
board[9][0] = board[9][8] = -1;
board[9][1] = board[9][7] = -2;
board[9][2] = board[9][6] = -3;
board[9][3] = board[9][5] = -4;
board[9][4] = -5;
board[7][1] = board[7][7] = -6;
board[6][0] = board[6][2] = board[6][4] = board[6][6] = -7;
board[6][8] = board[6][6] = board[6][4] = board[6][2] = -7;
}
// 走棋
public boolean move(int fromX, int fromY, int toX, int toY) {
int chess = board[fromX][fromY];
if (chess == 0) {
return false;
}
if (chess > 0 && (toX < 0 || toX > 9 || toY < 0 || toY > 8)) {
return false; // 红方不能移出九宫格
}
if (chess < 0 && (toX < 7 || toX > 16 || toY < 0 || toY > 8)) {
return false; // 黑方不能移出九宫格
}
if (chess == 1 && (toX < 7 || toY < 3 || toY > 5)) {
return false; // 红方兵只能前进,不能后退或横着走
}
if (chess == -1 && (toX > 2 || toY < 3 || toY > 5)) {
return false; // 黑方卒只能前进,不能后退或横着走
}
if (chess == 2 || chess == -2 || chess == 5 || chess == -5) {
// 车或将,需要判断是否有障碍
if (fromX == toX) {
for (int i = Math.min(fromY, toY) + 1; i < Math.max(fromY, toY); i++) {
if (board[fromX][i] != 0) {
return false;
}
}
} else if (fromY == toY) {
for (int i = Math.min(fromX, toX) + 1; i < Math.max(fromX, toX); i++) {
if (board[i][fromY] != 0) {
return false;
}
}
} else {
return false; // 车和将只能横着或竖着走
}
}
if (chess == 3 || chess == -3 || chess == 4 || chess == -4) {
// 象或士,需要判断是否走斜线
if (Math.abs(toX - fromX) != 2 || Math.abs(toY - fromY) != 2) {
return false;
}
int middleX = (fromX + toX) / 2;
int middleY = (fromY + toY) / 2;
if (board[middleX][middleY] != 0) {
return false; // 象或士不能跨越棋子
}
if (chess == 3 && (toX < 0 || toX > 4 || toY < 3 || toY > 5)) {
return false; // 红方象不能过河
}
if (chess == -3 && (toX < 5 || toX > 9 || toY < 3 || toY > 5)) {
return false; // 黑方象不能过河
}
}
if (chess == 6 || chess == -6) {
// 马,需要判断是否走日字
int dx = toX - fromX;
int dy = toY - fromY;
if (Math.abs(dx) == 2 && Math.abs(dy) == 1) {
int middleX = fromX + dx / 2;
int middleY = fromY;
if (board[middleX][middleY] != 0) {
return false; // 马脚被挡住
}
} else if (Math.abs(dx) == 1 && Math.abs(dy) == 2) {
int middleX = fromX;
int middleY = fromY + dy / 2;
if (board[middleX][middleY] != 0) {
return false; // 马脚被挡住
}
} else {
return false; // 马走日字
}
}
if (board[toX][toY] * chess > 0) {
return false; // 不能吃自己的棋子
}
// 能走到这里说明合法,进行移动
board[toX][toY] = chess;
board[fromX][fromY] = 0;
moveStack.push(new Move(fromX, fromY, toX, toY, chess));
return true;
}
// 悔棋
public boolean undo() {
if (moveStack.empty()) {
return false;
}
Move lastMove = moveStack.pop();
board[lastMove.fromX][lastMove.fromY] = lastMove.chess;
board[lastMove.toX][lastMove.toY] = 0;
return true;
}
// 打印棋盘
public void print() {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(getChessName(board[i][j]) + "\t");
}
System.out.println();
}
}
// 将棋子编号转换成字符串
private String getChessName(int chess) {
switch (chess) {
case 0:
return " ";
case 1:
return "车";
case 2:
return "马";
case 3:
return "相";
case 4:
return "士";
case 5:
return "帅";
case 6:
return "炮";
case -1:
return "車";
case -2:
return "馬";
case -3:
return "象";
case -4:
return "士";
case -5:
return "將";
case -6:
return "砲";
default:
return "";
}
}
// 移动信息类
private static class Move {
int fromX, fromY, toX, toY, chess;
public Move(int fromX, int fromY, int toX, int toY, int chess) {
this.fromX = fromX;
this.fromY = fromY;
this.toX = toX;
this.toY = toY;
this.chess = chess;
}
}
}
```
在这个实现中,我们使用了一个二维数组来表示棋盘矩阵,使用一个栈来记录每一步的操作,其中`Move`类表示一次移动的信息。`initialize()`方法用于初始化棋盘,`move()`方法用于走棋,`undo()`方法用于悔棋,`print()`方法用于打印棋盘,`getChessName()`方法用于将棋子编号转换成字符串。实际应用中,我们可能需要对这个代码进行一些修改,以适应不同的需求。
阅读全文