思路 :主要是模拟蛇的运动。只要对蛇头进行操作,然后让前一种状态先的蛇头位置复制给现在蛇身的第二个部分,让前一状态的蛇的第二个部分的位置复制给现在蛇身的第三个部分......以此类推,从而达到模拟蛇运动的状态。
GluttonousSnake.javaMapCanvas.java
- //贪吃蛇图形界面
- import java.awt.FlowLayout;
- import java.awt.GridLayout;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.util.Observable;
- import java.util.Observer;
- import javax.swing.ImageIcon;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JLabel;
- import javax.swing.JMenu;
- import javax.swing.JMenuBar;
- import javax.swing.JMenuItem;
- import javax.swing.JOptionPane;
- import javax.swing.JPanel;
- import javax.swing.JTextField;
- import javax.swing.border.TitledBorder;
- import javax.swing.event.CaretEvent;
- import javax.swing.event.CaretListener;
- import javax.swing.event.ChangeEvent;
- import javax.swing.event.ChangeListener;
- public class GluttonousSnake extends JFrame implements ActionListener {
- private JButton upButton, downButton, leftButton, rightButton;//控制方向按钮
- private JTextField score;//分数
- private SnakeCanvas snake;//蛇的模型
- public GluttonousSnake() {
- super("贪吃蛇");//设置标题
- this.setSize(725, 515);//设置大小
- this.setDefaultCloseOperation(EXIT_ON_CLOSE);//设置退出按键
- this.setLocationRelativeTo(null);//设置窗口居中
- JPanel p = new JPanel();//控制按钮和显示分数面板
- p.setBorder(new TitledBorder("控制和显示区"));//设置这个面板的标题
- this.getContentPane().add(p, "East");//设置此面板的位置
- p.setLayout(new GridLayout(4, 1));//设置此面板的布局方式,为网格布局方式
- JPanel p2 = new JPanel();//在此面板中添加显示分数的面板
- p2.setLayout(new FlowLayout());//设置为流布局方式
- p2.add(new JLabel("得分:"));
- score = new JTextField("0");
- score.setEditable(false);
- p2.add(score);
- p.add(p2);
- //添加按钮,有图片的并添加事件监听
- upButton = new JButton("", new ImageIcon("up.png"));
- upButton.setActionCommand("up");
- upButton.addActionListener(this);
- downButton = new JButton("", new ImageIcon("down.png"));
- downButton.setActionCommand("down");
- downButton.addActionListener(this);
- leftButton = new JButton("", new ImageIcon("left.png"));
- leftButton.setActionCommand("left");
- leftButton.addActionListener(this);
- rightButton = new JButton("", new ImageIcon("right.png"));
- rightButton.setActionCommand("right");
- rightButton.addActionListener(this);
- p.add(upButton);
- JPanel p1 = new JPanel();
- p1.setLayout(new GridLayout(1, 2));
- p1.add(leftButton);
- p1.add(rightButton);
- p.add(p1);
- p.add(downButton);
- addMenu();//添加菜单
- start();
- this.setResizable(false);
- this.setVisible(true);
- }
- private void start() {
- snake = new SnakeCanvas();
- this.getContentPane().add(snake);
- }
- private void addMenu() {
- JMenuBar menubar = new JMenuBar();
- this.setJMenuBar(menubar);
- JMenu game = new JMenu("游戏");
- JMenu help = new JMenu("帮助");
- JMenuItem jitemNew = new JMenuItem("新游戏");
- jitemNew.setActionCommand("new");
- jitemNew.addActionListener(this);
- JMenuItem jitemPause = new JMenuItem("暂停");
- jitemPause.setActionCommand("pause");
- jitemPause.addActionListener(this);
- JMenuItem jitemExit = new JMenuItem("退出");
- jitemExit.setActionCommand("exit");
- jitemExit.addActionListener(this);
- game.add(jitemNew);
- game.add(jitemPause);
- game.addSeparator();//菜单里设置分隔线
- game.add(jitemExit);
- menubar.add(game);
- menubar.add(help);
- }
- public static void main(String[] args) {
- new GluttonousSnake();
- }
- public void actionPerformed(ActionEvent e) {
- if (e.getActionCommand().equalsIgnoreCase("exit")) {
- System.exit(EXIT_ON_CLOSE);
- }
- if (e.getSource() instanceof JButton) {
- if (e.getActionCommand().equalsIgnoreCase("up")) {//响应向上按钮按下事件
- snake.setDirect(1);//设置蛇头运动方向
- snake.repaint();//对蛇模型重新画
- snake.timer.start();//定时器开始
- return;
- }
- if (e.getActionCommand().equalsIgnoreCase("down")) {
- snake.setDirect(2);
- snake.repaint();
- snake.timer.start();
- return;
- }
- if (e.getActionCommand().equalsIgnoreCase("left")) {
- snake.setDirect(3);
- snake.repaint();
- snake.timer.start();
- return;
- }
- if (e.getActionCommand().equalsIgnoreCase("right")) {
- snake.setDirect(4);
- snake.repaint();
- snake.timer.start();
- return;
- }
- }
- if (e.getSource() instanceof JMenuItem) {
- if (e.getActionCommand().equalsIgnoreCase("new")) {
- //this.getContentPane().remove(snake);
- snake.init();
- snake.repaint();
- snake.timer.start();
- }
- if (e.getActionCommand().equalsIgnoreCase("pause")) {
- snake.timer.stop();
- JOptionPane.showMessageDialog(this, "继续请按“确定”");
- snake.timer.start();
- }
- }
- }
- }
- import java.awt.Canvas;
- import java.awt.Color;
- import java.awt.Graphics;
- //蛇运行的地图
- public class MapCanvas extends Canvas{
- public void paint(Graphics g) {
- g.setColor(Color.red);
- for(int i=30;i<=450;i+=30){
- g.drawLine(0,i,450,i);
- }
- for(int i=30;i<=450;i+=30){
- g.drawLine(i,0,i,450);
- }
- g.drawLine(0, 0, 450, 0);
- g.drawLine(0, 450, 450, 450);
- g.drawLine(0, 0, 0, 450);
- g.drawLine(450, 0, 450, 450);
- }
- }
来自:http://blog.csdn.net/u011479875/article/details/46355905
- import java.awt.Color;
- import java.awt.Graphics;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.util.Random;
- import javax.swing.JOptionPane;
- import javax.swing.Timer;
- //蛇模型
- public class SnakeCanvas extends MapCanvas implements ActionListener {
- private int number = 5;//蛇身的初始长度
- public Timer timer;//定时器
- private Body[] bodys;//蛇身
- private Body food;//食物
- public int score=0;//分数
- private int speed=250;//定时器延时事件
- int direct = 3;//蛇头初始方向
- private int[][] mapflag = new int[455][455];//地图标记
- //初始化
- public void init(){
- this.direct=3;
- this.number=5;
- this.bodys = new Body[this.number];
- mapflag = new int[455][455];
- for (int i = 0, x = 300; i < this.number; i++, x += 30) {
- bodys[i] = new Body(x, 180);
- mapflag[bodys[i].x][bodys[i].y] = 2;//如果是蛇体 设标记为2
- }
- food = creatFood();//创建食物
- }
- public SnakeCanvas() {
- init();
- timer = new Timer(speed, this);//创建定时器对象
- timer.start();//定时器启动
- }
- private class Body {//蛇头成员
- int x, y;
- Body(int x, int y) {
- this.x = x;
- this.y = y;
- }
- }
- public void paint(Graphics g) {//画图
- super.paint(g);
- if(bodys==null){
- return ;
- }
- for (int i = 0; i < this.number; i++) {
- if(i==0){//设置蛇头颜色不同
- g.setColor(Color.blue);
- }else{
- g.setColor(Color.black);
- }
- mapflag[bodys[i].x][bodys[i].y] = 2;
- g.fillOval(bodys[i].x, bodys[i].y, 30, 30);//画蛇体
- }
- g.setColor(Color.red);
- g.fillOval(food.x, food.y, 30, 30);//画食物
- }
- public Body creatFood() {
- int x = 0, y = 0;
- do {//随机生成食物位置
- Random r = new Random();//创建随机数对象
- x = r.nextInt(450);//在0到所给的数中随机产生一个伪随机数
- y = r.nextInt(450);
- //System.out.println(mapflag[x][y]+"!");
- } while (x % 30 != 0 || y % 30 != 0 || mapflag[x][y]==2 );//保证位置不是蛇身的部分,并且确保整齐性
- //System.out.println(x + " " + y);
- mapflag[x][y] = 1;//将食物标记为1,下面就可以通过标记的不同来判断是吃到食物还是自身,从而进行不同的操作
- return new Body(x, y);
- }
- public void actionPerformed(ActionEvent e) {
- if(bodys==null){
- return ;
- }
- if(!isMove()){//如果移动失败,游戏结束
- JOptionPane.showMessageDialog(this, "Game Over !");
- bodys=null;
- timer.stop();
- return ;
- }
- repaint();
- }
- //蛇移动,原理:仅需对蛇头进行操作,然后将蛇头之前的位置赋值给现在蛇身的第二个部分,
- //让之前的第二个部分复制个现在的第三个部分。。。。以此类推,模拟蛇运动(这是关键)
- public void move(int x,int y) {
- Body[] b=new Body[bodys.length];
- for(int i=0;i<this.number;i++){
- b[i]=new Body(bodys[i].x,bodys[i].y);
- }
- this.bodys[0].x=x;
- this.bodys[0].y=y;
- for(int i=1;i<this.number;i++){
- this.bodys[i]=b[i-1];
- }
- setMapflag();
- }
- private void setMapflag() {//地图标记的刷新
- mapflag=new int[455][455];
- mapflag[food.x][food.y]=1;
- for(int i=0;i<this.number;i++){
- mapflag[bodys[i].x][bodys[i].y]=2;
- }
- }
- //判断是否移动成功
- public boolean isMove() {
- if(bodys==null){
- return false;
- }
- int x=bodys[0].x;
- int y=bodys[0].y;
- switch (this.direct) {//通过方向的不同对蛇头进行不同的操作
- case 1:
- y -= 30;
- break;
- case 2:
- y += 30;
- break;
- case 3:
- x -= 30;
- break;
- case 4:
- x += 30;
- break;
- }
- if(x<0||y>=450||x>=450||y<0){//越界问题
- return false;
- }
- if(mapflag[x][y]==1){//标记为1 ,则为蛇头,要添加蛇身长度
- this.number++;
- addSnake(x,y);//添加蛇长
- // System.out.println("*");
- return true;
- }else if(mapflag[x][y]==2){//标记为2,则为蛇体,即自己吃到自己,游戏结束
- // System.out.println("^");
- return false;
- }else{
- // System.out.println("%");
- move(x,y);
- return true;
- }
- }
- //添加蛇身,类似move();
- private void addSnake(int x, int y) {
- this.score++;
- Body[] b=new Body[bodys.length];
- for(int i=0;i<this.number-1;i++){
- b[i]=new Body(bodys[i].x,bodys[i].y);
- }
- bodys=new Body[this.number];
- this.bodys[0]=new Body(x,y);
- for(int i=1;i<this.number;i++){
- this.bodys[i]=b[i-1];
- }
- setMapflag();
- food = creatFood();
- }
- public void setDirect(int i) {//设置蛇头方向
- this.direct = i;
- }
- }
来源: http://www.phpxs.com/code/1001788/