java貪吃蛇,java貪吃蛇代碼
思路 :主要是類比蛇的運動。只要對蛇頭進行操作,然後讓前一種狀態先的蛇頭位置複製給現在蛇身的第二個部分,讓前一狀態的蛇的第二個部分的位置複製給現在蛇身的第三個部分......以此類推,從而達到類比蛇運動的狀態。
GluttonousSnake.java
package xjj;//貪吃蛇圖形介面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();}}}}
MapCanvas.java
package xjj;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);}}
SnakeCanvas.java
package xjj;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;}}