用java实现推箱子sokoban游戏.docx
《用java实现推箱子sokoban游戏.docx》由会员分享,可在线阅读,更多相关《用java实现推箱子sokoban游戏.docx(21页珍藏版)》请在冰豆网上搜索。
用java实现推箱子sokoban游戏
推箱子游戏
一、功能描述:
Ø可以通过面板上的按钮或是键盘上的pageup,pagedown键选择上下关
Ø可以通过面板上按钮或是键盘上的Backspace键后退,一直后退自己想要的位置,知道游戏开始时的位置。
Ø可以通过面板上的按钮或是键盘上的字母r重新开始当前关卡游戏。
Ø可以在复选框选择想要玩的关卡。
二、界面及运行截图
三、源代码(三部分)
1、地图类
packagebox;
importjava.io.BufferedReader;
importjava.io.File;
importjava.io.FileNotFoundException;
importjava.io.FileReader;//读取字符文件类FileReader
importjava.io.IOException;
publicclassmap{
int[][]map=newint[20][20];
intmanX,manY;
publicmap(intlevel){
Stringfilepath="mapc/"+level+".txt";
Filefile=newFile(filepath);
FileReaderfr=null;//利用FileReader流来读取一个文件中的数据
BufferedReaderbr=null;//字符读到缓存里
try{
fr=newFileReader(file);
br=newBufferedReader(fr);
for(inti=0;i<15;i++){
Stringline=br.readLine();//以行为单位,一次读一行利用BufferedReader的readLine,读取分行文本
byte[]point=line.getBytes();//将字符串转换为字节数组
for(intj=0;j<15;j++){
map[i][j]=point[j]-48;//根据ASCall码表要减掉30H(十进制的48)
if(map[i][j]==5||map[i][j]==6||map[i][j]==7||map[i][j]==8){
manX=i;
manY=j;
}
}
}
}
catch(FileNotFoundExceptione){
e.printStackTrace();//深层次的输出异常调用的流程
}
catch(IOExceptione){
e.printStackTrace();//深层次的输出异常调用的流程
}
catch(NullPointerExceptione){
e.printStackTrace();//深层次的输出异常调用的流程
}
finally{
if(br==null){
try{
br.close();
}
catch(IOExceptione){
e.printStackTrace();
}
br=null;
}
if(fr==null){
try{
fr.close();
}catch(IOExceptione){
e.printStackTrace();
}
fr=null;
}
}
}
publicint[][]getMap(){
returnmap;
}
publicintgetManX(){
returnmanX;
}
publicintgetManY(){
returnmanY;
}
}
2、游戏运行类
packagebox;
importjava.awt.*;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
importjava.awt.event.ItemEvent;
importjava.awt.event.ItemListener;
importjava.awt.event.KeyEvent;
importjava.awt.event.KeyListener;
importjava.util.*;
importjavax.swing.*;
publicclasspushboxextendsJFrameimplementsKeyListener,ActionListener{
mapmap_level=newmap
(1);//首次获取地图
int[][]map=newint[15][15];//地图上每个位置所对应的图片
int[][]map_restart=newint[15][15];//备用图片
staticintmanX,manY;//人所处的位置
staticintlevel=1;//所处关卡
staticintstep=0;
Image[]picture;//地图上的所有图片
ImageIcon[]image=newImageIcon[10];
Stackback_stack=newStack();//存储所前行的路径
JButtonnext,previous,back,restart,exit;//按钮:
下一关,上一关,重新开始,退出
Stringcurrent_level="第"+level+"关";//当前所处关卡(右上角显示文本)
String[]level_button=newString[13];//复选框的容
JComboBoxselectBox;//选关复选框
finalintUp=0;
finalintDown=1;
finalintLeft=2;
finalintRight=3;
int[]dir_x={-1,1,0,0};
int[]dir_y={0,0,-1,1};
publicpushbox(){
super("推箱子");
getmap(map);
previous=newJButton("上一关");
next=newJButton("下一关");
restart=newJButton("重新开始");
back=newJButton("后退");
exit=newJButton("退出游戏");
for(inti=0;i<13;i++)
level_button[i]="第"+Integer.toString(i+1)+"关";
selectBox=newJComboBox(level_button);
FlowLayoutlayout=newFlowLayout();//布局模式
Containerc=getContentPane();
c.setLayout(layout);
layout.setAlignment(FlowLayout.CENTER);//控件在布局中的位置
c.setBackground(Color.CYAN);//背景色
c.add(previous);
c.add(next);
c.add(back);
c.add(restart);
c.add(selectBox);
c.add(exit);
previous.addActionListener((ActionListener)this);
previous.addKeyListener(this);
next.addActionListener((ActionListener)this);
next.addKeyListener(this);
back.addActionListener(this);
back.addKeyListener(this);
restart.addActionListener((ActionListener)this);
restart.addKeyListener(this);
exit.addActionListener((ActionListener)this);
exit.addKeyListener(this);
selectBox.addItemListener(//监听复选框点击事件
newItemListener(){
publicvoiditemStateChanged(ItemEvente){
if(e.getStateChange()==e.SELECTED){
step=0;
back_stack.clear();//每次重新选关后都要清空路径栈
level=selectBox.getSelectedIndex()+1;//获取所选的关卡
map_level=newmap(level);//重新获取对应关卡的地图
getmap(map);
current_level="第"+level+"关";//右上角提示所处关卡文本的更新
repaint();//重画地图
requestFocus();//重新获取焦点(因为按钮事件后键盘事件不起作用)
}
}
}
);
for(intk=0;k<10;k++){
image[k]=newImageIcon("picture/"+k+".png");//获取图片
}
picture=newImage[]{
image[0].getImage(),
image[1].getImage(),
image[2].getImage(),
image[3].getImage(),
image[4].getImage(),
image[5].getImage(),
image[6].getImage(),
image[7].getImage(),
image[8].getImage(),
image[9].getImage()
};
this.setFocusable(true);
this.addKeyListener((KeyListener)this);
setSize(640,640);
setVisible(true);
}
//判断是否通关(方法是,检查地图中是否还有箱子编号4)
publicBooleanpass(){
intp=0;
for(inti=0;i<15;i++)
for(intj=0;j<15;j++){
if(map[i][j]==4)p++;
}
if(p==0)returntrue;
elsereturnfalse;
}
//获取地图上每个位置所对应的图片编号
publicvoidgetmap(int[][]map){
for(inti=0;i<15;i++)
for(intj=0;j<15;j++)
map[i][j]=map_level.map[i][j];
manX=map_level.manX;
manY=map_level.manY;
}
publicvoidpaint(Graphicsg){
super.paint(g);
//提示信息
back_stack.push(Down+5);//这里是一个细节,先将“DOWN”存入栈
g.drawString(current_level,500,90);
g.drawString("第"+step+"步",400,90);
g.drawString("用键盘上的R重新开始,Q退出游戏",200,565);
g.drawString("用键盘pageup,pagedown切换关卡",200,580);
g.drawString("用键盘上的上下左右键控制人的移动",200,600);
g.drawString("用键盘上的Backspace键后退",200,620);
//在面板上画地图
for(inti=0;i<15;i++)
for(intj=0;j<15;j++)
g.drawImage(picture[map[i][j]],100+30*j,100+30*i,this);
}
publicvoidStep(Graphicsg){
g.setColor(Color.cyan);
g.drawString("第"+step+"步",400,90);
step++;
g.setColor(Color.BLACK);
g.drawString("第"+step+"步",400,90);
}
publicvoidmove(intdir,Graphicsg){
intman=dir+5;
intdx=dir_x[dir];
intdy=dir_y[dir];
intx=manX;
inty=manY;
manX+=dx;
manY+=dy;
intorigin_picture=map[manX][manY];
intnext_picture=map[manX+dx][manY+dy];
if((map[manX][manY]==4||map[manX][manY]==3)&&(map[manX+dx][manY+dy]==2||map[manX+dx][manY+dy]==4||map[manX+dx][manY+dy]==3))//上面是箱子,箱子上面是墙或箱子
{
manX-=dx;
manY-=dy;
return;
}
if(map[manX][manY]==2)//上面是墙
{
manX-=dx;
manY-=dy;
return;
}
if(map[manX][manY]==1||map[manX][manY]==9){//人上面是草地或是目的地
g.drawImage(picture[man],100+30*manY,manX*30+100,this);//人的朝向变化
if(map[x][y]==9)//原来位置是目的地
g.drawImage(picture[9],100+30*y,100+30*x,this);
else{//原来位置是草地
g.drawImage(picture[1],100+30*y,x*30+100,this);
map[x][y]=1;
}
Step(g);
}
if((map[manX][manY]==4||map[manX][manY]==3)&&map[manX+dx][manY+dy]==1){//上面是箱子,箱子上面是草地
g.drawImage(picture[man],100+30*manY,manX*30+100,this);//人的朝向变化
if(map[manX][manY]==3)//若是移动一大目的地的箱子,原箱子位置值为9
map[manX][manY]=9;
if(map[x][y]==9)//原来位置是目的地
g.drawImage(picture[9],100+30*y,100+30*x,this);
else{//原来位置是草地
g.drawImage(picture[1],100+30*y,x*30+100,this);
map[x][y]=1;
}
g.drawImage(picture[4],100+30*(manY+dy),(manX+dx)*30+100,this);//草地位置变箱子
map[manX+dx][manY+dy]=4;
Step(g);
}
if((map[manX][manY]==4||map[manX][manY]==3)&&map[manX+dx][manY+dy]==9){//上面是箱子,箱子上面是目的地
g.drawImage(picture[man],100+30*manY,manX*30+100,this);//人的朝向变化
if(map[manX][manY]==3)//若是移动一大目的地的箱子,原箱子位置值为9
map[manX][manY]=9;
elsemap[manX][manY]=0;
if(map[x][y]==9)//原来位置是目的地
g.drawImage(picture[9],100+30*y,100+30*x,this);
else{//原来位置是草地
g.drawImage(picture[1],100+30*y,x*30+100,this);
map[x][y]=1;
}
g.drawImage(picture[3],100+30*(manY+dy),(manX+dx)*30+100,this);//目的地位置变箱子
map[manX+dx][manY+dy]=3;
Step(g);
}
back_stack.push(next_picture);
back_stack.push(origin_picture);
back_stack.push(manY);
back_stack.push(manX);
back_stack.push(man);
if(pass())
JOptionPane.showMessageDialog(null,"恭喜你过关了!
");
}
//键盘事件
publicvoidkeyPressed(KeyEvente){
Graphicsg=getGraphics();
intdir;
switch(e.getKeyCode()){
caseKeyEvent.VK_UP:
dir=Up;
move(dir,g);
break;
caseKeyEvent.VK_DOWN:
dir=Down;
move(dir,g);
break;
caseKeyEvent.VK_LEFT:
dir=Left;
move(dir,g);
break;
caseKeyEvent.VK_RIGHT:
dir=Right;
move(dir,g);
break;
caseKeyEvent.VK_BACK_SPACE:
back.doClick();
break;
caseKeyEvent.VK_PAGE_DOWN:
next.doClick();
break;
caseKeyEvent.VK_PAGE_UP:
previous.doClick();
break;
caseKeyEvent.VK_R:
restart.doClick();
break;
caseKeyEvent.VK_Q:
exit.doClick();
break;
}
}
publicvoidkeyReleased(KeyEvente){}
publicvoidkeyTyped(KeyEvente){}
//悔步后退
publicvoidstep_back(Graphicsg){
g.setColor(Color.cyan);
g.drawString("第"+step+"步",400,90);
step--;
g.setColor(Color.BLACK);
g.drawString("第"+step+"步",400,90);
}
publicvoidBack(){
if(back_stack.size()==2)
return;
intdir=back_stack.pop()-5;//获取上一步的方向
ints=back_stack.pop();
intt=back_stack.pop();
intorigin_picture=back_stack.pop();
intnetx_picture=back_stack.pop();
intpre_dir=back_stack.lastElement();
Graphicsg=getGraphics();
intdx=dir_x[dir];
intdy=dir_y[dir];
g.drawImage(picture[origin_picture],100+30*t,100+30*s,this);
g.drawImage(picture[netx_picture],100+30*(t+dy),100+30*(s+dx),this);
g.drawImage(picture[pre_dir],100+30*(t-dy),100+30*(s-dx),this);
manX=s-dx;
manY=t-dy;
map[s][t]=origin_picture;
map[s+dx][t+dy]=netx_picture;