java小游戏-贪吃蛇

java小游戏-贪吃蛇

1、 设计蓝图

  • 首先是设计三个类,分别为Food,She,Game。

  • 有两个对象,分别为蛇和食物;其中蛇有依照键盘按键走不同方向,吃食物的行为;食物有消失和产生的行为。

  • Food类存入食物的坐标 ;She类存入蛇头位置,蛇的长度,蛇头的方向等蛇的基本属性和蛇移动、吃食物的方法;Game产生界面,并且实现键盘监听,判断游戏是否结束,实现蛇的自动移动的功能;

效果:
upload successful

2、源代码:

Food类:

1
2
3
4
 public class Food {
		public int[] foodx= {500,50,125,600,800};
		public int[] foody= {500,75,800,125,800};
}

She类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class She {
	// 线程内部类实现面板重画功能
	
	String direction="R";  //蛇头的方向,R L U D
	int length=1;        //除了蛇头的身体的长度
	int x=400;             //she头的坐标
	int y=400;
	int[] bodyx=new int[100];
	int[] bodyy=new int[100];
	int speed=25;  //蛇的速度,一小格 是 25
   //蛇头的图片
	public String imageUrl="/image/s_mario_stand_R.png";
	
	public void move() {
		//一个蛇身体的块 是由上一个块来决定的
		//蛇头的方向是由键盘方向来控制的
		
		//for循环倒着遍历
		for(int i=length;i>0;i--) {
			if(i==1) {
				//数组 下标头部的下一节为0,然后依次推,靠头的那部分,就是i==1的时候,变为头的坐标
				//否则就,从蛇尾开始,后一节的变为前一节(因为这样不会出现空节的现象)
				bodyx[i-1]=x;
				bodyy[i-1]=y;
			}else {
				bodyx[i-1]=bodyx[i-2];
				bodyy[i-1]=bodyy[i-2];
			}
		}
		
		//要先遍历在判断蛇头向哪走,加多少
		if(direction=="R") {
			x+=speed;
		}else if(direction=="L") {
			x-=speed;
		}else if(direction=="D") {
			y+=speed;
		}else if(direction=="U") {
			y-=speed;
		}
	}
	public void eat() {
		//先加上一节,虽然不知道在那里加
		length++;
		move();
	}
}

Game类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.Timer;

public class Game extends JFrame implements KeyListener{
	 //创建一个蛇和食物的全局对象
	She snake=new She();
	Food food=new Food();
	boolean iseat=false;
	boolean isdie=false;
	int j;   //记录消失的食物的代号,因为要产生的食物覆盖消食的食物的位置
	
	public Game() {
		this.setTitle("贪贪吃蛇");
		Container container =this.getContentPane();
		container.setLayout(new BorderLayout());
		this.setSize(1016,1038);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//添加监听器
		this.addKeyListener(this);
		this.setVisible(true);
		tim.start();	
	}
	//重新游戏
	public void regame() {
		this.dispose();
		new Game();
	}
	//开一个计时器 让蛇自己动
	Timer tim=new Timer(300,new ActionListener() {
		public void actionPerformed(ActionEvent arg0) {
			if(isdie){
				tim.stop();
				return;
			}
			if(snake.direction=="L") {   //如果头朝向左
				for(int i=0;i<5;i++) {
					if((snake.x-25)==food.foodx[i]&&snake.y==food.foody[i]) {
						iseat=true;
						//记录消失的食物的数组下标
						j=i;
					}
				}
				if(iseat) {
					snake.eat();
					snake.move();
					createfood();
					iseat=false;
				}else {
					snake.move();
				}
				repaint();
			}
			if(snake.direction=="U") {   //如果头朝向上
				for(int i=0;i<5;i++) {
					if(snake.x==food.foodx[i]&&(snake.y-25)==food.foody[i]) {
						iseat=true;
						j=i;
					}
				}
				if(iseat) {
					snake.eat();
					snake.move();
					createfood();
					iseat=false;
				}else {
					snake.move();
				}
				repaint();
			}
			if(snake.direction=="R") {   //如果头朝向右
				for(int i=0;i<5;i++) {
					if((snake.x+25)==food.foodx[i]&&snake.y==food.foody[i]) {
						iseat=true;
						j=i;
					}
				}
				if(iseat) {
					snake.eat();
					snake.move();
					createfood();
					iseat=false;
				}else {
					snake.move();
				}
				repaint();
			}
			if(snake.direction=="D") {   //如果头朝向下
					for(int i=0;i<5;i++) {
						if(snake.x==food.foodx[i]&&(snake.y+25)==food.foody[i]) {
							iseat=true;
							j=i;
						}
					}
					if(iseat) {
						snake.eat();
						snake.move();
						createfood();
						iseat=false;
				}else {
					snake.move();
				}
				repaint();
			}
		}
	});

	public void paint(Graphics g) {
//		g.clearRect(0,0,600,600);   这一行可以用下面这句话来代替,重画一下面板,才能继续画
		super.paint(g);      // 这个是paint空方法,用来初始化一下面板
		//判断蛇撞到身子时,这时候最后一个身子上前移的时候,覆盖头,就是和头的坐标一致,所以会直接结束游戏,不判断最后一节的方法是什么
		for(int i=1;i<snake.length;i++) {
			if(snake.x==snake.bodyx[i]&&snake.y==snake.bodyy[i]) {
				isdie=true;
				JOptionPane.showMessageDialog(null, "GameOver");
				regame();
			}
		}
		
		//初始化面板
		g.setColor(Color.WHITE);
		g.fillRect(0, 0, 1000, 1000);    //实心矩形
		g.setColor(Color.BLUE);
		Image headimg=Toolkit.getDefaultToolkit().getImage(
				Panel.class.getResource(snake.imageUrl));
		//画蛇头和蛇身子,蛇头用图片,蛇身子用蓝色实心圆画
		for(int i=0;i<=snake.length;i++) {
			g.drawImage(headimg,snake.x, snake.y,25,25,this);
			g.fillArc(snake.bodyx[i], snake.bodyy[i], 25, 25,0,360);
		}
		//先换一下黄色颜色,画食物
		g.setColor(Color.YELLOW);  
		for(int i=0;i<5;i++) {
			g.fillRect(food.foodx[i], food.foody[i], 25, 25);
		}
	}
	//食物产生的方法
	public void createfood() {
		int x=((int)(Math.random()*40)*25);
		int y=((int)(Math.random()*40)*25);
		food.foodx[j]=x;
		food.foody[j]=y;
	}
	
	//键盘监听
	public void keyPressed(KeyEvent e) {
		if(e.getKeyCode()==KeyEvent.VK_LEFT) {   //左键
			if(snake.direction=="R") {
			//添加if-else这样做的原因是不让蛇头与正在走的方向相反的方向走,否则就会死亡
			}
			else{snake.direction="L";}
		}
		if(e.getKeyCode()==KeyEvent.VK_UP) {    //上键
			if(snake.direction=="D") {
			}
			else{snake.direction="U";}
		}
		if(e.getKeyCode()==39) {                //右键
			if(snake.direction=="L") {
			}
			else{snake.direction="R";}
		}
		if(e.getKeyCode()==40) {                //下键
			if(snake.direction=="U") {
			}
			else{snake.direction="D";}
		}
	}
	public void keyReleased(KeyEvent e) {
	}
	public void keyTyped(KeyEvent e) {
	}
    
	public static void main(String[] args) {
		new Game();
	}
}

3、 总结:
复习了一下关于java窗口设计的知识,懂的了计时器是怎么用的,为键盘添加监听器的方法,Toolkit画图片的方法,关键之处是如何把蛇的运动这个行为抽象成一个move方法,对象的属性抽象成几个变量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值