在我们学习java的时候,为了提高我们的兴趣,我们经常会使用所学到的知识去做一些小游戏,这篇blog就介绍了一个经典而且好理解的小游戏-贪吃蛇。

一、使用知识Jframe

GUI

双向链表

线程

二、使用工具IntelliJ IDEA

jdk 1.8

三、开发过程

3.1素材准备

首先在开发之前应该准备一些素材,已备用,我主要找了一个图片以及一段优雅的音乐。

3.2 开发过程

3.2.1 创建项目首先进入idea首页 open一个你想放项目的文件夹

进入之后右键文件名 new 一个新的Directory——Snake

把准备好的素材复制到文件中

继续创建目录 src/Sanke

选中src Mark Directory as — Souces 把src添加为根目录

3.2.2 页面设计创建java Class 文件 Snake - new - java class SnakeName 接下来的时候会对这个SnakeName.java里面的代码不停完善

首先设置窗口格式package Sanke;import javax.swing.*;/** * @author Swyee **/public class SnakeGame extends JFrame {

SnakeGame(){

this.setBounds(100, 50, 700, 500);//设置窗口大小        this.setLayout(null);//更改layout 以便添加组件        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭窗口的状态        this.setResizable(false);//窗口不可以改变大小        this.setVisible(true);//设置焦点状态为true    }

public static void main(String[] args) {

new SnakeGame();

}}

继续创建新的文件 SnakeGridpackage Sanke;import java.awt.*;/** * @author Swyee **/public class SnakeGrid extends Panel {

SnakeGrid(){

this.setBounds(0, 0, 700, 400);

this.setBackground(Color.black);设置背景颜色

}}将页面引用到SnakeGame.java中package Sanke;import javax.swing.*;/** * @author Swyee **/public class SnakeGame extends JFrame {

SnakeGrid snakeGrid= new SnakeGrid();

SnakeGame(){

this.setBounds(100, 50, 700, 500);//设置窗口大小        this.setLayout(null);//更改layout 以便添加组件        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭窗口的状态        this.setResizable(false);//窗口不可以改变大小        this.add(snakeGrid);

this.setVisible(true);//设置焦点状态为true    }

public static void main(String[] args) {

new SnakeGame();

}}

运行样式

设置背景图片 背景音乐

在SnakeGrid.java中增加Music方法 设置画笔 绘图package Sanke;import java.applet.Applet;import java.applet.AudioClip;import java.awt.*;import java.io.File;import java.net.MalformedURLException;import java.net.URI;import java.net.URL;import javax.swing.ImageIcon;import javax.swing.JOptionPane;import javax.swing.JPanel;/** * @author Swyee **/public class SnakeGrid extends JPanel {

ImageIcon image = new ImageIcon("Snake/sky.jpg");//图片文件地址    File f= new File("Snake/music.wav");//音乐文件地址    SnakeGrid(){

this.setBounds(0, 0, 700, 400);

this.setBackground(Color.black);

}

/**     * 设置画笔     * @param g     */

@Override

public void paint(Graphics g) {

super.paint(g);

image.paintIcon(this, g, 0, 0); //设置背景图片    }

//读取音乐文件    void Music(){

try {

URI uri = f.toURI();

URL url = uri.toURL();

AudioClip aau= Applet.newAudioClip(url);

aau.loop();

} catch (MalformedURLException e) {

// TODO Auto-generated catch block            e.printStackTrace();

}

}}

在SnakeName中调用package Sanke;import javax.swing.*;/** * @author Swyee **/public class SnakeGame extends JFrame {

SnakeGrid snakeGrid= new SnakeGrid();

SnakeGame(){

this.setBounds(100, 50, 700, 500);//设置窗口大小        this.setLayout(null);//更改layout 以便添加组件        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭窗口的状态        this.setResizable(false);//窗口不可以改变大小        this.add(snakeGrid);

//设置焦点        snakeGrid.setFocusable(true);

snakeGrid.requestFocus();

snakeGrid.Music();//调用打开音乐的方法        this.setVisible(true);//设置焦点状态为true    }

public static void main(String[] args) {

new SnakeGame();

}}

呈现

3.23 画蛇

蛇的身体将会有双向链表组成,双向链表能记录一个节点的上一个节点和下一个节点。蛇的移动其实就是节点的变化,从而达到一种移动的视觉。新建java Snake 创建节点package Sanke;import java.awt.Graphics;public class Snake {

public static final int span=20;//间距public static final String up="u";

public static final String down="d";

public static final String left="l";

public static final String right="r";

class Node{

int row;

int col;

String dir;//方向Node next;

Node pre;

Node(int row,int col,String dir){

this.row = row;

this.col = col;

this.dir = dir;

}

public void draw(Graphics g) {

g.fillOval(col*span, row*span, span,span);

}

}}画蛇

在snake里面增加draw()方法/*把蛇画出来 */

public void draw(Graphics g) {

g.setColor(Color.yellow);

for(Node n=head;n!=null;n=n.next){

n.draw(g);

g.setColor(Color.green);

}

}

在SnakeGrid.java中创建蛇Snake snake = new Snake();//创建蛇

并在paint中调用snake.draw(g);/**     * 设置画笔     * @param g     */

@Override

public void paint(Graphics g) {

super.paint(g);

image.paintIcon(this, g, 0, 0); //设置背景图片        snake.draw(g);

}控制蛇的移动

在snake中增加键盘调用的方法:/*调用键盘的上下左右键head.dir记录现在操作的是什么按钮,从而更改蛇的状态向上移送时,下键失效,其他四个方向也是如此判断 */

public void keyboard(KeyEvent e) {

switch(e.getKeyCode()){

case KeyEvent.VK_UP:

if(head.dir.equals(down)){

break;

}

head.dir=up;

break;

case KeyEvent.VK_DOWN:

if(head.dir.equals(up)){

break;

}

head.dir=down;

break;

case KeyEvent.VK_LEFT:

if(head.dir.equals(right)){

break;

}

head.dir=left;

break;

case KeyEvent.VK_RIGHT:

if(head.dir.equals(left)){

break;

}

head.dir=right;

break;

default:

break;

}

}

增加头部的方法/*增加头部不管移动哪个方向都是在相应位置增加一个节点 */

public void addHead(){

Node node = null;

switch (head.dir){

case "l":

node = new Node(head.row,head.col-1,head.dir);

break;

case "r":

node = new Node(head.row,head.col+1,head.dir);

break;

case "u":

node = new Node(head.row-1,head.col,head.dir);

break;

case "d":

node = new Node(head.row+1,head.col,head.dir);

break;

default:

break;

}

node.next=head;

head.pre=node;

head=node;

}

删除尾部的方法/*删除尾部 删除最后一个节点 */public void deleteTail(){

tail.pre.next=null;

tail=tail.pre;}

增加move的方法/*增加move方法 一增一减,实现蛇的移动 */

public void move() {

addHead();

deleteTail();

}

在SnakeGrid中创建一个线程类,用来执行蛇的移动方法class SnakeThread extends Thread{

@Override

public void run() {

while (true){

try {

Thread.sleep(300);//沉睡300ms 用来控制蛇的移动速度        } catch (InterruptedException e) {

e.printStackTrace();

}

repaint();//每次沉睡完之后都执行一下repaint()方法,重新绘画        }

}

print方法中调用remove 在SnakeGrid()创建键盘监听事件:package Sanke;import java.applet.Applet;import java.applet.AudioClip;import java.awt.*;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.io.File;import java.net.MalformedURLException;import java.net.URI;import java.net.URL;import javax.swing.ImageIcon;import javax.swing.JOptionPane;import javax.swing.JPanel;/** * @author Swyee **/public class SnakeGrid extends JPanel {

Snake snake = new Snake();//创建蛇    ImageIcon image = new ImageIcon("Snake/sky.jpg");//图片文件地址    File f= new File("Snake/music.wav");//音乐文件地址    SnakeThread snakeThread = new SnakeThread();

SnakeGrid(){

this.setBounds(0, 0, 700, 400);

this.setBackground(Color.black);

snakeThread.start();

this.addKeyListener(new KeyAdapter() {

@Override

public void keyPressed(KeyEvent e) {

snake.keyboard(e);

}

});

}

/**     * 设置画笔     * @param g     */

@Override

public void paint(Graphics g) {

super.paint(g);

image.paintIcon(this, g, 0, 0); //设置背景图片        snake.move();//蛇移动        snake.draw(g);

}

//读取音乐文件    void Music(){

try {

URI uri = f.toURI();

URL url = uri.toURL();

AudioClip aau= Applet.newAudioClip(url);

aau.loop();

} catch (MalformedURLException e) {

// TODO Auto-generated catch block            e.printStackTrace();

}

}

class SnakeThread extends Thread{

@Override

public void run() {

while (true){

try {

Thread.sleep(300);//沉睡300ms 用来控制蛇的移动速度        } catch (InterruptedException e) {

e.printStackTrace();

}

repaint();//每次沉睡完之后都执行一下repaint()方法,重新绘画        }

}}}

执行main方法可以看到可以通过键盘进行控制移动了

3.24创建蛇的食物

增加食物的实例 以及画食物的方法 反映食物坐标的方法 新建Food.javapackage Sanke;import java.awt.*;public class Food {

int row;

int col;

Food(){

row = 10;//创建食物的大小col  =10;

}

public void repearShow(){

row = (int)(Math.random()*18);//生成随机数 乘以食物的大小可以得到坐标col = (int)(Math.random()*32);

}

public void draw(Graphics g) {//把食物画出来g.setColor(Color.red);

g.fillRect(col*20, row*20, 20, 20);//表示坐标

}

public Rectangle getCoordinates(){

return new Rectangle(col*20,row*20,20,20);//获得食物的坐标

}}

修改Snake.java 增加判断蛇头位置的方法,修改午无参构造方法,改为有参构造,把food添加进来 修改move方法package Sanke;import java.awt.*;import java.awt.event.KeyEvent;/** * @author Swyee */public class Snake {

public static final int span=20;//间距public static final String up="u";

public static final String down="d";

public static final String left="l";

public static final String right="r";

Node body;//蛇的身体Node head;//蛇的头部Node tail;//蛇的头部Food food;

Snake(Food food){

body = new Node(5,20,left);

head = body;

tail = body;

this.food=food;

}

class Node{

int row;

int col;

String dir;//方向Node next;

Node pre;

Node(int row,int col,String dir){

this.row = row;

this.col = col;

this.dir = dir;

}

public void draw(Graphics g) {

g.fillOval(col*span, row*span, span,span);//坐标

}

}

/*把蛇画出来 */

public void draw(Graphics g) {

g.setColor(Color.yellow);

for(Node n=head;n!=null;n=n.next){

n.draw(g);

g.setColor(Color.green);

}

}

/*调用键盘的上下左右键head.dir记录现在操作的是什么按钮,从而更改蛇的状态向上移送时,下键失效,其他四个方向也是如此判断 */

public void keyboard(KeyEvent e) {

switch(e.getKeyCode()){

case KeyEvent.VK_UP:

if(head.dir.equals(down)){

break;

}

head.dir=up;

break;

case KeyEvent.VK_DOWN:

if(head.dir.equals(up)){

break;

}

head.dir=down;

break;

case KeyEvent.VK_LEFT:

if(head.dir.equals(right)){

break;

}

head.dir=left;

break;

case KeyEvent.VK_RIGHT:

if(head.dir.equals(left)){

break;

}

head.dir=right;

break;

default:

break;

}

}/*增加头部 */

public void addHead(){

Node node = null;

switch (head.dir){

case "l":

node = new Node(head.row,head.col-1,head.dir);

break;

case "r":

node = new Node(head.row,head.col+1,head.dir);

break;

case "u":

node = new Node(head.row-1,head.col,head.dir);

break;

case "d":

node = new Node(head.row+1,head.col,head.dir);

break;

default:

break;

}

node.next=head;

head.pre=node;

head=node;

}/*删除尾部 */public void deleteTail(){

tail.pre.next=null;

tail=tail.pre;}/*增加move方法 */

public void move() {

addHead();

if(this.getSnakeRectangle().intersects(food.getCoordinates())){//当蛇头与食物重合的时候 蛇吃食物 食物刷新,不再删除尾巴,达到一种蛇增长的要求

food.repearShow();

}else{

deleteTail();

}

}

public Rectangle getSnakeRectangle(){//获取蛇头的坐标

return new Rectangle(head.col*span,head.row*span,span,span);

}}

在修改snakegrid.java 贪吃蛇的功能就基本实现了Food food = new Food();

Snake snake = new Snake(food);//创建蛇    ImageIcon image = new ImageIcon("Snake/sky.jpg");//图片文件地址    File f= new File("Snake/music.wav");//音乐文件地址    SnakeThread snakeThread = new SnakeThread();

@Override

public void paint(Graphics g) {

super.paint(g);

image.paintIcon(this, g, 0, 0); //设置背景图片        snake.move();//蛇移动        snake.draw(g);

food.draw(g);

}

3.2.5增加蛇的存活状态

在Snake中增加蛇的存活状态,每一次移动都判断下是否存活,修改SnakeGrid的线程,执行时进行判断是否存活public void DeadOrLive(){//超出边框范围 蛇头撞到身体 游戏结束if(head.row<0 || head.row>rows-1 || head.col<0 ||head.col>cols){

islive=false;

}

for(Node n=head.next;n!=null;n=n.next){

if(n.col==head.col && n.row==head.row){

islive=false;

}

}

}

public void move() {

addHead();

if(this.getSnakeRectangle().intersects(food.getCoordinates())){//当蛇头与食物重合的时候 蛇吃食物 食物刷新,不再删除尾巴,达到一种蛇增长的要求

food.repearShow();

}else{

deleteTail();

}

DeadOrLive();//每移动一步都要判断一下是否存活}

class SnakeThread extends Thread{

boolean flag = true;

@Override

public void run() {

while (Snake.islive && flag) {

try {

Thread.sleep(300);

} catch (InterruptedException e) {

// TODO Auto-generated catch block                    e.printStackTrace();

}

if (Snake.islive ) {

repaint();

}

}

if (!flag == false) {

JOptionPane.showMessageDialog(SnakeGrid.this, "游戏结束");

}

}

3.2.6 增加按钮最后的时候,给这个小游戏增加几个按钮,用来实现暂停开始

新建Button.javapackage Sanke;import javax.swing.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;public class Button extends JPanel{

public static boolean isMove=true;//表示运行状态

SnakeGrid snakeGrid;

Button(SnakeGrid snakeGrid){

this.snakeGrid=snakeGrid;

this.setBounds(0, 400, 700, 100);

JButton jb1 = new JButton("暂停游戏");

JButton jb2 = new JButton("继续游戏");

JButton jb3 = new JButton("重新游戏");

this.add(jb1);

this.add(jb2);

this.add(jb3);

jb1.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

isMove=false;

}

});

jb2.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

isMove=true;

snakeGrid.setFocusable(true);

snakeGrid.requestFocus();

}

});

jb3.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {//重新创建蛇等 重新开始游戏snakeGrid.snakeThread.stopThread();

Food food = new Food();

snakeGrid.food=food;

snakeGrid.snake=new Snake(food);

Snake.islive=true;

isMove=true;

SnakeGrid.SnakeThread st = snakeGrid.new SnakeThread();

snakeGrid.snakeThread=st;

st.start();

snakeGrid.setFocusable(true);

snakeGrid.requestFocus();

}

});

}}

再修改SnakeGrid中的threadpackage Sanke;import java.applet.Applet;import java.applet.AudioClip;import java.awt.*;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.io.File;import java.net.MalformedURLException;import java.net.URI;import java.net.URL;import javax.swing.ImageIcon;import javax.swing.JOptionPane;import javax.swing.JPanel;/** * @author Swyee **/public class SnakeGrid extends JPanel {

Food food = new Food();

Snake snake = new Snake(food);//创建蛇    ImageIcon image = new ImageIcon("Snake/sky.jpg");//图片文件地址    File f= new File("Snake/music.wav");//音乐文件地址    SnakeThread snakeThread = new SnakeThread();

SnakeGrid(){

this.setBounds(0, 0, 700, 400);

this.setBackground(Color.black);

snakeThread.start();

this.addKeyListener(new KeyAdapter() {

@Override

public void keyPressed(KeyEvent e) {

snake.keyboard(e);

}

});

}

/**     * 设置画笔     * @param g     */

@Override

public void paint(Graphics g) {

super.paint(g);

image.paintIcon(this, g, 0, 0); //设置背景图片        snake.move();//蛇移动        snake.draw(g);

food.draw(g);

}

//读取音乐文件    void Music(){

try {

URI uri = f.toURI();

URL url = uri.toURL();

AudioClip aau= Applet.newAudioClip(url);

aau.loop();

} catch (MalformedURLException e) {

// TODO Auto-generated catch block            e.printStackTrace();

}

}

class SnakeThread extends Thread{

boolean flag = true;

@Override

public void run() {

while(Snake.islive &&flag){

try {

Thread.sleep(300);

} catch (InterruptedException e) {

// TODO Auto-generated catch block                    e.printStackTrace();

}

if(Snake.islive&& Button.isMove){

repaint();

}

}

if(!flag==false){

JOptionPane.showMessageDialog(SnakeGrid.this, "游戏结束");

}

}

public void stopThread(){

flag=false;

}

}}

在主页面中把按钮添加上去package Sanke;import javax.swing.*;/** * @author Swyee **/public class SnakeGame extends JFrame {

SnakeGrid snakeGrid= new SnakeGrid();

Button button = new Button(snakeGrid);

SnakeGame(){

this.setBounds(100, 50, 700, 500);//设置窗口大小        this.setLayout(null);//更改layout 以便添加组件        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭窗口的状态        this.setResizable(false);//窗口不可以改变大小        this.add(snakeGrid);

this.add(button);

//设置焦点        snakeGrid.setFocusable(true);

snakeGrid.requestFocus();

snakeGrid.Music();//调用打开音乐的方法        this.setVisible(true);//设置焦点状态为true    }

public static void main(String[] args) {

new SnakeGame();

}}

到这里这个小游戏就全部做完了,当然也可以在其基础上增加其他功能

也可以把这个小游戏打成jar包的形式进行运行,将打好的jar包和资源文件放在同一个目录下,即可正常运行访问

四、打jar包

源码

最后附上源码链接:

最终幻想游戏java_Java简单实现贪吃蛇经典小游戏(附源代码)相关推荐

  1. 隐藏窗口 java swing_Java简单实现贪吃蛇经典小游戏(附源代码)

    在我们学习java的时候,为了提高我们的兴趣,我们经常会使用所学到的知识去做一些小游戏,这篇blog就介绍了一个经典而且好理解的小游戏-贪吃蛇. 一.使用知识 Jframe GUI 双向链表 线程 二 ...

  2. 贪食蛇php,贪吃蛇网页小游戏的代码

    贪吃蛇网页小游戏的代码 ::selection { color:#FFFFFF; background:transparent; } ::-moz-selection { color:#FFFFFF; ...

  3. 用前端技术实现贪吃蛇的小游戏

    用前端技术实现贪吃蛇的小游戏 前言 游戏功能 游戏设计 游戏主页代码 游戏中的js代码(snake.js) 游戏运行界面 前言 周末大热天窝在家里无聊,想温习一下前端开发,所以用javascript ...

  4. 100行实现《贪吃蛇》小游戏详解(Qt)

    目录 游戏说明 游戏效果展示 游戏代码详解 ​关键数据结构 初始化游戏界面 游戏部分 提示部分 蛇逻辑 小蛇的初始化 边界判断 蛇吃食物判断 随机生成食物 是否撞到自己 小蛇的移动 游戏主体逻辑 定时 ...

  5. 贪吃蛇html网页小游戏,网页贪吃蛇HTML5小游戏制作

    贪吃蛇是以前我们经常在手机里玩的一个小游戏,现在要是把它搬到网页上也会让人更回味.这是一款非常有趣的HTML5响应式网页贪吃蛇小游戏.在游戏中你可以使用键盘的上下左右来控制蛇的运动方向.现在要列出的是 ...

  6. javaswing 贪吃蛇双人小游戏

    游戏截图 代码 Java14写的哦低版本会报错 文件列表 package Sys;import javax.swing.*; import java.awt.*; import java.awt.ev ...

  7. 在家用c++实现贪吃蛇——c++小游戏

    伪代码: 地图为二位数组 int main(){ 死循环 刷新地图 生成水果 获取键盘 移动头部 判定死亡.吃到水果 if(没有吃到水果) {移动尾部 } 等待指定秒数 清屏 } 首先,我们因该可以把 ...

  8. 我要糖糖糖HTML5小游戏,一些简单的团建破冰小游戏「15个」

    导读:1.破冰小游戏[警察抓小偷] 两组人成两排,面对面站立,互相伸出手,交错,互击.喊1左边队拍右边队员的手.喊2右边队拍左边队.喊3停住不动.做错的做蹲起. 2.破冰小游戏[ 1.破冰小游戏[警察 ...

  9. 五子棋游戏的简单实现(Java入门小游戏手把手教学)

    ##五子棋* 需求分析 完成一个简单的五子棋游戏 界面 窗体[带标题和背景] 棋盘[棋盘,棋子] 图标[白子,黑子,重来] 业务 页面展示 选择先走的棋子 落子开始下棋 黑白切换 判断输赢,如何判断赢 ...

最新文章

  1. python加颜色_Python 给屏幕打印信息加上颜色的实现方法
  2. Python-EEG处理和事件相关电位(ERP)
  3. DCMTK:可加载的DICOM数据字典中的字典条目
  4. 批量打印pdf并合并_CAD批量打印攻略
  5. ASP.NET Core依赖注入解读使用Autofac替代实现
  6. python open encoding_Python文件操作
  7. 自动驾驶帆船,有史以来第一次成功横渡大西洋
  8. Spring Cloud Config客户端使用
  9. type python django models_Python菜鸟之路:Django ModelForm的使用
  10. 如何将Win7便签添加到桌面快捷方式
  11. 浏览器预览pdf文件名称不对,Java使用iText修改Pdf文件的标题属性,自定义预览文件名
  12. Web前端-HTML
  13. 手动安装 Spyder 4.0 beta 版
  14. 输入法打出的英文间隔很大
  15. flash chart(amCharts的破解)
  16. [免费视频教程]UI自动化测试之Jenkins配置教程
  17. 如何高效读取计费规则等热数据——分布式缓存
  18. PC端抖音HTML布局,抖音有PC端了,终于可以发布无损视频了,支持15min内的作品...
  19. 2017年双十一最全面的大数据分析报告在此!+2018年双十一已经开始,厚昌竞价托管教你如何应对流量流失?+2019年双十一大战一触即发:阿里、京东都有哪些套路和玩法
  20. 【GNN报告】耶鲁大学Rex Ying(应智韬): 双曲表示学习与知识图谱

热门文章

  1. 不知道从哪里找数据?这一篇,都解决(持续更新)
  2. [转]程序员常用不常见很难得的地址大全,转来自己用
  3. HTTP协议漫谈 C#实现图(Graph) C#实现二叉查找树 浅谈进程同步和互斥的概念 C#实现平衡多路查找树(B树)...
  4. Java8 JVM参数解读
  5. bottle学习之JSON模块
  6. 18种植物放入室内的功效
  7. failed to req API:/nacos/v1/ns/instance after all servers([127.0.0.1:8848]) tried: ErrCode:503, ErrM
  8. 怎么用u盘制作pe系统启动盘
  9. win7电脑恢复系统设置或计算机点不了,Win7系统出现故障怎么恢复出厂设置?
  10. 【LT4320的三相理想整流】