貪喫蛇遊戲:是一條蛇在封閉圍牆裏,圍牆裏隨機出現一個食物,通過按鍵盤四個光標鍵控制蛇向上下左右四個方向移動,蛇頭撞倒食物,則食物被喫掉,蛇身體長一節,接着又出現食物,等待蛇來喫,如果蛇在移動中撞到牆或身體交叉蛇頭撞倒自己身體遊戲結束。
(本文就是隻需要用到一個類就能來實現這個小遊戲,源代碼在文章最後面哦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);
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個元素,那麼會調用n次o.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哈哈~