实验内容:
1)实现贪吃蛇游戏基本功能,屏幕上随机出现一个“食物”,称为豆子。玩家能利用上下左右键控制“蛇”的移动,“蛇”吃到“豆子”后“蛇”身体加长一节,得分增加,“蛇”碰到边界或蛇头与蛇身相撞,“蛇”死亡,游戏结束。
2)进行交互界面的设计,要有开始键、暂停键和停止退出的选项,能够控制游戏进程。对蛇吃到豆子进行分值计算,可以设置游戏速度,游戏音乐等拓展元素。
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class Mpanel extends JPanel implements KeyListener,ActionListener{
ImageIcon title = new ImageIcon("title.jpg");
ImageIcon body = new ImageIcon("body.png");
ImageIcon up = new ImageIcon("up.png");
ImageIcon down = new ImageIcon("down.png");
ImageIcon left = new ImageIcon("left.png");
ImageIcon right = new ImageIcon("right.png");
ImageIcon food = new ImageIcon("food.png");
int len = 3;
int score=0;
int[] snakex = new int[750];
int[] snakey = new int[750];
String fx = "r";
boolean isStarted=false;
boolean isFailed=false;
Timer timer=new Timer(300, (ActionListener) this);
int foodx;
int foody;
Random rand=new Random();
public Mpanel() {
initSnake();
this.setFocusable(true);
this.addKeyListener(this);
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.black);
title.paintIcon(this, g, 25, 11);
g.fillRect(25, 75, 850, 600);
g.setColor(Color.green);
g.drawString("length"+len,750,25);
g.drawString("score"+score,750,50);
if(fx=="r"){
right.paintIcon(this,g,snakex[0],snakey[0]);
}
else if(fx=="l"){
left.paintIcon(this,g,snakex[0],snakey[0]);
}
else if(fx=="d"){
down.paintIcon(this,g,snakex[0],snakey[0]);
}
else if(fx=="u"){
up.paintIcon(this,g,snakex[0],snakey[0]);
}
for(int i=1;i<len;i++){
body.paintIcon(this,g,snakex[i],snakey[i]);
}
food.paintIcon(this,g,foodx,foody);
if(isStarted==false) {
g.setColor(Color.green);
g.drawString("press space to start", 325, 325);
g.setFont(new Font("arial",Font.BOLD,40));
}
if(isFailed) {
g.setColor(Color.green);
g.drawString("fail:press space to restart", 325, 325);
g.setFont(new Font("arial",Font.BOLD,40));
}
}
public void initSnake(){
len=3;
snakex[0]=100;
snakey[0]=100;
snakex[1]=75;
snakey[1]=100;
snakex[2]=50;
snakey[2]=100;
foodx=25+25*rand.nextInt(34);
foody=25+25*rand.nextInt(24);
fx="r";
score=0;
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
int keyCode=e.getKeyCode();
if(keyCode==KeyEvent.VK_SPACE){
if(isFailed){
isFailed=false;
initSnake();
} else{
isStarted=!isStarted;
}
repaint();
}
else if(keyCode==KeyEvent.VK_LEFT){
fx="l";
}
else if(keyCode==KeyEvent.VK_RIGHT){
fx="r";
}
else if(keyCode==KeyEvent.VK_DOWN){
fx="d";
}
else if(keyCode==KeyEvent.VK_UP){
fx="u";
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void actionPerformed(ActionEvent e) {
if(isStarted&&!isFailed){
for (int i=len-1;i>0;i--) {
snakex[i] = snakex[i - 1];
snakey[i] = snakey[i - 1];
}
if(fx=="r"){
snakex[0]=snakex[0]+25;
if(snakex[0]>850)snakex[0]=25;
}
else if(fx=="l"){
snakex[0]=snakex[0]-25;
if(snakex[0]<25)snakex[0]=850;
}
else if(fx=="u"){
snakey[0]=snakey[0]-25;
if(snakey[0]<75)snakey[0]=650;
}
else if(fx=="d"){
snakey[0]=snakey[0]+25;
if(snakex[0]>670)snakex[0]=75;
}
if(snakex[0]==foodx&&snakey[0]==foody){
len++;
score++;
foodx=25+25*rand.nextInt(34);
foody=25+25*rand.nextInt(24);
}
for(int q=1;q<len;q++){
if (snakex[q] == snakex[0]&&snakey[q]==snakey[0]) {
isFailed=true;
}
}
repaint();
}
timer.start();
}
}
实现结果:
4.总结
4.1 项目的难点和关键点
显示界面需要JFrame和Jpanel来实现。使用一个全局变量记录当前蛇的长度,方便绘图时画出正确的蛇。在做碰撞检测时,只需要将蛇头节点的坐标和蛇身的坐标、食物的坐标、墙的坐标进行比较即可。当蛇在移动时,需要将储存蛇的数组的每一个元素赋给后一个元素,最后计算首元素,此时最后一个元素的值被丢弃。若吃到食物,则将最后一个元素继续向后赋值,同时设置蛇的长度加一。
4.2 项目的评价:
贪吃蛇的主要功能可以很好的实现,在其基础上加入有趣的图片使得游戏更具有可玩性。
4.3 心得体会
通过该项目,我再次熟悉了frame框架和GUI编程的用法,强化了自己的JAVA编程能力,得到了不小的收获。