java貪吃蛇游戲編寫代碼
本文實(shí)例為大家分享了java貪吃蛇游戲展示的具體代碼,供大家參考,具體內(nèi)容如下
1、采用MVC(model、view、control)框架模式


2、包和類的關(guān)系樹形圖為:

3、源碼:
package com.huai;
import Java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import com.huai.listener.SnakeListener;
import com.huai.util.Constant;
public class Snake {
//和蛇的監(jiān)聽器有關(guān)
Set<SnakeListener> snakeListener = new HashSet<SnakeListener>();
//用鏈表保存蛇的身體節(jié)點(diǎn)
LinkedList<Point> body = new LinkedList<Point>();
private boolean life = true;
//默認(rèn)速度為400ms
private int speed = 400;
private Point lastTail = null;
private boolean pause = false;
//定義各個(gè)方向
public static final int UP = 1;
public static final int DOWN = -1;
public static final int LEFT = 2;
public static final int RIGHT = -2;
int newDirection = RIGHT;
int oldDirection = newDirection;
public Snake(){
initial();
}
public void initial(){
//先清空所有的節(jié)點(diǎn)
body.removeAll(body);
int x = Constant.WIDTH/2;
int y = Constant.HEIGHT/2;
//蛇的默認(rèn)長(zhǎng)度為7
for(int i = 0; i < 7; i++){
body.add(new Point(x--, y));
}
}
public void setSpeed(int speed){
this.speed = speed;
}
public void setLife(boolean life){
this.life = life;
}
public boolean getLife(){
return this.life;
}
public boolean getPause(){
return this.pause;
}
public void setPause(boolean pause){
this.pause = pause;
}
public void move(){
//蛇移動(dòng)的實(shí)現(xiàn)所采用的數(shù)據(jù)結(jié)構(gòu)為:蛇尾刪除一個(gè)節(jié)點(diǎn),蛇頭增加一個(gè)節(jié)點(diǎn)。
System.out.println("snake move");
if(!(oldDirection + newDirection == 0)){
oldDirection = newDirection;
}
lastTail = body.removeLast();
int x = body.getFirst().x;
int y = body.getFirst().y;
switch(oldDirection){
case UP:
y--;
break;
case DOWN:
y++;
break;
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
}
Point point = new Point(x, y);
body.addFirst(point);
}
//當(dāng)吃到一個(gè)食物的時(shí)候,把刪掉的蛇尾節(jié)點(diǎn)增加回來
public void eatFood(){
System.out.println("snake eat food");
body.addLast(lastTail);
}
public boolean isEatItself(){
for(int i = 2; i < body.size(); i++){
if(body.getFirst().equals(body.get(i))){
return true;
}
}
return false;
}
public void drawMe(Graphics g){
System.out.println("draw snake");
//循環(huán)打印蛇的各個(gè)身體節(jié)點(diǎn)
for(Point p:body){
if(p.equals(body.getFirst())){
//當(dāng)是蛇頭的時(shí)候,就設(shè)置顏色為橘色
g.setColor(Color.orange);
}else{
g.setColor(Color.pink);
}
g.fill3DRect(p.x * Constant.CELL_SIZE, p.y * Constant.CELL_SIZE,
Constant.CELL_SIZE, Constant.CELL_SIZE, true);
}
}
public void changeDirection(int direction){
System.out.println("snake changeDirection");
this.newDirection = direction;
}
//內(nèi)部類,新增一個(gè)游戲線程
public class DriveSnake implements Runnable{ @Override
public void run() {
while(life){
if(!pause){
//只要讓蛇不動(dòng)就可以暫停游戲
move();
}
//監(jiān)聽蛇每次移動(dòng)的情況
for(SnakeListener listener : snakeListener){
listener.snakeMove(Snake.this);
}
try {
Thread.sleep(speed);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void startMove(){
new Thread(new DriveSnake()).start();
}
//增加監(jiān)聽器的方法
public void addSnakeListener(SnakeListener listener){
if(listener != null){
snakeListener.add(listener);
}
}
//返回蛇的第一個(gè)身體節(jié)點(diǎn)
public Point getHead(){
return body.getFirst();
}
//返回蛇的所有身體節(jié)點(diǎn)
public LinkedList<Point> getSnakeBody(){
return this.body;
}
public boolean died(){
this.life = false;
return true;
}
}
package com.huai;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import com.huai.util.Constant;
public class Food {
private int x = 0;
private int y = 0;
//設(shè)置食物的默認(rèn)顏色為紅色
private Color color = Color.red;
public void newFood(Point point){
x = point.x;
y = point.y;
}
//判斷是否被吃到
public boolean isAte(Snake snake){
if(snake.getHead().equals(new Point(x, y))){
System.out.println("food isAte");
return true;
}
return false;
}
public void setFoodColor(Color color){
this.color = color;
}
public Color getFoodColor(){
return this.color;
}
public void drawMe(Graphics g){
System.out.println("draw food");
g.setColor(this.getFoodColor());
g.fill3DRect(x * Constant.CELL_SIZE, y * Constant.CELL_SIZE,
Constant.CELL_SIZE, Constant.CELL_SIZE, true);
}
}
package com.huai;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.LinkedList;
import java.util.Random;
import com.huai.util.Constant;
public class Ground {
//在二維數(shù)組中,當(dāng)為1,表示是磚塊
private int[][] rock = new int[Constant.WIDTH][Constant.HEIGHT];
private boolean drawLine = true;
public boolean isDrawLine() {
return drawLine;
}
public void setDrawLine(boolean drawLine) {
this.drawLine = drawLine;
} public Ground(){
for(int x = 0; x < Constant.WIDTH; x++){
for(int y = 0; y < Constant.HEIGHT; y++){
rock[0][y] = 1;
rock[x][0] = 1;
rock[Constant.WIDTH-1][y] = 1;
rock[y][Constant.HEIGHT-1] = 1;
}
}
}
//打印游戲的網(wǎng)格
public void drawGrid(Graphics g){
for(int x = 2; x < Constant.WIDTH; x++){
g.drawLine(x * Constant.CELL_SIZE, 0, x*Constant.CELL_SIZE,
Constant.CELL_SIZE * Constant.HEIGHT);
}
for(int y = 2; y < Constant.HEIGHT; y++){
g.drawLine(0, y * Constant.CELL_SIZE,
Constant.WIDTH*Constant.CELL_SIZE, y*Constant.CELL_SIZE);
}
}
public void drawMe(Graphics g){
System.out.println("draw ground");
//打印圍墻
g.setColor(Color.pink);
for(int x = 0; x < Constant.WIDTH; x++){
for(int y = 0; y < Constant.HEIGHT; y++){
if(rock[x][y] == 1){
g.fill3DRect(x * Constant.WIDTH, y * Constant.HEIGHT,
Constant.CELL_SIZE, Constant.CELL_SIZE, true);
}
}
}
if(isDrawLine()){
g.setColor(Color.yellow);
this.drawGrid(g);
}
}
//得到一個(gè)隨機(jī)點(diǎn)
public Point getRandomPoint(Snake snake, Thorn thorn){
Random random = new Random();
boolean isUnderSnakebody = false;
boolean isUnderThorn = false;
int x,y = 0;
LinkedList<Point> snakeBody = snake.getSnakeBody();
LinkedList<Point> thorns = thorn.getThorns();
do{
x = random.nextInt(Constant.WIDTH);
y = random.nextInt(Constant.HEIGHT);
for(Point p:snakeBody){
if(x == p.x && y == p.y){
isUnderSnakebody = true;
}
}
for(Point point : thorns){
if(x == point.x && y == point.y){
isUnderThorn = true;
}
}
}while(rock[x][y] == 1 && !isUnderSnakebody && !isUnderThorn);
return new Point(x, y);
}
public boolean isSnakeHitRock(Snake snake){
System.out.println("snack hit rock");
for(int i = 0; i < Constant.WIDTH; i++){
for(int j = 0; j < Constant.HEIGHT; j++){
if(snake.getHead().x == i &&
snake.getHead().y == j && rock[i][j] == 1){
return true;
}
}
}
return false;
}
}
package com.huai
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.LinkedList;
import com.huai.util.Constant;
public class Thorn { int x, y;
private LinkedList<Point> thorns = new LinkedList<Point>();
//返回所有荊棘的鏈表
public LinkedList<Point> getThorns(){
return this.thorns;
}
public void newThorn(Point point){
x = point.x;
y = point.y;
thorns.add(new Point(x, y));
}
public void drawMe(Graphics g){
System.out.println("draw thorns");
for(Point p: thorns){
int[] xb = {p.x*Constant.CELL_SIZE,
(p.x*Constant.CELL_SIZE +Constant.CELL_SIZE/2),
(p.x*Constant.CELL_SIZE+Constant.CELL_SIZE),
(p.x*Constant.CELL_SIZE+Constant.CELL_SIZE/4*3),
(p.x*Constant.CELL_SIZE+Constant.CELL_SIZE),
(p.x*Constant.CELL_SIZE+Constant.CELL_SIZE/2),
p.x*Constant.CELL_SIZE,
(p.x*Constant.CELL_SIZE+Constant.CELL_SIZE/4),
p.x*Constant.CELL_SIZE};
int [] yb = {p.y*Constant.CELL_SIZE,
(p.y*Constant.CELL_SIZE+Constant.CELL_SIZE/4),
p.y*Constant.CELL_SIZE,
(p.y*Constant.CELL_SIZE+Constant.CELL_SIZE/2),
(p.y*Constant.CELL_SIZE+Constant.CELL_SIZE),
(int)(p.y*Constant.CELL_SIZE+Constant.CELL_SIZE*0.75),
(p.y*Constant.CELL_SIZE+Constant.CELL_SIZE),
(p.y*Constant.CELL_SIZE+Constant.CELL_SIZE/2),
p.y*Constant.CELL_SIZE};
g.setColor(Color.darkGray);
g.fillPolygon(xb, yb, 8);
}
}
public boolean isSnakeHitThorn(Snake snake){
for(Point points : thorns){
if(snake.getHead().equals(points)){
System.out.println("hit thorn");
return true;
}
}
return false;
}
}
package com.huai.listener;
import com.huai.Snake;
public interface SnakeListener {
public void snakeMove(Snake snake);
}
package com.huai.util;public class Constant {
public static int CELL_SIZE = 20;
public static int WIDTH = 20;
public static int HEIGHT = 20;
}
package com.huai.view;
import java.awt.Color;
import java.awt.Graphics;import javax.swing.JPanel;import com.huai.Food;
import com.huai.Ground;
import com.huai.Snake;
import com.huai.Thorn;
import com.huai.util.Constant;public class GamePanel extends JPanel{
/**
*
*/
private static final long serialVersionUID = 1L;
Snake snake;
Food food;
Ground ground;
Thorn thorn;
public void display(Snake snake, Food food, Ground ground, Thorn thorn){
this.snake = snake;
this.food = food;
this.ground = ground;
this.thorn = thorn;
System.out.println("display gamePanel");
this.repaint();
}
@Override
protected void paintComponent(Graphics g) {
if(snake != null && food != null && ground != null){
g.setColor(Color.lightGray);
g.fillRect(0, 0, Constant.WIDTH*Constant.CELL_SIZE,
Constant.HEIGHT*Constant.CELL_SIZE);
snake.drawMe(g);
food.drawMe(g);
ground.drawMe(g);
thorn.drawMe(g);
}else{
System.out.println("snake = null || food = null || ground = null");
}
}
}
package com.huai.controller;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;import com.huai.Food;
import com.huai.Ground;
import com.huai.Snake;
import com.huai.Thorn;
import com.huai.listener.SnakeListener;
import com.huai.view.GamePanel;public class Controller extends KeyAdapter implements SnakeListener{
/**
* 整個(gè)游戲的控制類,屬于MVC設(shè)計(jì)框架中的Controller
* 其中包括控制游戲的監(jiān)聽事件和游戲邏輯
*/
Snake snake;
Food food;
Ground ground;
GamePanel gamePanel;
Thorn thorn;
public Controller(){}
//利用構(gòu)造方法初始化對(duì)象
public Controller(Snake snake, Food food, Ground ground, GamePanel gamePanel, Thorn thorn) {
super();
this.snake = snake;
this.food = food;
this.ground = ground;
this.gamePanel = gamePanel;
this.thorn = thorn;
}
@Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_UP:
snake.changeDirection(Snake.UP);
snake.setSpeed(150);
break;
case KeyEvent.VK_DOWN:
snake.changeDirection(Snake.DOWN);
snake.setSpeed(150);
break;
case KeyEvent.VK_LEFT:
snake.changeDirection(Snake.LEFT);
snake.setSpeed(150);
break;
case KeyEvent.VK_RIGHT:
snake.changeDirection(Snake.RIGHT);
snake.setSpeed(150);
break;
case KeyEvent.VK_ENTER:
if(!snake.getPause() && snake.getLife()){
//暫停游戲
snake.setPause(true);;
}else if(!snake.getLife()){
//重新開始游戲
snake.setLife(true);
snake.initial();
snake.changeDirection(Snake.UP);
thorn.getThorns().removeAll(thorn.getThorns());
this.startGame();
}else{
snake.setPause(false);
}
break;
case KeyEvent.VK_L:
//當(dāng)按下L按鈕時(shí),是否顯示游戲網(wǎng)格
if(ground.isDrawLine()){
ground.setDrawLine(false);
}else{
ground.setDrawLine(true);
}
break;
}
}
@Override
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_UP:
snake.setSpeed(400);
break;
case KeyEvent.VK_DOWN:
snake.setSpeed(400);
break;
case KeyEvent.VK_LEFT:
snake.setSpeed(400);
break;
case KeyEvent.VK_RIGHT:
snake.setSpeed(400);
break;
}
}
//這是實(shí)現(xiàn)SnakeListener監(jiān)聽器所Override的方法
@Override
public void snakeMove(Snake snake) {
//顯示snake ,food,ground,和thorn
gamePanel.display(snake, food, ground, thorn);
if(ground.isSnakeHitRock(snake)){
snake.died();
}
if(snake.isEatItself()){
snake.died();
}
if(food.isAte(snake)){
snake.eatFood();
food.newFood(ground.getRandomPoint(snake, thorn));
thorn.newThorn(ground.getRandomPoint(snake, thorn));
}
if(thorn.isSnakeHitThorn(snake)){
snake.died();
}
}
public void startGame(){
snake.startMove();//這個(gè)將會(huì)啟動(dòng)一個(gè)新的線程
food.newFood(ground.getRandomPoint(snake, thorn));
thorn.newThorn(ground.getRandomPoint(snake, thorn));
}
}
package com.huai.game;
import java.awt.BorderLayout;
import java.awt.Color;import javax.swing.JFrame;
import javax.swing.JLabel;import com.huai.Food;
import com.huai.Ground;
import com.huai.Snake;
import com.huai.Thorn;
import com.huai.controller.Controller;
import com.huai.util.Constant;
import com.huai.view.GamePanel;public class Game {
public static void main(String args[]){
Snake snake = new Snake();
Food food = new Food();
GamePanel gamePanel = new GamePanel();
Ground ground = new Ground();
Thorn thorn = new Thorn();
Controller controller = new Controller(snake, food, ground, gamePanel, thorn);
JFrame frame = new JFrame("懷哥的小小蛇兒游戲");
frame.add(gamePanel);
frame.setBackground(Color.magenta);
frame.setSize(Constant.WIDTH*Constant.CELL_SIZE+6,
Constant.HEIGHT*Constant.CELL_SIZE+40);
gamePanel.setSize(Constant.WIDTH*Constant.CELL_SIZE,
Constant.HEIGHT*Constant.CELL_SIZE);
frame.add(gamePanel);
frame.setResizable(false);//不可改變窗口大小
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
gamePanel.addKeyListener(controller);
snake.addSnakeListener(controller);
frame.addKeyListener(controller);
JLabel label1 = new JLabel();
label1.setBounds(0, 400, 400, 100);
label1.setText(" ENTER=>>PAUSE or AGAIN; "
+ " L=>DRAWGRID");
label1.setForeground(Color.BLACK);
frame.add(label1, BorderLayout.SOUTH);
controller.startGame();
}
}
更多精彩游戲,請(qǐng)參考專題《java經(jīng)典小游戲》
更多有趣的經(jīng)典小游戲?qū)崿F(xiàn)專題,分享給大家:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
mybatis解決<foreach>標(biāo)簽不能超過1000的問題
MyBatis是一個(gè)開源的持久層框架,它可以幫助開發(fā)者簡(jiǎn)化數(shù)據(jù)庫操作的編寫,而foreach是MyBatis中的一個(gè)重要標(biāo)簽,用于在SQL語句中進(jìn)行循環(huán)操作,本文主要給大家介紹了mybatis解決<foreach>標(biāo)簽不能超過1000的問題,需要的朋友可以參考下2024-05-05
關(guān)于@Autowired注入依賴失敗的問題及解決
這篇文章主要介紹了關(guān)于@Autowired注入依賴失敗的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
Java傳入用戶名和密碼并自動(dòng)提交表單實(shí)現(xiàn)登錄到其他系統(tǒng)的實(shí)例代碼
這篇文章主要介紹了Java傳入用戶名和密碼并自動(dòng)提交表單實(shí)現(xiàn)登錄到其他系統(tǒng),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-01-01
SpringCloud?Gateway詳細(xì)分析實(shí)現(xiàn)負(fù)載均衡與熔斷和限流
這篇文章主要介紹了SpringCloud?Gateway實(shí)現(xiàn)路由轉(zhuǎn)發(fā),負(fù)載均衡,熔斷和限流,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07
MAC上IntelliJ IDEA的svn無法保存密碼解決方案
今天小編就為大家分享一篇關(guān)于MAC上IntelliJ IDEA的svn無法保存密碼解決方案,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-10-10
Mybatis Order by動(dòng)態(tài)參數(shù)防注入方式
這篇文章主要介紹了Mybatis Order by動(dòng)態(tài)參數(shù)防注入方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
springboot構(gòu)建docker鏡像并推送到阿里云
本文主要介紹了springboot構(gòu)建docker鏡像并推送到阿里云,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05

