这个贪吃蛇是我学完Java之后的课程设计作业,做了有挺久的,做完这个小游戏,自己对Java的一些知识也更了解了些。其中包括按完按钮后焦点的处理啊,还有就是图形的闪烁问题。我当时做的时候基本是在自己电脑上完成的,后来才放到学校机房测试的。说来也奇怪,这个代码开始在我自己电脑上运行的时候并没有闪烁,所以我也就没想过要处理闪烁的问题,可是后来在学校机房闪烁的十分严重,所以才又用双缓冲来处理闪烁。
双缓冲解决图形闪烁源代码:
@Overridepublic void update(Graphics g) {// TODO Auto-generated method stubImageBuffer = createImage(this.getWidth(), this.getHeight());GraImage = ImageBuffer.getGraphics(); // 获取图形缓冲区的图形上下文paint(GraImage); // 用paint方法中编写的绘图过程对图形缓冲区绘图GraImage.dispose(); // 释放图形上下文资源g.drawImage(ImageBuffer, 0, 0, this); // 将图形缓冲区绘制到屏幕上}
运行效果:
下面是贪吃蛇完整源代码:
SnakeBody.java
package com.java.snake;import java.awt.Color;public class SnakeBody {private int x;private int y;private Color color;public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}public Color getColor() {return color;}public void setColor(Color color) {this.color = color;}
}
GameUi.java
package com.java.snake;import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
import java.util.Random;import javax.swing.*;public class GameUi extends JFrame {int flag = 1;JLabel jl = new JLabel();JLabel fs = new JLabel();JButton start = new JButton("开始");JButton stop = new JButton("暂停");JButton restart = new JButton("重玩");JButton exit = new JButton("退出");boolean p = true;JPanel pan = new JPanel();GridLayout grid = new GridLayout(1, 5);Random r1 = new Random();Random r2 = new Random();int a = (r1.nextInt(53) + 1) * 10 - 4;int b = (r2.nextInt(35) + 6) * 10 - 1;int score = 0;int foodNumber = 0;final int HW = 9;int x = (r1.nextInt(35) + 10) * 10 - 4;int y = (r2.nextInt(35) + 6) * 10 - 1;LinkedList<SnakeBody> snake = new LinkedList<SnakeBody>();int direction = 1;SnakeBody tail;SnakeBody head;class Mytask implements Runnable{@Overridepublic void run() {// TODO Auto-generated method stubALL: while (true) {head = snake.getFirst();/** 判断蛇是否吃到食物,如果吃到食物则产生一个随机数,若产生的随机数在蛇的身体上则重新再产生一个随机数*/if (head.getX() == a && head.getY() == b) {SnakeBody c = new SnakeBody();snake.add(c);++foodNumber;score += 10;fs.setText("分数:" + score);/* 判断生成的食物是不是在蛇的身体里 */for (int i = 0; i < snake.size(); i++) {SnakeBody d = snake.get(i);if (d.getX() == a && d.getY() == b) {a = (r1.nextInt(53) + 1) * 10 - 4;b = (r2.nextInt(35) + 6) * 10 - 1;}}}int x1 = head.getX();int y1 = head.getY();/* 判断是否触到边缘 */if (x1 < 6 || x1 > 536 || y1 < 59 || y1 > 419) {gameover();break ALL;}/* 判断是否吃到自己的身体 */else {for (int i = 3; i < snake.size(); i++) {SnakeBody d = snake.get(i);if (d.getX() == x1 && d.getY() == y1) {gameover();break ALL;}}}if (p != false) {moving(direction);update(getGraphics());}try {//Thread.sleep(500 - foodNumber / 2 * 100);//可设置等级,等级不同可以有不同的速度Thread.sleep(100);} catch (Exception e) {}}}private void gameover() {// TODO Auto-generated method stubjl.setText("GAME OVER");jl.setBounds(150, 150, 400, 100);jl.setForeground(Color.red);jl.setFont(new Font("宋体", Font.BOLD, 55));add(jl);update(getGraphics());}}Thread timer = new Thread(new Mytask());public GameUi() {// TODO Auto-generated constructor stubthis.setTitle("我的贪吃蛇");this.setSize(552, 435);this.setResizable(false);this.setLocationRelativeTo(null);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);initSnakeBody();initEvent();fs.setText("分数:" + score);add(pan, BorderLayout.NORTH);pan.setLayout(grid);pan.add(start);pan.add(stop);pan.add(restart);pan.add(exit);pan.add(fs);this.requestFocus();start.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubif (e.getSource() == start) {p = true;}GameUi g = getUi();g.requestFocus();}});stop.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubif (e.getSource() == stop)p = false;}});restart.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubif (e.getSource() == restart) {new GameUi();dispose();}}});exit.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubif (e.getSource() == exit)System.exit(EXIT_ON_CLOSE);}});timer.start();}protected GameUi getUi() {return this;}@Override/* 画边缘,蛇身,食物 */public void paint(Graphics g) {// TODO Auto-generated method stubsuper.paint(g);Graphics2D g_2d = (Graphics2D) g;g_2d.setColor(Color.BLACK);g_2d.setStroke(new BasicStroke(2f));g_2d.drawLine(5, 58, 547, 58);// 上面的那根线g_2d.drawLine(5, 58, 5, 430);// 左边的那根线g_2d.drawLine(5, 430, 547, 430);// 下面的那根线g_2d.drawLine(547, 58, 547, 430);// 右边的那根线g_2d.setColor(Color.black);for (int i = 0; i < snake.size(); i++) {SnakeBody b = snake.get(i);g.fillRect(b.getX(), b.getY(), HW, HW);}g.setColor(Color.red);g.fillRect(a, b, HW, HW);}Image ImageBuffer = null;Graphics GraImage = null;@Overridepublic void update(Graphics g) {// TODO Auto-generated method stubImageBuffer = createImage(this.getWidth(), this.getHeight());GraImage = ImageBuffer.getGraphics(); // 获取图形缓冲区的图形上下文paint(GraImage); // 用paint方法中编写的绘图过程对图形缓冲区绘图GraImage.dispose(); // 释放图形上下文资源g.drawImage(ImageBuffer, 0, 0, this); // 将图形缓冲区绘制到屏幕上}/* 初始化蛇身 */public void initSnakeBody() {// TODO Auto-generated method stubfor (int i = 0; i < 5; i++) {SnakeBody b = new SnakeBody();b.setX(x + i * HW + i);b.setY(y);snake.add(b);}tail = snake.getLast();head = snake.getFirst();}/* 蛇移动的时候身体的变化 */public void moving(int direction) {tail = snake.removeLast();head = snake.getFirst();switch (direction) {// 1:左;2:上;3:右;4:下case 1:tail.setX(head.getX() - HW - 1);tail.setY(head.getY());break;case 2:tail.setX(head.getX());tail.setY(head.getY() - HW - 1);break;case 3:tail.setX(head.getX() + HW + 1);tail.setY(head.getY());break;case 4:tail.setX(head.getX());tail.setY(head.getY() + HW + 1);break;}snake.addFirst(tail);}/* 方向控制 */public void initEvent() {this.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent event) {// TODO Auto-generated method stubswitch (event.getKeyCode()) {case KeyEvent.VK_UP:if (direction == 2 || direction == 4) {break;}direction = 2;break;case KeyEvent.VK_DOWN:if (direction == 2 || direction == 4) {break;}direction = 4;break;case KeyEvent.VK_LEFT:if (direction == 1 || direction == 3) {break;}direction = 1;break;case KeyEvent.VK_RIGHT:if (direction == 1 || direction == 3) {break;}direction = 3;break;}}});}
}
Test.java
package com.java.snake;public class Test {/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubnew GameUi();}}