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;