Java_GUI小遊戲--貪喫蛇



貪喫蛇遊戲:是一條蛇在封閉圍牆裏,圍牆裏隨機出現一個食物,通過按鍵盤四個光標鍵控制蛇向上下左右四個方向移動,蛇頭撞倒食物,則食物被喫掉,蛇身體長一節,接着又出現食物,等待蛇來喫,如果蛇在移動中撞到牆或身體交叉蛇頭撞倒自己身體遊戲結束。



(本文就是隻需要用到一個類就能來實現這個小遊戲,源代碼在文章最後面哦O(∩_∩)O~)


一、首先給蛇添加一個界面

二、對蛇和食物的初始化

三、實現判斷遊戲結束的方法以及鍵盤對蛇的運動




一、首先給蛇添加一個界面


	public Snake() {
		//給遊戲外邊框添加標題(this就表示當前對象)
		this.setTitle("貪喫蛇");
		//不能改變邊框的大小
		this.setResizable(false);
		//設施邊框的大小
		this.setSize(500, 500);
		//居中顯示
		this.setLocationRelativeTo(null);
		//當點擊關閉時候程序停止
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//設置可見
		this.setVisible(true);
	}


把這些放到Snake構造函數裏面的好處:可以在創建這個對象的自動調用這個裏面的代碼


下面來設置遊戲背景和貪喫蛇在紅線裏面能活動的範圍


(Graphics是Java Gui裏面的一個畫筆類)


	public void paint(Graphics g) {
		
		Image img=createImage(500,500);
		//用Graphics畫筆類創建一個畫筆來畫出這個白布
		Graphics g2=img.getGraphics();
		//把遊戲背景填充成白色
		g2.setColor(Color.WHITE);
		//設置填充範圍
		g2.fillRect(0, 0, 500, 500);
		//把畫筆移動到的位置
		g2.translate(50, 50);
		//設置邊框爲紅色(邊框內爲蛇能活動的範圍)
		g2.setColor(Color.RED);
		g2.drawRect(0,0,400,400);
		

		}

貪喫蛇的食物可以一個紅色的小方塊來實現,這個食物目前是固定的,下面會實現食物的隨機生成
		g2.setColor(Color.RED);
		g2.fillRect(100, 100, 10, 10);
運行Eclipse可以看到




二、對蛇和食物的初始化


爲了可以讓蛇不斷的向四周移動,我們用多個小正方形來組成,而LinkList正好可以來組成貪喫蛇,而食物就比較簡單,用一個隨機生成紅點就可以用來表示食物的生成


遊戲開始的時候蛇本身就已經存在,所以在遊戲開始的時候蛇和食物就已經產生了


蛇:

public class Snake extends	JFrame
{
	
	//食物
	private Point point=new Point();
	//蛇
	private LinkedList<Point>	list=new LinkedList<Point>();
	
	//爲食物和蛇的座標進行初始化
	public void init() {
		//默認食物輸出化的位置
		point.setLocation(100, 100);
		list.add(new Point(300,300));
		list.add(new Point(310,300));
		list.add(new Point(320,300));
		list.add(new Point(330,300));
		list.add(new Point(340,300));
		list.add(new Point(350,300));
		list.add(new Point(360,300));
		new Thread(new MoveThread()).start();
	}

		for(int i=0;i<list.size();i++) {
			//下面來得到蛇的那些小點,後面兩個參數是表示小方框的大小
			//能在指定的位置畫出蛇的位置
			g2.fillRect(list.get(i).x,list.get(i).y, 10, 10);
		}


食物:

先前上面食物點是寫死了的,遊戲中的食物是需要隨機生成的,而我們知道了實際上這個食物的點是point,所以上面畫食物的代碼就可以改爲

		g2.setColor(Color.RED);
		g2.fillRect(point.x, point.y, 10, 10);


紅點的隨機生成可以用到Math中的random方法

					int x=(int)(Math.random()*40)*10;
					int y=(int)(Math.random()*40)*10;
					point.setLocation(x, y);



接下來就是在構造函數中調用這個Init()初始化方法


	public Snake() {
		//給遊戲外邊框添加標題(this就表示當前對象)
		this.setTitle("貪喫蛇");
		//不能改變邊框的大小
		this.setResizable(false);
		//設施邊框的大小
		this.setSize(500, 500);
		//居中顯示
		this.setLocationRelativeTo(null);
		//當點擊關閉時候程序停止
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//設置可見
		this.setVisible(true);
		//調用init
		this.init();
	}

運行Eclipse可以看到


上面遊戲的初始化就完成了,目前遊戲是靜止不動的,接下來我們要用上下左右四個按鍵來讓蛇移動起來,一開始我們讓蛇不斷的想左移動,直到我們按下鍵盤上下左右才讓蛇改變移動的方向,蛇移動的時候原理也很簡單,可以不斷的讓右邊的點去掉,然後讓左邊生成一個新的點,這時候我們就可以用到線程,用線程的好處:貪喫蛇遊戲一直在往前動,我們可以通過死循環,用線程一直讓貪喫蛇進行移動,我們在這裏是實現一個接口,在裏面重寫它的Run方法,start方法已經封裝好了,這個線程是一個死循環,只要遊戲沒有Over,線程是不斷運行的

//內部類 實現線程
	//寫內部類是因爲用線程的時候都都需要獲取點的值來改變點的屬性
	class MoveThread implements Runnable{
		@Override
		public void run()
		{
			// TODO Auto-generated method stub
			while(true) {
				try {
					Thread.sleep(150);	//每隔150毫秒對線程實行一次監控
				}catch(InterruptedException e) {
					e.printStackTrace();
				}
				//獲取蛇的第一個點
				Point p=list.getFirst().getLocation();
				switch(37) {//37在ASCII中表示左的意思
				case 37:
					p.x=p.x-10;	
					break;
					
				}
				list.addFirst(p);
			
				//刪除最後一個點
				list.removeLast();
				
				//調用畫的方法
				Snake.this.repaint();
			}
		}

內部類實現的好處:因爲在線程裏面還得不斷用到上面的屬性,我們得改變這些點的值,如果在外面寫的話還要不斷去寫方法得到這些點的值


在初始化小蛇的時候開啓這個線程,執行線程裏面的內容

	public void init() {
		//默認食物輸出化的位置
		point.setLocation(100, 100);
		list.add(new Point(300,300));
		list.add(new Point(310,300));
		list.add(new Point(320,300));
		list.add(new Point(330,300));
		list.add(new Point(340,300));
		list.add(new Point(350,300));
		list.add(new Point(360,300));
		//開始啓用這個線程
		new Thread(new MoveThread()).start();
	}
這時候蛇就一直向左動起來了,注意這裏沒有實現當蛇喫掉食物變長的方法,也沒有判斷蛇能移動範圍,這時候運行Eclipse可以看到程序運行如下



三、實現判斷遊戲結束的方法以及鍵盤對蛇的運動


(list.contains(o),系統會對list中的每個元素e調用o.equals(e),方法,加入list中有n個元素,那麼會調用no.equals(e),只要有一次o.equals(e)返回了true,那麼list.contains(o)返回true,否則返回false。)


				//判斷遊戲結束的兩種方法
				//1.蛇超出了邊界	2.蛇頭碰到蛇的身體
				if(p.x<0||p.x>390||p.y<0||p.y>390||list.contains(p)) {//在上面的時候點就已經定位到50,50
					JOptionPane.showMessageDialog(null, "遊戲結束");
					break;
				}

在判斷遊戲結束下面實現遊戲的一些基本邏輯


				list.addFirst(p);
				//當蛇喫掉食物後 馬上生成新的食物 自身變長
				if(p.equals(point)) {
					int x=(int)(Math.random()*40)*10;
					int y=(int)(Math.random()*40)*10;
					point.setLocation(x, y);
				}else {
					//刪除最後一個點
					list.removeLast();
				}
				//調用畫的方法
				Snake.this.repaint();

接下來是要實現用上下左右來控制蛇的移動,這裏就需要用線程不斷的去監聽


定義一個變量key

	private int key =37;

下面就是實現蛇的監聽

	public Snake() {
		//給遊戲外邊框添加標題(this就表示當前對象)
		this.setTitle("貪喫蛇");
		//不能改變邊框的大小
		this.setResizable(false);
		//設施邊框的大小
		this.setSize(500, 500);
		//居中顯示
		this.setLocationRelativeTo(null);
		//當點擊關閉時候程序停止
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//設置可見
		this.setVisible(true);
		this.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				//鍵盤的上下左右
					if(e.getKeyCode()>=37&&e.getKeyCode()<=40) {
						if(Math.abs(key-e.getKeyCode())!=2) {
							key=e.getKeyCode();
						}
					}
			}
		});
		this.init();
	}

重寫在線程中run方法實現的邏輯:

public void run()
		{
			// TODO Auto-generated method stub
			while(true) {
				try {
					Thread.sleep(150);
				}catch(InterruptedException e) {
					e.printStackTrace();
				}
				//獲取蛇的第一個點
				Point p=list.getFirst().getLocation();
				switch(key) {//37表示前行
				case 37:
					p.x=p.x-10;	
					break;
				case 38:
					p.y=p.y-10;	
					break;
				case 39:
					p.x=p.x+10;
					break;
				case 40:
					p.y=p.y+10;
					break;
					
				}


這時候在主函數中創建這個蛇就可以運行遊戲:

	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
			new Snake();
	}


運行結果如下:



下面就給出這個類的代碼,在Eclipse中按F11就可以直接運行了

package game;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.LinkedList;

import javax.swing.*;

public class Snake extends	JFrame
{
	
	//食物
	private Point point=new Point();
	//蛇
	private LinkedList<Point>	list=new LinkedList<Point>();
	
	private int key =37;
	//爲食物和蛇的座標進行初始化
	public void init() {
		//默認食物輸出化的位置
		point.setLocation(100, 100);
		list.add(new Point(300,300));
		list.add(new Point(310,300));
		list.add(new Point(320,300));
		list.add(new Point(330,300));
		list.add(new Point(340,300));
		list.add(new Point(350,300));
		list.add(new Point(360,300));
		//開始啓用這個線程
		new Thread(new MoveThread()).start();
	}
	
	public void paint(Graphics g) {
		
		Image img=createImage(500,500);
		//用Graphics畫筆類創建一個畫筆來畫出這個白布
		Graphics g2=img.getGraphics();
		//把遊戲背景填充成白色
		g2.setColor(Color.WHITE);
		//設置填充範圍
		g2.fillRect(0, 0, 500, 500);
		//把畫筆移動到的位置
		g2.translate(50, 50);
		//設置邊框爲紅色(邊框內爲蛇能活動的範圍)
		g2.setColor(Color.RED);
		g2.drawRect(0,0,400,400);
		
		
		//下面實現小蛇
		g2.setColor(Color.GREEN);
		//蛇 獲取List中的每一個點
		for(int i=0;i<list.size();i++) {
			//下面來得到蛇的那些小點,後面兩個參數是表示小方框的大小
			//能在指定的位置畫出蛇的位置
			g2.fillRect(list.get(i).x,list.get(i).y, 10, 10);
		}
		

		
		//畫食物
		g2.setColor(Color.RED);
		g2.fillRect(point.x, point.y, 10, 10);
		
		g.drawImage(img, 0, 0, 500, 500, this);
	}
	
	public Snake() {
		//給遊戲外邊框添加標題(this就表示當前對象)
		this.setTitle("貪喫蛇");
		//不能改變邊框的大小
		this.setResizable(false);
		//設施邊框的大小
		this.setSize(500, 500);
		//居中顯示
		this.setLocationRelativeTo(null);
		//當點擊關閉時候程序停止
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//設置可見
		this.setVisible(true);
		this.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				//鍵盤的上下左右
					if(e.getKeyCode()>=37&&e.getKeyCode()<=40) {
						if(Math.abs(key-e.getKeyCode())!=2) {
							key=e.getKeyCode();
						}
					}
			}
		});
		this.init();
	}
	
	//內部類 實現線程
	//寫內部類是因爲用線程的時候都都需要獲取點的值來改變點的屬性
	class MoveThread implements Runnable{
		@Override
		public void run()
		{
			// TODO Auto-generated method stub
			while(true) {
				try {
					Thread.sleep(150);
				}catch(InterruptedException e) {
					e.printStackTrace();
				}
				//獲取蛇的第一個點
				Point p=list.getFirst().getLocation();
				switch(key) {//37表示前行
				case 37:
					p.x=p.x-10;	
					break;
				case 38:
					p.y=p.y-10;	
					break;
				case 39:
					p.x=p.x+10;
					break;
				case 40:
					p.y=p.y+10;
					break;
					
				}
				//判斷遊戲結束的兩種方法
				//1.蛇超出了邊界	2.蛇頭碰到蛇的身體
				if(p.x<0||p.x>390||p.y<0||p.y>390||list.contains(p)) {//在上面的時候點就已經定位到50,50
					JOptionPane.showMessageDialog(null, "遊戲結束");
					break;
				}
				list.addFirst(p);
				//當蛇喫掉食物後 馬上生成新的食物 自身變長
				if(p.equals(point)) {
					int x=(int)(Math.random()*40)*10;
					int y=(int)(Math.random()*40)*10;
					point.setLocation(x, y);
				}else {
					//刪除最後一個點
					list.removeLast();
				}
				//調用畫的方法
				Snake.this.repaint();
			}
		}
		
	}
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
			new Snake();
	}

}


這個遊戲還有很多沒有完善的,比如計分板,排行榜,暫停按鍵,背景音樂,隨機生成的食物會不會出現在蛇的身體上等等,嗯這裏就當分享學習啦O(∩_∩)O哈哈~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章