java登塔小游戏,是男人就上一百层

  学习java很久了,很少完完全全的自己编写一个有难度点的程序。又正好赶上一门课程任务,所以前段时间自己决定用java写一个小游戏,既可以当设计作品又可以练习巩固所学。

这个游戏具体规则如下:

1. 在窗体中央有一座塔,塔的左边或右边会有梯子,但左右不能同时有梯子。

  2. 小球初始在最下面的梯子上,按下左键或右键小球向上跳跃。

  3. 小球向上跳跃一次,则所有梯子下降一个单位,上方将出现一个方向随机的梯子。

  4. 若小球的上方梯子在塔的左方就应该按下左键,若小球的上方梯子在塔的右方就应该按下右键。

  5. 若按错方向键,则游戏结束。

  6. 小球走过的梯子经过短时间就会断裂消失。

  7. 若小球所站的梯子断裂,则游戏结束。

  8. 小球走过一个梯子,分数加1。

下面贴上游戏的主流程图(主要是课程要求):


游戏开始后的流程图:



好了,下面给上代码:

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.*;
public class Climb extends JFrame implements  KeyListener, ActionListener{
	private draw d;
	private Timer timer;
	private char key;
	private int score,bestscore;
	private JLabel lscore,lbestscore;
	public Climb()
	{
		super("登塔:是男人就上100层!");
		this.setBounds(300, 200, 600, 550);
		this.setLayout(null);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		JPanel right=new JPanel();
		right.setLayout(null);
		right.setBackground(Color.gray);
		right.setBounds(400, 0, 200, 550);
		this.lscore=new JLabel("当前得分:");
		this.lbestscore=new JLabel("最高得分:"); 
		lscore.setBounds(0, 100, 100, 50);
		lbestscore.setBounds(0, 200, 100, 50);
		right.add(lscore);
		right.add(lbestscore);
		this.add(right);                           //加入右边的面板,容纳记录分数的标签和开始按钮
		JPanel left=new JPanel();
		left.setBackground(Color.lightGray);
		left.setBounds(0, 0, 400, 550);
		this.addKeyListener(this);
		this.setFocusable(true);
		this.d=new draw(Color.darkGray);
		left.add(this.d);
		this.add(left);                           //加入左边面板,这块面板里加入了一块画布,画布上绘制梯子和球
		this.setVisible(true);
		timer=new Timer(400, this);           //新建一个定时器,每过一定时间触发事件调用actionPeformed 
	}
	public void keyPressed(KeyEvent e) {
		
	}
    public void keyReleased(KeyEvent e) {
    	if(e.getKeyCode()==KeyEvent.VK_SPACE)
    	{
    		
    	}
    	 if(e.getKeyCode()==KeyEvent.VK_LEFT)
    	 {
    		 timer.restart();            //及时按下键,则计时器重新开始
    		 this.key=0;
    		 this.score++;
    		 d.move(this.key);            //根据按下的键决定小球位置
        	 this.printscore(Integer.toString(score));
        	 this.printbestscore(Integer.toString(bestscore));
    	 }
    	 if(e.getKeyCode()==KeyEvent.VK_RIGHT)
    	 {
    		 timer.restart();                //及时按下键,则计时器重新开始
    		 this.key=1;
    		 this.score++;
    		 d.move(this.key);            //根据按下的键决定小球位置
        	 this.printscore(Integer.toString(score));
        	 this.printbestscore(Integer.toString(bestscore));
    	 }
    	 if(key!=d.LorR[3])                        //按键错误则游戏结束
    	 {
    		 this.over();
    	 }
    } 
    public void keyTyped(KeyEvent e) {
    	
	}
    public void actionPerformed(ActionEvent ev) {         //若一定时间没按键,则触发事件,调用此函数,将会调用over()函数结束本次游戏
    	timer.stop();
    	this.d.broken=1;
    	this.d.repaint();
    	this.over();
    }

    public void printscore(String s)
    {
    	this.lscore.setText("当前得分:"+s);
    }                                        //输出当前得分
    public void printbestscore(String s)
    {
    	this.lbestscore.setText("最高得分:"+s);
    }                                         //输出最高得分
    public void init()
    {
    	timer.stop();
    	for(int i=0;i<5;i++)
		{
			this.d.LorR[i]=(int)(2*Math.random());
		}                                    //为5个初始梯子随机生成代表左右的参数
    	this.d.lr=this.d.LorR[3];
    	this.d.repaint();
    }
    public void over()                   //游戏结束后调用进行清场并初始化下一次游戏
    {
    	JOptionPane.showMessageDialog(this,"Game Over");
		 if(this.score>this.bestscore)
		 {
			 bestscore=score;
		 }
		 this.score=0;              //更新最大分数,同时将本次分数清零
		 this.init();
    }
	public static void main(String[] args) {
		Climb m=new Climb();
		m.init();
	}

}

class draw extends Canvas
{
	private Color color;
	protected int lr=0,broken=1;
	protected int LorR[]=new int[5];  //表示第i个梯子实在左边还是右边。0左 1右
	public draw(Color color)
	{
		this.color=color;
		this.setBounds(0, 0, 400, 550);
		
	}
	public void paint(Graphics g)
	{
		g.setColor(this.color);
		g.fillRect(150, 0, 100, 550);         //在画布里画出矩形,同时填充这个矩形,充当塔身
		for(int i=0;i<5;i++)
		{
			if((this.LorR[i]==0&&i!=3&&i!=4)||(this.LorR[i]==0&&this.broken==0))
			{				
				g.fillRect(50, 80*(i+1)+i*20, 100, 20); 
			}
			if((this.LorR[i]==1&&i!=3&&i!=4)||(this.LorR[i]==1&&this.broken==0))
			{
				g.fillRect(250, 80*(i+1)+i*20, 100, 20); 
			}
		}  //for循环根据参数画出5个梯子 
		if(lr==0) {
			g.fillOval(75, 330, 50, 50);
			}
		if(lr==1)
		{
			g.fillOval(275, 330, 50, 50);
		}                                   //根据按下左键还是右键,画出小球位置
		if(broken==1)                    //如果断裂标志为1
		{
			if(this.LorR[3]==0)
			{				
				g.fillRect(50, 380, 40, 20);
				g.fillRect(110, 380, 40, 20); 
			}
			if(this.LorR[3]==1)
			{
				g.fillRect(250, 380, 40, 20);
				g.fillRect(310, 380, 40, 20);
			}
			if(this.LorR[4]==0)
			{				
				g.fillRect(50, 480, 40, 20);
				g.fillRect(110, 480, 40, 20); 
			}
			if(this.LorR[4]==1)
			{
				g.fillRect(250, 480, 40, 20);
				g.fillRect(310, 480, 40, 20);
			}
			this.broken=0;
		}                               //在梯子的位置画两个小梯子,看起来像断裂的效果
		
	}
	public void move(int s)
	{
		for(int i=4;i>0;i--)
		{
			this.LorR[i]=this.LorR[i-1];
		}
		this.LorR[0]=(int)(2*Math.random()); 
		this.lr=s;
		this.repaint();
	}
	//梯子刷新函数,将下面的梯子左右参数改为它上面梯子的左右参数。依次类推,最上面的梯子还是随机生成方向。这样梯子看起来想在向下运动。
}

运行后是这样子的:


由于自己编程经验欠缺,设计思路有些混乱,代码结构可能也不完美。但是还是实现了功能。这次完全的自身实战(每用过别人一行代码)完成后,发现有些事自己亲自动手了还是没有想象中难(信心小增强)。特地在此记录一下。

记录一下遇到的主要困难吧:

  1. 开始窗口总是接受不到键盘事件。
  原因:窗口失去了焦点,这需要设置窗口成焦点。
  2. 开始在画布上画图但运行后每效果。

  解决:在继承了画布的类的构造函数加了设置大小的代码就ok了,而且这个大小设置的和左边面板一样,这样画布就是完全覆盖了面板。

当然,游戏还是有很多的不足,最大的问题就是画面太low,要是有兴趣给这个游戏贴图(背景、塔身、梯子、人)的朋友贴好了还请发我一份。贴好图后可玩性还是可以的,移植到手机端可玩性更高。

最后说一下:这是我自己一个人写的程序,源码也都给出了,转载的还请注明。




猜你喜欢

转载自blog.csdn.net/xlantian/article/details/80643235