寒假在家无事,看看别人的博客,发现一篇博客:用java实现贪吃蛇,看了看思路,花了一天时间,写出来了。
附图两张:
Game类
package 贪吃蛇带音乐版;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
public class Game extends JFrame implements KeyListener,Runnable{
private int score=0;
private int leftX=0;
private int leftY=0;
private int overtime=500;
private int counttime=0;
private int headX=2;
private int headY=2;
private int flag=1;
private int width=0;
private int height=0;
private int [][] map=null;
private int head_dir=4;
private Image [] image=null;
private ArrayList<node> snake=new ArrayList<node>();
Music music;
Thread t;
final int wall=1,space=0,food=2,
HEADUP=3,HEADDOWN=4,HEADLEFT=5,HEADRIGHT=6,
BODYUP=7,BODYDOWN=8,BODYLEFT=9,BODYRIGHT=10,
UP=1,DOWN=2,LEFT=3,RIGHT=4;
Game(){
super("贪吃蛇带音乐版");
this.setVisible(true);
this.setSize(600, 600);
setResizable(false);
setLocation(800, 20);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// this.setBackground(Color.YELLOW);
Container con=this.getContentPane();
con.setLayout(null);
// con.setBackground(Color.white);
this.setBackground(Color.yellow);
getImage();
width=this.getWidth();
height=this.getHeight();
this.setFocusable(true);
initMap();
this.addKeyListener(this);
// repaint();
t=new Thread(this);
t.start();
music=new Music("G:\\eclipse安装包\\Java工程文件\\贪吃蛇带音乐版\\素材\\音乐素材\\初音宝宝 - 甩葱歌.mp3");
music.loop();
}
void getImage() {
image=new Image[11];
for(int i=0;i<11;i++)
{
image[i]=Toolkit.getDefaultToolkit().getImage("G:\\eclipse安装包\\Java工程文件\\贪吃蛇带音乐版\\素材\\图像素材\\snake"+i+".jpg");
}
}
void get_headXY(){
int i=1;
int j=1;
for(;i<11;i++) {
for(j=1;j<11;j++)
{
if(map[i][j]==HEADUP||map[i][j]==HEADDOWN||map[i][j]==HEADLEFT||map[i][j]==HEADRIGHT)
{
headX=i;
headY=j;
snake.add(new node(headX,headY,map[i][j]));
break;
}
}
}
}
public void paint(Graphics g) {
// System.out.println("我被调用了");
int i=0;
int j=0;
printMap();
for(i=0;i<12;i++) {
for(j=0;j<12;j++) {
g.drawImage(image[map[i][j]], leftX+j*30, leftY+i*30,30,30,this);
}
}
g.clearRect(120, 60 , 360, 40);
g.setColor(Color.RED);
g.setFont(new Font("楷体_2312",Font.BOLD,30));
g.drawString("现在分数:", 180, 90);
g.drawString("得分为:"+String.valueOf(score),300,90);
}
public void initMap() {
map=new Map().getMap();
int i=0;
int j=0;
//
snake.clear();
head_dir=4;
flag=1;
int [][] tem=map;
for(i=0;i<tem.length;i++)
{
for(j=0;j<tem[i].length;j++)
System.out.print(tem[i][j]+" ");
System.out.println();
}
// System.out.println("map___________________________________________________________________");
// for(;i<map.length;i++)
// {
//
// for(j=0;j<map[i].length;j++)
// System.out.print(map[i][j]+" ");
// System.out.println();
// }
get_left_XY();
get_headXY();
}
private void get_left_XY() {
// TODO Auto-generated method stub
leftX=(width-map[0].length*30)/2;
leftY=(height-map.length*30)/2;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new Game();
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {
if(counttime<overtime) {
counttime+=50;
}
else
{
counttime=0;
move();
repaint();
}
try {
if(flag==2)
{
judge();
}
else
{
Thread.sleep(50);
}
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode()==KeyEvent.VK_A)
{
if(overtime>200)
overtime-=100;
}
if(e.getKeyCode()==KeyEvent.VK_D) {
if(overtime<1000)
overtime+=100;
}
if(e.getKeyCode()==KeyEvent.VK_UP)
{
if(map[snake.get(0).x][snake.get(0).y]==HEADDOWN)
return;
head_dir=UP;
}
if(e.getKeyCode()==KeyEvent.VK_DOWN)
{
System.out.println(snake.size());
System.out.println(snake.get(0).x+snake.get(0).y);
if(map[snake.get(0).x][snake.get(0).y]==HEADUP)
return;
head_dir=DOWN;
}
if(e.getKeyCode()==KeyEvent.VK_LEFT)
{
if(map[snake.get(0).x][snake.get(0).y]==HEADRIGHT)
return;
head_dir=LEFT;
}
if(e.getKeyCode()==KeyEvent.VK_RIGHT)
{
if(map[snake.get(0).x][snake.get(0).y]==HEADLEFT)
return;
head_dir=RIGHT;
}
// repaint();
if(flag==2){
String msg = "游戏结束,你的得分是"+score+"\n是否重来?";
int type = JOptionPane.YES_NO_OPTION;
String title = "Game Over";
int choice = 0;
choice = JOptionPane.showConfirmDialog(null, msg,title,type);
if(choice==1){
System.exit(0);
}else if(choice == 0){
initMap();
score=0;
counttime = 0;
overtime = 500;
repaint();
}
}
}
public void move() {
ArrayList<node> temp=new ArrayList<node>();
int i=0;
if(snake.size()==0)
return ;
else
{
System.out.println("蛇的大小:"+snake.size());
int x=snake.get(0).x;
int y=snake.get(0).y;
switch(head_dir) {
case UP :x=x-1 ;break;
case DOWN :x=x+1 ;break;
case LEFT :y=y-1 ;break;
case RIGHT:y=y+1 ;break;
}
if(map[x][y]==wall||map[x][y]==BODYUP||map[x][y]==BODYDOWN||map[x][y]==BODYLEFT||map[x][y]==BODYRIGHT)
{
flag=2;
}
else
if(map[x][y]==food)
{
score++;
resetFood();
switch(head_dir) {
case UP:
temp.add(new node(x,y,HEADUP));
map[x][y]=HEADUP;
break;
case DOWN:
temp.add(new node(x,y,HEADDOWN));
map[x][y]=HEADDOWN;
break;
case LEFT:
temp.add(new node(x,y,HEADLEFT));
map[x][y]=HEADLEFT;
break;
case RIGHT:
temp.add(new node(x,y,HEADRIGHT));
map[x][y]=HEADRIGHT;
break;
}
for(i=0;i<snake.size();i++)
{
if(i==0) {
switch(snake.get(i).dir) {
case HEADUP :snake.get(i).dir=BODYUP ;break;
case HEADDOWN :snake.get(i).dir=BODYDOWN ;break;
case HEADLEFT :snake.get(i).dir=BODYLEFT ;break;
case HEADRIGHT:snake.get(i).dir=BODYRIGHT ;break;
}
}
temp.add(snake.get(i));
map[snake.get(i).x][snake.get(i).y] = snake.get(i).dir;
}
snake=temp;
}
else
{
switch(head_dir) {
case UP:
temp.add(new node(x,y,HEADUP));
map[x][y]=HEADUP;
break;
case DOWN:
temp.add(new node(x,y,HEADDOWN));
map[x][y]=HEADDOWN;
break;
case LEFT:
temp.add(new node(x,y,HEADLEFT));
map[x][y]=HEADLEFT;
break;
case RIGHT:
temp.add(new node(x,y,HEADRIGHT));
map[x][y]=HEADRIGHT;
break;
}
for(i=0;i<snake.size()-1;i++)
{
if(i==0) {
switch(snake.get(i).dir) {
case HEADUP :snake.get(i).dir=BODYUP ;break;
case HEADDOWN :snake.get(i).dir=BODYDOWN ;break;
case HEADLEFT :snake.get(i).dir=BODYLEFT ;break;
case HEADRIGHT:snake.get(i).dir=BODYRIGHT ;break;
}
}
temp.add(snake.get(i));
map[snake.get(i).x][snake.get(i).y]=snake.get(i).dir;
}
map[snake.get(snake.size()-1).x][snake.get(snake.size()-1).y]=0;
snake=temp;
}
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
public void printMap() {
int i;
int j;
for(i=0;i<map.length;i++) {
for(j=0;j<map[0].length;j++)
{
System.out.print(map[i][j]+" ");
}
System.out.println();
}
System.out.println("______________________________________________");
}
public void resetFood()
{
int i;
int j;
do {
i=(int)(Math.random()*10)+1;
j=(int)(Math.random()*10)+1;
}while(map[i][j]!=0);
map[i][j]=food;
}
public void judge()
{
if(flag==2) {
int option=JOptionPane.YES_NO_OPTION;
int choice;
String message="游戏结束,你的得分为:"+score+"分,是否重来?";
choice=JOptionPane.showConfirmDialog(null, message,"游戏结束",option);
if(choice==1)
{
System.exit(0);
}
else
if(choice==0)
{
score=0;
initMap();
flag=1;
counttime=0;
overtime=500;
repaint();
}
}
}
}
主要方法:
用了线程驱动蛇前进,若规定时间(overtime)内,(用counttime计时)无按键事件,则蛇朝着原方向前进一步,
move() 先得出蛇下一步所到达的坐标,
1.判断是否为墙或自身:是,则给出分数,询问是否再来一局;否,则退出。
2.判断是否为食物,若是,新生成一个动态数组,将这个坐标加进去,将原来的蛇头变成蛇身,然后,将剩余的蛇身加进去。
3.既不是1,也不是2,前进一步,同样,,新生成一个动态数组,将这个坐标加进去,将原来的蛇头变成蛇身,然后,将剩余的蛇身加进去,但是不同的是,原来蛇的最后一个节点不用加进去,因为蛇只是前进了一步。
还有keyPressed()
1.按A ,加速前进(减小overtime);按D,减速前进(增大overtime)。
2.按四个方向键,调整蛇头方向。
Music类:
package 贪吃蛇带音乐版;
import java.io.*;
import javazoom.jl.player.Player;
public class Music {
private String filename;
private Player player;
Music(String filename){
this.filename=filename;
}
public void play() {
try {
BufferedInputStream buffer=new BufferedInputStream(new FileInputStream(filename));
player=new Player(buffer);
player.play();
}
catch(Exception e) {
System.out.println(e);
}
}
void loop() {
while(true) {
this.play();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Music music=new Music("G:\\eclipse安装包\\Java工程文件\\java 播放MP3\\src\\music\\初音宝宝 - 甩葱歌.mp3");
music.loop();
}
}
这个类主要是控制音乐播放,很简陋,也很容易理解。
Map类
package 贪吃蛇带音乐版;
public class Map {
int [][] map={
{1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,1},
{1,0,6,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,2,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1}
};
public int [][] getMap(){
int [][] temp=map;
// temp=map;
return temp;
}
}
初始化地图
node类
表示蛇的节点
package 贪吃蛇带音乐版;
public class node {
int x;
int y;
int dir;
node(int x,int y,int dir){
this.x=x;
this.y=y;
this.dir=dir;
}
}
总结一下所犯的错误:
1
int i;
int j;
for(i=0;i<map.length;i++) {
for(j=0;j<map[0].length;j++)
{
System.out.print(map[i][j]+" ");
}
System.out.println();
}
把内层循环的j=0忘了,结果导致我找了半天bug,
2.粗心
变量名字写错了,有浪费了时间。
3.
也可说是粗心
image[i]=Toolkit.getDefaultToolkit().getImage("G:\\eclipse安装包\\Java工程文件\\贪吃蛇带音乐版\\素材\\图像素材\\snake"+i+".jpg");
这句话,我少了snake,直接出不来图像。凉凉~~
想学学的同学,下面是链接:(记得改路径)
https://pan.baidu.com/s/1eGorbpPWEuDpNMRwRnia7w
欢迎各位大佬提出指导意见