游戏截图:
文件布局:
代码分享
用到的一些全局变量
//全局变量
public class Global {
public static final int RECT_WIDTH=20;//每个小方格的长宽
public static final int WIDTH=30;//长 40个小方格
public static final int HEIGHT=30;//宽 40个小方格
public static int GRADE;//成绩
public static long TIME;//时间
public static File file;//文件夹
}
定义蛇类
public class Snake {
private SnakeListener snakeListener;
public static final int UP=1;
public static final int DOWN=-1;
public static final int LEFT=2;
public static final int RIGHT=-2;//表示蛇运动的方向
private int newdirction=RIGHT;
private int olddirction=RIGHT;
private Point tail;//存储蛇的尾巴
public LinkedList<Point> body=new LinkedList<Point>();
private Point p;
//蛇的颜色
private int x,y,z;
private boolean suspendFlag = false;// 控制线程的执行
private SnakeDriver sd=new SnakeDriver();
public static boolean life=true;
public Snake(){
init();
}
//获取蛇的长度
public int getlenght() {
return body.size();
}
public void init() {
int x=Global.WIDTH/2;
int y=Global.HEIGHT/2;
for(int i=0;i<3;i++) {
p=new Point(x-i,y);//默认方向是向右的
body.add(p);
}
}
public void move() {
// System.out.println("蛇在移动...");
//去尾加头法实现蛇移动 首先要得到蛇头
tail=body.removeLast();
int x=getSnakehead().x;
int y=getSnakehead().y;
if(this.newdirction+this.olddirction!=0)
this.olddirction=this.newdirction; //控制方向不往反方向行走
switch(olddirction) {
case UP:
y--;
break;
case DOWN:
y++;
break;
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
}
body.addFirst(new Point(x,y));
}
//得到蛇头位置
public Point getSnakehead() {
return body.getFirst();
}
public void eatfood() {
// System.out.println("蛇正在吃食物...");
//怎么吃 就是将蛇的尾巴加回来 则用变量存储蛇的尾巴
body.addLast(tail);
}
public void changedirction(int dirction) {
this.newdirction=dirction;
// System.out.println("正在改变方向...");
}
public boolean iseatself(Snake snake) {
Point head=snake.getSnakehead();
for(int i=1;i<body.size();i++)
{
if(body.get(i).equals(head))
return true;
}
return false;
}
public void drowMe(Graphics g) {
// System.out.println("蛇正在画出自己...");
//g.setColor(Color.blue);
for(int i=0;i<body.size();i++) {
x=(int) (Math.random()*256);
y=(int) (Math.random()*256);
z=(int) (Math.random()*256);
Color color=new Color(x,y,z);
g.setColor(color);
g.fillRect(body.get(i).x*Global.RECT_WIDTH, body.get(i).y*Global.RECT_WIDTH, Global.RECT_WIDTH, Global.RECT_WIDTH);
}
}
//增加了自定义的监听器
public void addSnakeListener(SnakeListener snakeListener) {
if(snakeListener!=null){
this.snakeListener=snakeListener;
}
}
public void start() {
// new SnakeDriver().start();
sd.start();
}
//得到线程对象
public SnakeDriver getsd() {
return sd;
}
//线程暂停
public void suspend() {
suspendFlag=true;
}
public class SnakeDriver extends Thread{
//唤醒线程
public synchronized void Rouse() {
suspendFlag=false;
notify();
}
@Override
public void run() {
while(life)
{
move();
//每移动一次要判断是否吃到食物和墙
snakeListener.snakeMove(Snake.this);//调用外部类的当前对象
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(this) {
while(suspendFlag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
}
定义食物类
public class Food {
//定义两变量来存储food的位置
private int x,y;
public void drowMe(Graphics g) {
// System.out.println("食物正在画出自己...");
g.setColor(Color.red);
g.fillRect(x*Global.RECT_WIDTH,y*Global.RECT_WIDTH, Global.RECT_WIDTH,Global.RECT_WIDTH);
}
public boolean iseatbysnake(Snake snake) {
//怎么判断食物被蛇吃了 判断是否在同一位置
Point head=snake.getSnakehead();
Point p=new Point(x,y);
if(p.equals(head))
return true;
return false;
}
//增加食物
public void addFood(Point p) {
x=p.x;
y=p.y;
}
//设置food的位置
public Point setloction() {
int x=(int)(Math.random()*30)+1;
int y=(int)(Math.random()*30)+1;
return new Point(x,y);
}
}
定义地图类
public class Map {
private int[][] map=new int[Global.WIDTH+2][Global.HEIGHT+2];//存储边框的数据位置
public Map() {
for(int y=0;y<Global.HEIGHT+2;y++)
{
for(int x=0;x<Global.WIDTH+2;x++)
{
if(y==0||y==Global.HEIGHT+2-1)
map[x][y]=1;
if(x==0||x==Global.WIDTH+2-1)
map[x][y]=1;
}
}
}
public void drowMe(Graphics g) {
// System.out.println("正在画出地图...");
SetRectangle(g);
}
public boolean iseatbysnake(Snake snake) {
Point head=snake.getSnakehead();
for(int k=0;k<Global.WIDTH+2;k++) {
for(int m=0;m<Global.HEIGHT+2;m++) {
if(map[k][m]==1&&head.x==k&&head.y==m)
return true;
}
}
return false;
}
private void SetRectangle(Graphics g)
{
Graphics2D gp=(Graphics2D)g;
Rectangle2D rect=new Rectangle2D.Double(20, 20, 600, 600);
Stroke s=new BasicStroke(5);
gp.setStroke(s);
gp.draw(rect);
}
}
//定义接口用来监听Snake是否碰撞
public interface SnakeListener {
public void snakeMove(Snake snake);
}
GUI显示
public class GamePanel extends JPanel{
private Snake snake=new Snake();
private Food food;
private Map map;
private int x,y,z;
private JLabel label;
private JLabel explain1;
private JLabel explain2;
private JLabel explain3;
private JLabel explain4;
private JLabel explain5;
private JLabel grade;
private JLabel time;
private long endtime;//时间
public static long TIME;//最终显示时间
public static int GRADE;//最终显示分数
private JLabel bgm_label;
private BufferedImage img=null;
private Font font=new Font("宋体",Font.PLAIN,20);
public GamePanel() {
setLayout(null);
//加入说明
Count() ;
//加入图片
addBgm();
}
public void dispaly(Snake snake,Food food,Map map) {
// System.out.println("面板正在画出自己...");
this.snake=snake;
this.food=food;
this.map=map;
repaint(); //自动调用了paintComponent方法
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
SetLine(g);
drawNum(g);
if(food!=null)
food.drowMe(g);
if(map!=null)
map.drowMe(g);
if(snake!=null)
snake.drowMe(g);
}
private void drawNum(Graphics g) {
//分数
g.setColor(Color.black);
g.setFont(new Font("宋体",Font.PLAIN,36));
Global.GRADE=(snake.getlenght()-3)*5;
g.drawString(""+Global.GRADE+"", 720, 330);
//时间
endtime=System.currentTimeMillis();
Global.TIME=(endtime-Controller.starttime)/1000;
g.drawString(""+Global.TIME+""+"秒", 720, 390);
}
private void SetLine(Graphics g)
{
Graphics2D gl=(Graphics2D)g;
Stroke s=new BasicStroke();
gl.setStroke(s);
for(int i=1;i<30;i++)
{
// x=(int) (Math.random()*256);
// y=(int) (Math.random()*256);
// z=(int) (Math.random()*256);
// Color color=new Color(x,y,z);
x=154;//222
y=157;//225
z=162;//230
Color color=new Color(x,y,z);
gl.setColor(color);
Line2D Virtical_L=new Line2D.Double(Global.RECT_WIDTH*i+20, 20, Global.RECT_WIDTH*i+20, 620);
gl.draw(Virtical_L);
Line2D Level_L=new Line2D.Double(20, Global.RECT_WIDTH*i+20, 620, Global.RECT_WIDTH*i+20);
gl.draw(Level_L);
}
}
public void Count() {
label=new JLabel("版权:12210");
label.setLocation(630, 20);
label.setSize(200, 50);
label.setFont(font);
add(label);
//解释
explain1=new JLabel("说明:↑ ↓ ← →键");
explain2=new JLabel("控制方向");
explain3=new JLabel("暂停:Space");
explain4=new JLabel("继续:Enter");
explain5=new JLabel("退出:Esc");
explain1.setBounds(630, 90, 200,20);
explain2.setBounds(630, 130, 200, 20);
explain3.setBounds(630, 170, 200, 20);
explain4.setBounds(630, 210, 200, 20);
explain5.setBounds(630, 250, 200, 20);
explain1.setFont(font);
explain2.setFont(font);
explain3.setFont(font);
explain4.setFont(font);
explain5.setFont(font);
add(explain1);
add(explain2);
add(explain3);
add(explain4);
add(explain5);
//分数
grade=new JLabel("分数:");
grade.setBounds(630, 300, 100, 30);
grade.setFont(new Font("宋体",Font.PLAIN,30));
add(grade);
//时间
time=new JLabel("时间:");
time.setBounds(630, 360, 100, 30);
time.setFont(new Font("宋体",Font.BOLD,30));
add(time);
}
//加入图片
public void addBgm() {
try {
img=ImageIO.read(new File("bgm.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bgm_label=new JLabel(new ImageIcon(img));
bgm_label.setBounds(630,400,img.getWidth(),img.getHeight());
add(bgm_label);
}
}
控制游戏
public class Controller extends KeyAdapter implements SnakeListener{
private Snake snake;
private Food food;
private Map map;
private GamePanel gamepanel;
public static long starttime;//开始游戏时间
public Controller(Snake snake, Food food, Map map, GamePanel gamepanel) {
super();
this.snake = snake;
this.food = food;
this.map = map;
this.gamepanel = gamepanel;
}
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
// System.out.println("改变方向...");
switch(e.getKeyCode()) {
case KeyEvent.VK_UP:
snake.changedirction(Snake.UP);
break;
case KeyEvent.VK_DOWN:
snake.changedirction(Snake.DOWN);
break;
case KeyEvent.VK_RIGHT:
snake.changedirction(Snake.RIGHT);
break;
case KeyEvent.VK_LEFT:
snake.changedirction(Snake.LEFT);
break;
case KeyEvent.VK_SPACE:
snake.suspend();
break;
case KeyEvent.VK_ESCAPE:
System.exit(0);
break;
default:
snake.getsd().Rouse();
break;
}
}
@Override
public void snakeMove(Snake snake) {
// System.out.println("判断是否迟到食物或墙...");
if(food.iseatbysnake(snake)==true) {
snake.eatfood();
//增加新的食物位置
food.addFood(food.setloction());
}
if(map.iseatbysnake(snake)) {
JOptionPane.showMessageDialog(null, "傻瓜,撞到墙啦!");
Snake.life=false;
JOptionPane.showMessageDialog(null, "分数:"+""+Global.GRADE+""+"分"+" "+"耗时:"+""+Global.TIME+""+"秒");
System.exit(0);
}
if(snake.iseatself(snake)) {
JOptionPane.showMessageDialog(null, "傻瓜,吃到自己啦!");
Snake.life=false;
JOptionPane.showMessageDialog(null, "分数:"+""+Global.GRADE+""+"分"+" "+"耗时:"+""+Global.TIME+""+"秒");
System.exit(0);
}
gamepanel.dispaly(snake, food, map);;
}
public void startGame() {
starttime=System.currentTimeMillis();
snake.start();
food.addFood(food.setloction());
}
}
主程序
class Window extends JFrame{
private Snake snake=new Snake();
private Food food=new Food();
private Map map=new Map();
private GamePanel gamepanel=new GamePanel();
private Controller controller=new Controller(snake, food, map, gamepanel);
//背景音乐的变量
private URI uri;
private URL url;
//增加文字
JLabel label;
public Window(){
this.setBounds(100, 100, 900, 680);
this.setTitle("贪吃蛇 version2.0");
this.setResizable(false);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
snake.addSnakeListener(controller);
gamepanel.addKeyListener(controller);
gamepanel.setFocusable(true);
this.add(gamepanel);
this.setVisible(true);
music();
controller.startGame();
}
//添加背景音乐
public void music() {
System.out.println("运行了!");
try{
File f=new File("周二珂 - 告白气球.wav");
uri=f.toURI();
url=uri.toURL();
AudioClip auu=Applet.newAudioClip(url);
auu.loop();
}catch(Exception e) {
e.printStackTrace();
}
}
}
class GameThread extends Thread{
@Override
public void run() {
new Window();
}
}
public class Client{
public static void main(String[] args) throws UnknownHostException, IOException {
// Socket socket=new Socket("127.0.0.1",9999);
new GameThread().start();
// Operation ope=new Operation();
// ope.Write(socket);
// ope.Read();
// socket.close();
}
}
嘿嘿 新手 看视频学的 加油2020年
应该能执行成功的
源码下载