用JS写了一个“广度优先搜索法”自动推箱子,理论上无论多少箱子都可以求解,但事实上箱子多了以后,就。。。;
有需要的拿出发挥,修改,高手就可以跳过了。。。
代码随后给出,先看运行效果:
第一关:[url]http://www.108js.com/article/article5/zip/50059/Test-1.html[/url]
第四关:[url]http://www.108js.com/article/article5/zip/50059/Test-4.html[/url]
第五关:[url]http://www.108js.com/article/article5/zip/50059/Test-5.html[/url]
欢迎访问博主的网站:[url]http://www.108js.com[/url]
效果图:
[img]http://dl2.iteye.com/upload/attachment/0098/0315/b01bd691-0a6c-32f6-aa43-3d6638ea4b38.gif[/img]
上图是最初状态:S代表推箱子的人,#表示墙,有五个箱子B要推到目标点T,其中有一个箱子已经到了目标点,用Y表示。
下图是程序最后给出的解答:
R,D,L,U 表示箱子向某个方向移动
r,d,l,u 表示人向某个方向移动
代码分两部分:
[color=blue][b]第一部分:Storehouse.js[/b][/color]
/*仓库类,表示推箱子过程中的一种状态*/
(function(){
function Storehouse(playerPos,map,parent,path,step){
this.playerPos=playerPos;//人的位置
this.map=map;//地图
this.parent=parent;//父状态
this.path=path;//从最初状态来到此状态的路径
this.step=step; //来到此状态的步数
}
//获取人的位置
Storehouse.prototype.getPlayerPos=function() {
return this.playerPos;
}
//获取地图
Storehouse.prototype.getMap=function() {
return this.map;
}
//获取路径
Storehouse.prototype.getPath=function() {
return this.path;
}
//获取步数
Storehouse.prototype.getStep=function() {
return this.step;
}
Storehouse.prototype.getBoxList=function() {//获取此状态中的所有箱子
var boxlist=[];
for(var i=0;i<this.map.length;i++){
for(var j=0;j<this.map[i].length;j++){
if (this.map[i][j] == 'B'||this.map[i][j]=="Y")//箱子在目标上
boxlist.push({x:i,y:j});//箱子坐标
}
}
return boxlist.sort(order);
}
//位置是否越界[url]http://www.108js.com[/url]
Storehouse.prototype.isOk=function(pos){
if(pos.x<0||pos.x>=map.length) return false;
if(pos.y<0||pos.y>=map[0].length) return false;
return true;
}
Storehouse.prototype.getEndList=function() {//获取此状态中的所有目标点
var endlist=[];
for(var i=0;i<this.map.length;i++){
for(var j=0;j<this.map[i].length;j++){
if (this.map[i][j] == "T"||this.map[i][j]=="Y"||this.map[i][j]=="Z")//箱子在目标上,人在目标点
endlist.push({x:i,y:j});//目标坐标
}
}
return endlist.sort(order);
//return endlist;
}
//剪枝函数,玩家的阻碍点,箱子的死点,用递归进行分析[url]http://www.108js.com[/url]
Storehouse.prototype.isBlock=function(array,row,col) {
var b=false;
if ((this.map[row][col] == '.') || (this.map[row][col]=="T")||this.map[row][col]=="S"){
b=false;
}else if ((this.map[row][col] == '#') || contains(array,{x:row,y:col})!=-1) {
b = true;
array.push({x:row,y:col});
} else if (this.map[row][col]=="B") {
array.push({x:row,y:col});
b = (((this.isBlock(array, row + 1, col) || this.isBlock(array, row - 1, col))
&& (this.isBlock(array, row, col + 1) || this.isBlock(array, row, col - 1))));
if (!b) {
var index=contains(array,{x:row,y:col});
array.splice(index,1);
}
}
return b;
}
Storehouse.prototype.toString=function(){
var s="";
for(var i=0,lenx=this.map.length;i<lenx;i++){
s=s+this.map[i].join(" ")+"<br>";
}
return s;
}
Storehouse.prototype.isWin=function() {//是否赢了,比较此状态中的所有箱子和目标点
var boxl=this.getBoxList();
var endl=this.getEndList();
for (var i = 0; i < boxl.length; i++) {
if ((boxl[i].x !=endl[i].x)||(boxl[i].y!=endl[i].y))
return false;
}
return true;
}
//比较两个状态是否相等
Storehouse.prototype.equals=function(other){
if((this.playerPos.x!=other.playerPos.x)||(this.playerPos.y!=other.playerPos.y))
return false;
for(var i=0;i<this.map.length;i++){
for(var j=0;j<this.map[i].length;j++){
if (this.map[i][j] !=other.map[i][j])
return false;
}
}
return true;
}
//判断数组是否包含某一点
function contains(arr,p){
for(var i=0,len=arr.length;i<len;i++){
if(arr[i].x==p.x&&arr[i].y==p.y)
return i;
}
return -1;
}
//箱子排序函数
function order(s1,s2){
if (s1.x > s2.x){
return 1;
}
else if (s1.x == s2.x) { //在同一行,比较列
if (s1.y>s2.y) {
return 1;
}else if(s1.y==s2.y){
return 0;
}else
return -1;
}else
return -1;
}
window.Storehouse=Storehouse;
})()
请继续阅下文:javaScript 广度优先搜索法"自动推箱子"(二)[url]http://128kj.iteye.com/blog/2078631[/url]
有需要的拿出发挥,修改,高手就可以跳过了。。。
代码随后给出,先看运行效果:
第一关:[url]http://www.108js.com/article/article5/zip/50059/Test-1.html[/url]
第四关:[url]http://www.108js.com/article/article5/zip/50059/Test-4.html[/url]
第五关:[url]http://www.108js.com/article/article5/zip/50059/Test-5.html[/url]
欢迎访问博主的网站:[url]http://www.108js.com[/url]
效果图:
[img]http://dl2.iteye.com/upload/attachment/0098/0315/b01bd691-0a6c-32f6-aa43-3d6638ea4b38.gif[/img]
上图是最初状态:S代表推箱子的人,#表示墙,有五个箱子B要推到目标点T,其中有一个箱子已经到了目标点,用Y表示。
下图是程序最后给出的解答:
R,D,L,U 表示箱子向某个方向移动
r,d,l,u 表示人向某个方向移动
代码分两部分:
[color=blue][b]第一部分:Storehouse.js[/b][/color]
/*仓库类,表示推箱子过程中的一种状态*/
(function(){
function Storehouse(playerPos,map,parent,path,step){
this.playerPos=playerPos;//人的位置
this.map=map;//地图
this.parent=parent;//父状态
this.path=path;//从最初状态来到此状态的路径
this.step=step; //来到此状态的步数
}
//获取人的位置
Storehouse.prototype.getPlayerPos=function() {
return this.playerPos;
}
//获取地图
Storehouse.prototype.getMap=function() {
return this.map;
}
//获取路径
Storehouse.prototype.getPath=function() {
return this.path;
}
//获取步数
Storehouse.prototype.getStep=function() {
return this.step;
}
Storehouse.prototype.getBoxList=function() {//获取此状态中的所有箱子
var boxlist=[];
for(var i=0;i<this.map.length;i++){
for(var j=0;j<this.map[i].length;j++){
if (this.map[i][j] == 'B'||this.map[i][j]=="Y")//箱子在目标上
boxlist.push({x:i,y:j});//箱子坐标
}
}
return boxlist.sort(order);
}
//位置是否越界[url]http://www.108js.com[/url]
Storehouse.prototype.isOk=function(pos){
if(pos.x<0||pos.x>=map.length) return false;
if(pos.y<0||pos.y>=map[0].length) return false;
return true;
}
Storehouse.prototype.getEndList=function() {//获取此状态中的所有目标点
var endlist=[];
for(var i=0;i<this.map.length;i++){
for(var j=0;j<this.map[i].length;j++){
if (this.map[i][j] == "T"||this.map[i][j]=="Y"||this.map[i][j]=="Z")//箱子在目标上,人在目标点
endlist.push({x:i,y:j});//目标坐标
}
}
return endlist.sort(order);
//return endlist;
}
//剪枝函数,玩家的阻碍点,箱子的死点,用递归进行分析[url]http://www.108js.com[/url]
Storehouse.prototype.isBlock=function(array,row,col) {
var b=false;
if ((this.map[row][col] == '.') || (this.map[row][col]=="T")||this.map[row][col]=="S"){
b=false;
}else if ((this.map[row][col] == '#') || contains(array,{x:row,y:col})!=-1) {
b = true;
array.push({x:row,y:col});
} else if (this.map[row][col]=="B") {
array.push({x:row,y:col});
b = (((this.isBlock(array, row + 1, col) || this.isBlock(array, row - 1, col))
&& (this.isBlock(array, row, col + 1) || this.isBlock(array, row, col - 1))));
if (!b) {
var index=contains(array,{x:row,y:col});
array.splice(index,1);
}
}
return b;
}
Storehouse.prototype.toString=function(){
var s="";
for(var i=0,lenx=this.map.length;i<lenx;i++){
s=s+this.map[i].join(" ")+"<br>";
}
return s;
}
Storehouse.prototype.isWin=function() {//是否赢了,比较此状态中的所有箱子和目标点
var boxl=this.getBoxList();
var endl=this.getEndList();
for (var i = 0; i < boxl.length; i++) {
if ((boxl[i].x !=endl[i].x)||(boxl[i].y!=endl[i].y))
return false;
}
return true;
}
//比较两个状态是否相等
Storehouse.prototype.equals=function(other){
if((this.playerPos.x!=other.playerPos.x)||(this.playerPos.y!=other.playerPos.y))
return false;
for(var i=0;i<this.map.length;i++){
for(var j=0;j<this.map[i].length;j++){
if (this.map[i][j] !=other.map[i][j])
return false;
}
}
return true;
}
//判断数组是否包含某一点
function contains(arr,p){
for(var i=0,len=arr.length;i<len;i++){
if(arr[i].x==p.x&&arr[i].y==p.y)
return i;
}
return -1;
}
//箱子排序函数
function order(s1,s2){
if (s1.x > s2.x){
return 1;
}
else if (s1.x == s2.x) { //在同一行,比较列
if (s1.y>s2.y) {
return 1;
}else if(s1.y==s2.y){
return 0;
}else
return -1;
}else
return -1;
}
window.Storehouse=Storehouse;
})()
请继续阅下文:javaScript 广度优先搜索法"自动推箱子"(二)[url]http://128kj.iteye.com/blog/2078631[/url]