要实现人物移动和推箱子的功能,需要在map类中添加一些方法。
首先是推箱子的功能。可以添加一个moveBox方法来实现:
public void moveBox(int rowOffset, int colOffset) {
// 计算新的行列值
int newRow = x + rowOffset;
int newCol = y + colOffset;
// 判断新位置是否可达
if (box[newRow][newCol] == 0 || box[newRow][newCol] == 3) {
// 更新地图数据
if (box[newRow][newCol] == 3) {
box[newRow][newCol] = 4; // 将终点位置变成目标位置砖块
} else {
box[newRow][newCol] = 2; // 否则将目标位置变成箱子
}
box[x][y] = box[x][y] == 2 ? 0 : 3;
x = newRow;
y= newCol;
// 重绘界面
repaint();
}
}
这个方法也接受两个参数,分别表示行和列的偏移量。如果人物前方是空白格子或者终点位置砖块,则不会发生推箱子的动作;否则,更新地图数据,将目标位置变成箱子或者终点位置砖块,并且重新绘制界面。
然后,在KeyListener监听器中添加相应代码来响应按键事件。例如,如果按下空格键,则向当前方向移动或者推箱子:
case KeyEvent.VK_SPACE:
switch (direction) {
case UP:
moveBox(-1, 0);
break;
case DOWN:
moveBox(1, 0);
break;
case LEFT:
moveBox(0, -1);
break;
case RIGHT:
moveBox(0, 1);
break;
}
break;
其中,direction是一个枚举类型,用于表示当前人物的朝向。可以在map类中定义它:
enum Direction {
UP,
DOWN,
LEFT,
RIGHT
}
Direction direction = Direction.DOWN; // 初始化为向下
同时,在movePlayer方法中更新direction变量的值:
if (colOffset == -1) {
direction = Direction.LEFT;
} else if (colOffset == 1) {
direction = Direction.RIGHT;
} else if (rowOffset == -1) {
direction = Direction.UP;
} else if (rowOffset == 1) {
direction = Direction.DOWN;
}
这样就可以实现推箱子的功能了。
接着是人物移动的功能。可以将movePlayer方法中判断新位置是否可达的代码提取出来,并封装成一个canMove方法:
private boolean canMove(int newRow, int newCol) {
if(newRow<0||newCol<0||newRow>=box.length||newCol>=box[newRow].length){//越界情况
return false;
}
if(box[newRow][newCol]==2){//若果前方有箱子
int nextRow=newRow+rowoffset;//获取箱子下一步的行坐标
int nextCol=newCol+coloffset;//获取箱子下一步的列坐标
if(nextRow<0||nextCol<0||nextRow>=box.length||nextCol>=box[nextRow].length){//越界情况
return false;
}
if(box[nextRow][nextCol]!=1&&box[nextRow][nextCol]!=2&&box[nextRow][nextCol]!=3&&box[nextRow][newCol]!=4){//若果可以将箱子推到目标点上
box[newRow][newCol]=0;//此时该位置就是人走过后变成草地,所以为0
box[nextRow][nextCol]=2;//目标点上就是箱子了,所以为2
x=newRow;//人的行坐标改为新位置的行坐标
y=newCol;//人的列坐标改为新位置的列坐标
repaint();//重新绘制图形界面
return true;
}else{
return false;
}
}else{//如果前方没有箱子
if(box[newRow][newCol]==1) {//如果前方有障碍物不能通过 ,需要返回false
return false;
} else {//如果前方是空地或者目标点
box[x][y] = 0; // 将当前位置变为空地
x = newRow;
y = newCol; // 更新人物位置
box[x][y] = 5; // 标记新位置上有人
repaint(); // 重绘
return true;
}
}
}
这个方法接受新的行列值作为参数,并且返回一个布尔值,表示是否可以移动到新位置。
如果新位置是空白格子、终点位置砖块或者目标位置砖块,则直接返回true;否则,判断新位置是否是箱子,并且计算出下一个位置。如果下一个位置可以推箱子到达,则调用moveBox方法来实现推箱子,并且返回true;否则,返回false。
最后,在KeyListener监听器中添加相应代码来响应按键事件。例如,如果按下方向键,则向当前方向移动:
case KeyEvent.VK_UP:
if (canMove(x - 1, y)) {
movePlayer(-1, 0);
}
break;
case KeyEvent.VK_DOWN:
if (canMove(x + 1, y)) {
movePlayer(1, 0);
}
break;
case KeyEvent.VK_LEFT:
if (canMove(x, y- 1)) {
movePlayer(0, -1);
}
break;
case KeyEvent.VK_RIGHT:
if (canMove(x, y+ 1)) {
movePlayer(0, 1);
}
break;
这样就可以实现人物移动了。




