📄 mi.java
字号:
/**
* @(#)迷宫.java
*
* Sample Applet application
*
* @aut ******************************************hor
* @version 1.00 08********************* ******************* /04/26
*/
import javax.swing.JApplet.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.Timer;
import java.util.*;
public class Mi extends JApplet implements KeyListener {
Button 加,减,产生迷宫,提示,演示,停止;
int n=10,width=45,key,peoplex=1,peopley=1,keylist=0,原点i=0,原点j=0,nn=10;
char[][] 标记;
int[][] mark;
Image grass,people,grassUP,grassRight,grassFloor,offScreen;
Image updirection,downdirection,leftdirection,rightdirection;
Graphics drawoffScreen;
Graphics2D page_2d;
Label label;
Panel panel;
int count=0,delay=300;
按钮监听器 监听器;
int purpose=0;
int direction=0,是否提示=0;
Timer timer;
//---------------------------------------------------------------------------
//以下为init()方法
//
//--------------------------------------------------------------------------
public void init() {
grass=getImage(getCodeBase(),"grass.gif");
grassUP=getImage(getCodeBase(),"grassUP.gif");
grassRight=getImage(getCodeBase(),"grassRight.gif");
people=getImage(getCodeBase(),"people.gif");
grassFloor=getImage(getCodeBase(),"grassFloor.gif");
updirection=getImage(getCodeBase(),"updirection.gif");
downdirection=getImage(getCodeBase(),"downdirection.gif");
leftdirection=getImage(getCodeBase(),"leftdirection.gif");
rightdirection=getImage(getCodeBase(),"rightdirection.gif");
label=new Label("关数:"+(nn-9)); //此标签用于显示谜宫的复杂度
加=new Button("增加关数");
减=new Button("降低关数");
产生迷宫=new Button("产生迷宫");
提示=new Button("方向提示");
演示=new Button("自动行走");
停止=new Button("行走停止");
Listen演示 listen演示=new Listen演示();//生成下面的timer演示的监听器
timer=new Timer(delay,listen演示);
加.addKeyListener(this); //各按钮添加键盘事件,当发生键盘事件时就会接收到
产生迷宫.addKeyListener(this);
减.addKeyListener(this);
提示.addKeyListener(this);
演示.addKeyListener(this);
停止.addKeyListener(this);
监听器=new 按钮监听器(); //此为下面各按钮的按钮监听器,因为按钮处于容器的最前面,因此按钮能监听添得到
加.addActionListener(监听器);
减.addActionListener(监听器);
产生迷宫.addActionListener(监听器);
提示.addActionListener(监听器);
演示.addActionListener(监听器);
停止.addActionListener(监听器);
panel=new Panel(); //生成一个面板,主要用于加入加,减,产生迷宫,提示,演示,停止的按钮
panel.setPreferredSize(new Dimension(50,60));
setLayout(new BorderLayout());//设置边界布局方法
add(panel,BorderLayout.EAST); //把面板放置在右边
加.setBackground(Color.yellow); //各按钮加上颜色
减.setBackground(Color.yellow);
产生迷宫.setBackground(Color.yellow);
提示.setBackground(Color.pink);
演示.setBackground(Color.cyan);
停止.setBackground(Color.cyan);
panel.add(label); //分别加入标签与按钮
panel.add(加);
panel.add(减);
panel.add(产生迷宫);
panel.add(new Label());
panel.add(提示);
panel.add(new Label());
panel.add(演示);
panel.add(停止);
offScreen=createImage(1000,1000); //生成一个次画面
drawoffScreen=offScreen.getGraphics();
生成迷宫(); //调用该方法可以自动生成一个初始化的谜宫
}
//-------------------------------------------------------------------------
//这里是paint()方法,用于画图
//
//---------------------------------------------------------------------------
public void paint(Graphics g)
{
drawoffScreen.clearRect(0,0,(100+2)*width,(50+2)*width);
//clearRect方法用于清除次画面里面的内容
drawoffScreen.setColor(Color.white);
drawoffScreen.fillRect(0,0,(100+2)*width,(50+2)*width);
//使次画面变白
画出迷宫(drawoffScreen); //画出迷宫
画出人(drawoffScreen); //画出人所在处
提示方向(drawoffScreen);
调整(drawoffScreen); /*"调整"方法,是用于使镜头始对应着小人,
就算小人出了视野,也可以通过此方法
能看到它的所在处*/
g.drawImage(offScreen,0,0,this);//把次画面"贴上"原主画面上
}
//------------------------------------------------------------------------
//按钮事件监听器
//
//--------------------------------------------------------------------------
private class 按钮监听器 implements ActionListener
{
public void actionPerformed(ActionEvent event){
Object source=event.getSource();//得到按钮的事件源
if(source==加) //当按钮"加"被按时,就令n增一,增加复杂度,然后在标签里显示出
{
if(nn<=40)nn++;
/*nn主要用存储通过按钮或者通过游戏自动升级后的级数,避免在
游戏过程中突然改变级数变量n而出现程序运行错误,通过这种方法只有
当按了"生成迷宫"按钮后才能改变n的值,增加程序的安全性
*/
label.setText("关数:"+(nn-9));
}
if(source==减)
{
if(nn>10)nn--;
label.setText("关数:"+(nn-9));
}
if(source==产生迷宫)
生成迷宫();
if(source==提示)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mark[i][j]=0;
purpose=0; //purpose=0表示还没有找到目标,当purpose=1时,就表示已经找到目标了
direction=1;//direction表示方向,当direction=0时就表示初始化,没有方向
//direction=1,2,3,4分别表示向上,下,左,右
find(peoplex,peopley);//从人物当前的位置做起,进行递归
是否提示=1; //用"是否提示"来控制提示是否显示出来,当为1时,就显示出来,否则就不显示出
repaint();
}
if(source==演示)
timer.start();
if(source==停止)
timer.stop();
}
}
//----------------------------------------------------------------------------
//生成迷宫
//
//--------------------------------------------------------------------------
private void 生成迷宫(){
int Si,Sj,Ei,Ej;
n=nn; /*nn主要用存储通过按钮或者通过游戏自动升级后的级数,避免在
游戏过程中突然改变变量n而出现程序运行错误,通过这种方法只有
当按了"生成迷宫"按钮后才能改变n的值,增加程序的安全性
*/
timer.stop();//主要防止玩家操作错误,保证当生成一个迷宫数组时,机械猫是保持不动的
peoplex=peopley=1;//此为人所在之处的坐标
Si=Sj=1;
Ei=Ej=n;
标记=new char[n+2][n+2]; //标记数组主要是否记录迷宫哪些地方是边界,哪些地方在哪一个方向上有通路
mark=new int[n+2][n+2]; //存在加2的原因是因为画面上包括了边界的原因
for(int i=0;i<=n+1;i++)
for(int j=0;j<=n+1;j++)
{
int mm=n+1;
if(i==0||j==0||i==mm||j==mm)
{//边界处用字母w表示,并且用mark数组标记为1,此后在画出迷宫的方法中将在相对应的坐标点画上边界
标记[i][j]='w';mark[i][j]=1;
}
else
{
标记[i][j]='o';mark[i][j]=0;//如果不是边界的,则用字母o标示,
//此后在画出迷宫的方法中将在相对应的坐标点画上"上墙与右墙"
}
}
标记[Ei][Ej]='r';//此处为坐标(n,n)处,r表示没有右墙,这是合理的,因为它是出口,自然没有右墙
genmaze(Ei,Ej); //递归生成迷宫数组"标记"
标记[Ei+1][Ej]='e';//此处为坐标(n+1,n)处,为出口通道,标记为e,即表示上,右墙都没有
repaint();
}
//--------------------------------------------------------------------------
//此方法为genmaze()方法,产生递归,生成一个迷宫数组
//
//---------------------------------------------------------------------------
private void genmaze(int i,int j){
int k;
mark[i][j]=1;//迷宫数组中已经遍历过的地方用mark[i][j]=1标记
while(mark[i][j+1]==0||mark[i][j-1]==0
||mark[i-1][j]==0||mark[i+1][j]==0)
{//--------------------------------------------------------------
//如果坐标(i,j)处或上,或下,或左,或右尚没有遍历,则执行下列程序
//-----------------------------------------------------------------
k=(int)(4*Math.random()+1); //生成一个1,2,3,4之间的随机数
if(k==1&&mark[i][j-1]==0) //当指示向上走且坐标的上面没有遍历时,则向上走
{
if(标记[i][j]=='o')
{//-----------------------------------------------------------
//当当前位置不能通向上边或者右边时,则标记为u,表示此处可以通向上面,拆掉上墙
//--------------------------------------------------------
标记[i][j]='u';
}
else
{//---------------------------------------------------------
//当当前位置没有右墙(r表示不存在右墙)时,则标记为e,即表示上,右墙都没有
//---------------------------------------------------------
if(标记[i][j]=='r')标记[i][j]='e';
}
genmaze(i,j-1);//往上遍历
}
if(k==2&&mark[i][j+1]==0)//向下走
{
标记[i][j+1]='u'; //因为要往下走,因此要把坐标(i,j+1)处的上墙拆掉
genmaze(i,j+1); //往下遍历
}
if(k==3&&mark[i-1][j]==0)//向左走
{
标记[i-1][j]='r'; //因为要向左走,因此要把坐标(i-1,j)处的右墙拆掉
genmaze(i-1,j); //向左遍历
}
if(k==4&&mark[i+1][j]==0)//向右走
{
if(标记[i][j]=='o')标记[i][j]='r'; //如果上右墙都有,则拆右墙
else
{
if(标记[i][j]=='u')标记[i][j]='e';
//如果没有上墙,则标记e,表示上右墙都没有
}
genmaze(i+1,j);//向右遍历
}
}
}
//-------------------------------------------------------------------------------
//以下为 画出迷宫()方法
//
//-------------------------------------------------------------------------------
public void 画出迷宫(Graphics page)
{
page.clearRect(0,0,(100+2)*width,(50+2)*width);
//---------------------------------------------
//在已经生成迷宫的数组的基础上,画出相对应的迷宫图
//---------------------------------------------------
for(int i=0;i<=n+1;i++)
for(int j=0;j<=n+1;j++)
{
int x=i*width;
int y=j*width;
if(标记[i][j]=='r')
{page.drawImage(grassUP,x,y,width,width,this);//如果是右走,则画上墙
}
if(标记[i][j]=='u')
{page.drawImage(grassRight,x,y,width,width,this);//如果是上走,则画右墙
}
if(标记[i][j]=='o')
{page.drawImage(grassFloor,x,y,width,width,this);//上右墙都有,则画上,右墙
}
if(标记[i][j]=='w')
{page.drawImage(grass,x,y,width,width,this);////如果是外墙,则画上边界墙
}
}
}
//---------------------------------------------------------------------------
//以下为键盘事件的方法
//
//--------------------------------------------------------------------------
public void keyTyped(KeyEvent e){};
public void keyReleased(KeyEvent e){};
public void keyPressed(KeyEvent e)
{
key=e.getKeyCode();//getKeyCode方法得到按键事件源
if(key==KeyEvent.VK_RIGHT)
{
if(向右()) //向右方法是处理右边是否存在通道而设的,存在通道的话就返回true
peoplex++;//人的横坐标向右增一,即peoplex自增1
}
if(key==KeyEvent.VK_LEFT)//向左走
{
if(向左())
peoplex--;
}
if(key==KeyEvent.VK_UP)//向上走
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -