Skip to content

index.html ​

html
<!DOCTYPE html>
<html lang="cmn-hans">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .container {
            margin: 0 auto;
            position: relative;
        }

        .box {
            position: absolute;
            background-size: 100%;
            /* background-color: red; */
            box-sizing: border-box;
        }

        .box.greenBox {
            /* background-color: blue; */
            background-image: url("imgs/over_box.png");
        }

        .box.yellowBox {
            background-image: url("imgs/box.png");
        }

        .box.end {
            border: 3px green solid;
            /* outline: 3px green solid; */

            z-index: -1;
        }

        .box.player {
            /* background-color: blue; */
            background-image: url("imgs/player.png");
        }

        .box.wall {
            /* background-color: blue; */
            background-image: url("imgs/wall.jpg");
        }
    </style>
</head>

<body>
    <div class="container">
    </div>
    <script src="./js/index.js" type="module"></script>
</body>

</html>

index.js ​

js
// import config from "./Config.js";
import Game from "./Game.js";
new Game();

Game.js ​

js
import config from "./Config.js";
import Common from "./Common.js";
import Wall from "./Wall.js";
import Box from "./Box.js";
import Player from "./Player.js";
class Game {
    constructor() {
        this.boxs = [];
        config.container.style.width = config.mapWidth * config.boxWidth + "px";
        config.container.style.height =
            config.mapHeight * config.boxHeight + "px";

        for (let i = 0; i < config.mapHeight; i++) {
            for (let j = 0; j < config.mapWidth; j++) {
                //创建Wall
                if (config.map[i][j] == -1) {
                    new Wall(i, j);
                }
                //创建end
                if (config.end[i][j]) {
                    const end = new Common(i, j);
                    end.dom.classList.add("end");
                }
                //创建Box
                if (config.base[i][j]) {
                    const base = new Box(i, j);
                    base.dom.classList.add("box");
                    this.boxs.push(base);
                }
            }
        }
        this.player = new Player();
        this.handleClick();
    }
    isVictory() {
        for (let i = 0; i < config.mapHeight; i++) {
            for (let j = 0; j < config.mapWidth; j++) {
                if (config.base[i][j] !== config.end[i][j]) {
                    return false;
                }
            }
        }
        return true;
    }
    handleClick() {
        document.addEventListener("keydown", (e) => {
            let disRow = 0;
            let disCol = 0;
            switch (e.key) {
                case "ArrowRight":
                    disCol = 1;
                    break;
                case "ArrowDown":
                    disRow = 1;
                    break;
                case "ArrowLeft":
                    disCol = -1;
                    break;
                case "ArrowUp":
                    disRow = -1;
                    break;
            }
            //是否推到了箱子
            if (
                config.base[this.player.row + disRow][this.player.col + disCol]
            ) {
                //前面有箱子,移动箱子
                //找到箱子
                const box = this.boxs.find((item) => {
                    return (
                        item.col == this.player.col + disCol &&
                        item.row == this.player.row + disRow
                    );
                });
                //推箱子
                if (!box.move(disRow, disCol)) {
                    return false;
                }
            }
            this.player.move(disRow, disCol);
            // if (this.isVictory()) {
            //     this.player.dom.offsetHeight;
            //     alert("你成功了");
            //     location.reload();
            // }
        });
    }
}
export default Game;

Config.js ​

js
class Config {
	    //配置类
	    constructor(map, base, end, boxWidth, boxHeight) {
	        this.map = map;
	        this.base = base;
	        this.end = end;
	        this.mapHeight = map.length;
	        this.mapWidth = map[0].length;
	        this.boxWidth = boxWidth;
	        this.boxHeight = boxHeight;
	        this.boxNumber = 0;
	        this._endNumber = 0;
	        this.birdRow = 1;
	        this.birdCol = 4;
	        this.container = document.querySelector(".container");
	        for (let i = 0; i < this.mapHeight; i++) {
	            for (let j = 0; j < map[i].length; j++) {
	                if (this.base[i][j] === 1) {
	                    this.boxNumber++;
	                }
	                if (this.end[i][j] === 1) {
	                    this._endNumber++;
	                }
	            }
	        }
	        if (!this.validator() || this.boxNumber !== this._endNumber) {
	            throw new Error("地图信息错误,请检查地图配置");
	        }
	    }
	    validator() {
	        //地图验证器
	        let correct = false;
	        for (let i = 0; i < this.mapHeight; i++) {
	            for (let j = 0; j < this.mapWidth; j++) {
	                if (
	                    this.map[i][j] !== 1 &&
	                    (this.base[i][j] || this.end[i][j])
	                ) {
	                    console.log(1);
	                    return false;
	                }
	                if (this.base[i][j] !== this.end[i][j]) {
	                    correct = true;
	                }
	            }
	        }
	        return correct;
	    }
	}
	const map = [
	    [0, 0, -1, -1, -1, -1, -1, 0, 0],
	    [0, 0, -1, 1, 1, 1, -1, 0, 0],
	    [0, 0, -1, 1, 1, 1, -1, 0, 0],
	    [-1, -1, -1, 1, 1, 1, -1, -1, -1],
	    [-1, 1, 1, 1, 1, 1, 1, 1, -1],
	    [-1, 1, 1, 1, 1, 1, 1, 1, -1],
	    [-1, 1, 1, 1, 1, 1, 1, 1, -1],
	    [-1, -1, 1, 1, 1, 1, 1, -1, -1],
	    [0, -1, 1, 1, 1, 1, 1, -1, 0],
	    [0, -1, 1, 1, 1, 1, 1, -1, 0],
	    [0, -1, 1, 1, 1, 1, 1, -1, 0],
	    [0, -1, -1, -1, -1, -1, -1, -1, 0],
	];
	const base = [
	    [0, 0, 0, 0, 0, 0, 0, 0, 0],
	    [0, 0, 0, 0, 0, 0, 0, 0, 0],
	    [0, 0, 0, 0, 1, 0, 0, 0, 0],
	    [0, 0, 0, 0, 0, 0, 0, 0, 0],
	    [0, 0, 0, 0, 1, 0, 0, 0, 0],
	    [0, 0, 1, 1, 1, 1, 1, 0, 0],
	    [0, 0, 0, 0, 1, 0, 0, 0, 0],
	    [0, 0, 0, 1, 1, 1, 0, 0, 0],
	    [0, 0, 0, 0, 0, 0, 0, 0, 0],
	    [0, 0, 0, 0, 1, 0, 0, 0, 0],
	    [0, 0, 0, 0, 0, 0, 0, 0, 0],
	    [0, 0, 0, 0, 0, 0, 0, 0, 0],
	];
	const end = [
	    [0, 0, 0, 0, 0, 0, 0, 0, 0],
	    [0, 0, 0, 0, 0, 0, 0, 0, 0],
	    [0, 0, 0, 0, 0, 0, 0, 0, 0],
	    [0, 0, 0, 0, 1, 0, 0, 0, 0],
	    [0, 0, 0, 0, 1, 0, 0, 0, 0],
	    [0, 0, 1, 1, 1, 1, 1, 0, 0],
	    [0, 0, 0, 0, 1, 0, 0, 0, 0],
	    [0, 0, 0, 0, 1, 0, 0, 0, 0],
	    [0, 0, 0, 0, 1, 0, 0, 0, 0],
	    [0, 0, 0, 0, 1, 0, 0, 0, 0],
	    [0, 0, 0, 0, 1, 0, 0, 0, 0],
	    [0, 0, 0, 0, 0, 0, 0, 0, 0],
	];
	export default new Config(map, base, end, 30, 30);

Common.js ​

js
import config from "./Config.js";
class Common {
    //盒子公共类
    constructor(row, col) {
        this.width = config.boxWidth;
        this.height = config.boxHeight;
        this.row = row;
        this.col = col;
        if (config.map[row][col] == 0) {
            throw new Error(`box(${this.row},${this.col})位置错误`);
        }
        this.dom = document.createElement("div");
        this.dom.classList.add("box");
        this.dom.style.width = this.width + "px";
        this.dom.style.height = this.height + "px";
        this.render();
        config.container.append(this.dom);
    }
    render() {
        this.dom.style.left = this.getLeft() + "px";
        this.dom.style.top = this.getTop() + "px";
    }
    getLeft() {
        return this.col * this.width;
    }
    getTop() {
        return this.row * this.height;
    }
}

export default Common;

Wall. js ​

js
import Common from "./Common.js";
import config from "./Config.js";
class Wall extends Common {
    constructor(row, col) {
        super(row, col);
        if (config.map[row][col] !== -1) {
            throw new Error(`墙体(${row},${col})位置错误`);
        }
        this.dom.classList.add("wall");
    }
}
export default Wall;

Player.js ​

js
import Common from "./Common.js";
import config from "./Config.js";

class Player extends Common {
    constructor() {
        super(config.birdRow, config.birdCol);
        this.dom.classList.add("player");
    }
    move(row, col) {
        if (row > 1 || row < -1 || col > 1 || col < -1) {
            throw new Error("move方法错误");
        }
        if (
            config.map[this.row + row][this.col + col] !== 1 ||
            config.base[this.row + row][this.col + col] !== 0
        ) {
            return false;
        }
        this.row += row;
        this.col += col;
        this.render();
        return true;
    }
}
export default Player;

Box.js ​

js
import Common from "./Common.js";
import config from "./Config.js";
class Box extends Common {
    constructor(row, col) {
        super(row, col);
        this.isCorrect = false;
        if (config.map[row][col] !== 1) {
            throw new Error(`box(${row},${col})位置错误`);
        }
        if (config.end[this.row][this.col]) this.isCorrect = true;

        this.render();
    }
    move(row, col) {
        if (row > 1 || row < -1 || col > 1 || col < -1) {
            throw new Error("move方法错误");
        }
        if (
            config.map[this.row + row][this.col + col] !== 1 ||
            config.base[this.row + row][this.col + col] !== 0
        ) {
            return false;
        }
        config.base[this.row][this.col] = 0;
        this.row += row;
        this.col += col;
        config.base[this.row][this.col] = 1;
        if (config.end[this.row][this.col]) {
            this.isCorrect = true;
        } else {
            this.isCorrect = false;
        }
        this.render();
        return true;
    }
    render() {
        super.render();
        if (this.isCorrect) {
            this.dom.classList.remove("yellowBox");
            this.dom.classList.add("greenBox");
        } else {
            this.dom.classList.remove("greenBox");
            this.dom.classList.add("yellowBox");
        }
    }
}
export default Box;

以笔记为镜,可以知得失