package com.bao.txz;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
/**
* 推箱子(控制台版)
*
* 2021.11.07
* @author 尘客
* @version v1.0_bao
*/
public class Txz {
private Scanner sc; // 扫描器
private Random rd; // 随机器
private int[][] map; // 地图
private int high = 10; // 地图高
private int width = 10; // 地图宽
private int playerX, playerY; // 玩家坐标
private int boxX, boxY; // 箱子坐标
private int terminusX, terminusY; // 终点坐标
private boolean pd = false; // 判断玩家坐标是否和终点坐标重合
private boolean exit = false; // 是否退出
private List<int[][]> maps; // 地图集合 记录玩家走过的地图
/**
* 无参构造方法
* 默认地图的大小为 10*10
*/
public Txz() {
sc = new Scanner(System.in); // 初始化扫描器
rd = new Random(); // 初始化随机器
map = new int[high][width]; // 初始地图大小
maps = new ArrayList<>(); // 初始地图集合
}
/**
* 有参构造方法 默认地图的大小为 10*10 如果用户设定的地图大小小于 3*3,则使用默认地图大小
*
* @param high 初始地图的高
* @param width 初始地图的宽
*/
public Txz(Integer high, Integer width) {
sc = new Scanner(System.in); // 初始化扫描器
rd = new Random(); // 初始化随机器
// 地图大小最小必须3*3
if (high > 2 && width > 2) {
this.high = high; // 改变地图高为用户设定的值
this.width = width; // 改变地图宽为用户设定的值
}
map = new int[this.high][this.width]; // 初始地图大小
maps = new ArrayList<>(); // 初始地图集合
}
/**
* 推箱子的启动方法
*/
public void startTxz() {
myRandom(); // 初始玩家,终点,箱子的位置
map[playerX][playerY] = 1; // 玩家坐标对应的值
map[boxX][boxY] = 2; // 箱子坐标对应的值
map[terminusX][terminusY] = 3; // 终点坐标对应的值
plan(); // 将初始地图加入地图集合
// 死循环
while (true) {
InitializationMap(); // 初始化地图
try {
GoIntoAction(); // 玩家行动
// ArrayIndexOutOfBoundsException 下标越界异常 表示玩家或者箱子移出了地图范围
} catch (ArrayIndexOutOfBoundsException e) {
System.err.println("提示:您已越界,游戏失败!");
// 退出循环
break;
}
// 如果为true,代表用户输入退出指令
if (exit) {
System.err.println("提示:您已退出游戏!");
// 退出循环
break;
}
//箱子的坐标与终点坐标重合,表示到达终点
if (boxX == terminusX && boxY == terminusY) {
// 恭喜过关
CongratulationsToPass();
// 退出循环
break;
}
}
}
/**
* 恭喜过关
*/
private void CongratulationsToPass() {
// 将过关之后的地图显示
InitializationMap();
myFormatPrintln(32, null, 1, "※※※※※※※※※※※※※※※");
myFormatPrintln(32, null, 1, "※■■■■■■■■■■■■■※※");
myFormatPrintln(32, null, 1, "※■■■■恭喜过关!■■■■※※");
myFormatPrintln(32, null, 1, "※■■■■■■■■■■■■■※※");
myFormatPrintln(32, null, 1, "※※※※※※※※※※※※※※※");
}
/**
* 玩家行动
*/
private void GoIntoAction() {
myFormatPrintln(35, null, 1, "移动指示:上-w 下-s 左-a 右-d 返回上一步-z 退出游戏-e");
myFormatPrint(35, null, 1, "请输入:");
// 用户输入操作
String move = sc.next();
if ("e".equals(move)) {
exit = true;
} else if ("z".equals(move)) {
// 地图集合的大小必须大于1,代表玩家已经走过(1为初始地图)
if (maps.size() > 1) {
// 定义一个二维数组,接收当前地图的上一个地图数据
int[][] newMap = maps.get(maps.size() - 2);
// 将二维数组的数据复制给地图
for (int i = 0; i < high; i++) {
for (int j = 0; j < width; j++) {
map[i][j] = newMap[i][j];
// 将玩家的坐标更改为上一个地图
if (newMap[i][j] == 1) {
playerX = i;
playerY = j;
}
// 将箱子的坐标更改为上一个地图
else if (newMap[i][j] == 2) {
boxX = i;
boxY = j;
}
// 终点坐标是不变的,无需更改
}
}
// 将当前地图从地图集合中移除
maps.remove(maps.size() - 1);
} else {
System.err.println("已退到初始状态,不可再退!");
// 要求用户重新输入操作
GoIntoAction();
}
}
// 判断是否是上,下,左,右指令
else if (!"w".equals(move) && !"s".equals(move) && !"a".equals(move) && !"d".equals(move)) {
System.err.println("指令错误,请重新输入!");
// 要求用户重新输入操作
GoIntoAction();
} else {
// 如果玩家坐标和终点坐标重合
if (map[playerX][playerY] == map[terminusX][terminusY]) {
// 将判断改为true
pd = true;
} else {
// 将判断改为false
pd = false;
}
// 上
if ("w".equals(move)) {
// 如果玩家的x坐标减1,等于箱子的坐标,表示箱子在玩家上方
if (map[playerX - 1][playerY] == map[boxX][boxY]) {
// 箱子x坐标减1
boxX--;
// 表示箱子向上移动一格
map[boxX][boxY] = 2;
}
// 判断玩家,终点坐标是否重合
easy();
// 玩家x坐标减1
playerX--;
// 表示玩家向上移动一格
map[playerX][playerY] = 1;
}
// 下
else if ("s".equals(move)) {
// 如果玩家的x坐标加1,等于箱子的坐标,表示箱子在玩家下方
if (map[playerX + 1][playerY] == map[boxX][boxY]) {
// 箱子x坐标加1
boxX++;
// 表示箱子向下移动一格
map[boxX][boxY] = 2;
}
// 判断玩家,终点坐标是否重合
easy();
// 玩家x坐标加1
playerX++;
// 表示玩家向下移动一格
map[playerX][playerY] = 1;
}
// 左
else if ("a".equals(move)) {
// 如果玩家的y坐标减1,等于箱子的坐标,表示箱子在玩家左方
if (map[playerX][playerY - 1] == map[boxX][boxY]) {
// 箱子y坐标减1
boxY--;
// 表示箱子向左移动一格
map[boxX][boxY] = 2;
}
// 判断玩家,终点坐标是否重合
easy();
// 玩家y坐标减1
playerY--;
// 表示玩家向左移动一格
map[playerX][playerY] = 1;
}
// 右
else if ("d".equals(move)) {
// 如果玩家的y坐标加1,等于箱子的坐标,表示箱子在玩家右方
if (map[playerX][playerY + 1] == map[boxX][boxY]) {
// 箱子y坐标加1
boxY++;
// 表示箱子向右移动一格
map[boxX][boxY] = 2;
}
// 判断玩家,终点坐标是否重合
easy();
// 玩家y坐标减1
playerY++;
// 表示玩家向右移动一格
map[playerX][playerY] = 1;
}
// 将更新的地图加入地图集合
plan();
}
}
/**
* 判断玩家坐标是否和终点坐标重合
*/
private void easy() {
// 如果为true,代表玩家坐标已经和终点坐标重合,玩家移动后,需要将终点重新显示
if (pd) {
map[playerX][playerY] = 3;
} else {
map[playerX][playerY] = 0;
}
}
/**
* 将地图加入地图集合
*/
private void plan() {
// 定义一个二维数组
int[][] newMap = new int[high][width];
// 将当前地图的数据复制给新定义的二维数组
for (int i = 0; i < high; i++) {
for (int j = 0; j < width; j++) {
newMap[i][j] = map[i][j];
}
}
// 将复制的二维数组加入地图集合
maps.add(newMap);
}
/**
* 初始化地图
*/
private void InitializationMap() {
myFormatPrintln(31, null, 1, "***************************************");
// 记录玩家步数,需要减去初始化地图
myFormatPrintln(31, null, 1, "步数:" + (maps.size() - 1));
// 初始化地图
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
if (map[i][j] == 1) {//玩家
myFormatPrint(31, null, 1, "♀ ");
} else if (map[i][j] == 2) {//箱子
myFormatPrint(34, null, 1, "■ ");
} else if (map[i][j] == 3) {//终点
myFormatPrint(33, null, 1, "★ ");
} else {//地图
myFormatPrint(32, null, 1, "□ ");
}
}
System.out.println();
}
}
/**
* 初始化玩家,终点,箱子的位置
*/
private void myRandom() {
//随机玩家,终点,箱子的x
int x = rd.nextInt(high);
playerX = x;
x = rd.nextInt(high);
terminusX = x;
//箱子的x不能是0或最后一个元素
x = rd.nextInt(high - 2) + 1;
boxX = x;
// 存储玩家,终点,箱子y
List<Integer> randoms = new ArrayList<>();
for (int i = 0; i < width; i++) {
randoms.add(i);
}
//随机玩家的y
int i = rd.nextInt(randoms.size());
Integer y = randoms.get(i);
playerY = y;
//如果玩家的x等于终点或箱子的x,则移除已占用的y
if (playerX == terminusX || playerX == boxX) {
randoms.remove(i);
}
//随机终点的y
i = rd.nextInt(randoms.size());
y = randoms.get(i);
terminusY = y;
//如果终点的x等于箱子的x,则移除已占用的y
if (terminusX == boxX) {
randoms.remove(i);
}
//箱子的y不能是0或最后一个元素,需要移除
Integer z = 0;
randoms.remove(z);
z = width - 1;
randoms.remove(z);
//判断y坐标的集合是否为空,不为空才可随机箱子的y
if(randoms.size() > 0){
//随机箱子的y
i = rd.nextInt(randoms.size());
y = randoms.get(i);
boxY = y;
}
else{
myRandom();
}
}
/**
* 格式化输出
*
* @param fontColor 字体颜色
* @param backgroundColor 背景颜色
* @param fontStyle 字体样式
* @param content 输出内容
*/
private void myFormatPrint(Integer fontColor, Integer backgroundColor, Integer fontStyle, String content) {
if (null == backgroundColor && null == fontStyle) {
System.out.format("\33[%d;%s", fontColor, content);
} else if (null == backgroundColor) {
System.out.format("\33[%d;%dm%s", fontColor, fontStyle, content);
} else if (null == fontStyle) {
System.out.format("\33[%d;%d;%s", fontColor, backgroundColor, content);
} else {
System.out.format("\33[%d;%d;%dm%s", fontColor, backgroundColor, fontStyle, content);
}
}
/**
* 格式化输出 换行
*
* @param fontColor 字体颜色
* @param backgroundColor 背景颜色
* @param fontStyle 字体样式
* @param content 输出内容
*/
private void myFormatPrintln(Integer fontColor, Integer backgroundColor, Integer fontStyle, String content) {
if (null == backgroundColor && null == fontStyle) {
System.out.format("\33[%d;%s%n", fontColor, content);
} else if (null == backgroundColor) {
System.out.format("\33[%d;%dm%s%n", fontColor, fontStyle, content);
} else if (null == fontStyle) {
System.out.format("\33[%d;%d;%s%n", fontColor, backgroundColor, content);
} else {
System.out.format("\33[%d;%d;%dm%s%n", fontColor, backgroundColor, fontStyle, content);
}
}
}
推箱子——Java控制台版
最新推荐文章于 2022-06-23 12:19:10 发布