java贪吃蛇_自己动手丰衣足食写java贪吃蛇

2023-10-06 23:30

本文主要是介绍java贪吃蛇_自己动手丰衣足食写java贪吃蛇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

工作越来越忙了,没有多少时间看书学习了,下班挤出时间写一个贪吃蛇的小游戏。当然还有许多瑕疵和不足,权当萌新学习交流之用。(吐槽:当年家人为什么要阻挡我学习计算机,报什么鬼会计。话说有没有自学编程的一起交流交流)

这个贪吃蛇有以下几个类:

GameFrame(主游戏窗口类)

StartPanel(开始界面)

游戏开始界面:

1279777-20180713164633314-374118020.png

3.GameHelp(上图的帮助)

4.Info(上图的关于)

5.OerationList(游戏运行后右侧信息栏,不要在意类名,打错了没改-。-)

游戏运行画面如下:

1279777-20180713165127018-632712259.png

6.Location(坐标类,必要时还会记录信息)

7.Snake(蛇的类,里面包含一个内部类,方向枚举类OritentionEum)

8.Food(食物类)

1.GameFrame类代码如下:

package贪吃蛇;importjava.awt.Canvas;importjava.awt.Color;importjava.awt.Font;importjava.awt.Frame;importjava.awt.Graphics;importjava.awt.Image;importjava.awt.event.KeyAdapter;importjava.awt.event.KeyEvent;importjava.awt.event.WindowAdapter;importjava.awt.event.WindowEvent;import贪吃蛇.Snake.OritentionEum;//游戏的主窗口

public classGameFrame {private Frame f ; //其实GameFrame直接继承Frame窗口就好

private int fLocationX = 300;private int fLocationY = 50;private int fWidth = 450; //窗口宽

private int fHeight=450; //窗口高

private StartPanel sp; //开始界面Panel

private GameCanvas gc; //贪吃蛇画布

private OerationList ol; //相关信息

private int rate = 5;privateSnake sk ;privateFood fd;//窗口初始化

public voidframeinit() {

f= new Frame("游戏窗口");

f.setLayout(null); //不使用布局管理,Panel用绝对定位

sp = new StartPanel(this).panelInit();//sp =sp.panelInit();

sp.setBounds(fWidth/3, 100, fWidth/3, fHeight/2); //这个是相对于sp的上一级的component的

f.add(sp);this.setAtt(fLocationX,fLocationY);

}//窗口的属性,单独拿出来,在切换到游戏运行时还要用

public void setAtt(int x,inty) {if(f!=null) {

f.addWindowListener(newWindowAdapter() {public voidwindowClosing(WindowEvent e) {

System.exit(0);

}

});

f.setLocation(x, y);//设置组件在桌面显示的位置

f.setSize(fWidth, fHeight); //设置组件的大小 ,也可用setBounds同时设置位置和大小

f.setVisible(true);

}

}//游戏开始窗口

public voidcreateGame() {

f.setVisible(false);int x=f.getX();int y =f.getY();

f= new Frame("贪吃蛇游戏开始");

sk= new Snake(); //蛇

fd = newFood();this.setAtt(x,y); //为了随时更新位置

f.setLayout(null);

gc= newGameCanvas();

gc.canvasInit();//所以

gc.setBounds(0, 0, fWidth*2/3, fHeight); //gc宽度为300,高度为450

gc.addKeyListener(newKeyAdapter() {public voidkeyPressed(KeyEvent e) {switch(e.getKeyCode()) {case KeyEvent.VK_UP: sk.setOritention(OritentionEum.UP);break;case KeyEvent.VK_DOWN: sk.setOritention(OritentionEum.DOWN);break;case KeyEvent.VK_LEFT: sk.setOritention(OritentionEum.LEFT);break;case KeyEvent.VK_RIGHT: sk.setOritention(OritentionEum.RIGHT);break;

}

}

});

gc.setFocusable(true); //画布获取焦点

f.add(gc);

ol= newOerationList().listInit();

ol.setBounds(310, 75, fWidth/4, fHeight*2/3);

f.add(ol);new updateTimeThread().start(); //更新时间线程

new updateCanvasThread().start();//绘画线程更新

}public intgetWidth() {returnf.getWidth();

}public intgetHeight() {returnf.getHeight();

}public int getX() { //返回当前窗口的X坐标

returnf.getX();

}public intgetY() {returnf.getY();

}//绘画线程

class updateCanvasThread extendsThread{public voidrun() {while(true) {

gc.repaint();

String sp=ol.getSpeed();try{switch(sp) {case "一级" : Thread.sleep(100);break;case "二级" : Thread.sleep(300);break;case "三级" : Thread.sleep(500);break;

}

}catch(Exception e) {e.printStackTrace();}

}

}

}//更新界面线程

class updateTimeThread extendsThread{public voidrun() {while(true) {try{

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

ol.updateTime();

}

}

}//画布

class GameCanvas extendsCanvas{publicGameCanvas canvasInit() {this.setVisible(true);return this;

}public voidupdate(Graphics g) {

Image img= this.createImage(fWidth*2/3,fHeight); //不能直接创建Image对象

Graphics gg =img.getGraphics();

gg.setColor(Color.GRAY);//灰色

gg.fillRect(0, 0, fWidth*2/3, fHeight);

gg.setColor(Color.BLACK);

gg.drawRect(10, 50, 250, 350); //起点10,,50,宽 250 高350 70行 50列的矩阵

if(!sk.crashed()) {if(sk.eatFood(fd)) { //蛇如果吃到食物就尾部增长

fd.updateFood();

sk.growTail();

ol.updateScore();

}

sk.drawSnake(gg,rate);//画蛇的时候传入一个rate来控制大小

fd.drawFood(gg, rate);

}else { //游戏结束画面

gg.setFont(new Font("微软雅黑",2,15)); //设置字体

gg.setColor(Color.WHITE);

gg.fillRect(60, 175, 150, 40);

gg.setColor(Color.RED);

gg.drawString("游戏结束 得分"+ol.getScore(), 80 , 200);

}

g.drawImage(img,0, 0, this);

paint(g);

}public voidpaint(Graphics g) {

}

}public static voidmain(String[] args) {

GameFrame game= newGameFrame();

game.frameinit();

}

}

2.startpanel代码如下:

package贪吃蛇;importjava.awt.Button;importjava.awt.GridLayout;//panel是容器,默认为FlowLayout布局,不能独立存在//该Panel主要容纳三个button,分别是 开始游戏 帮助 关于//Panel最后会被加入Frame//使用了布局管理,就不能使用绝对定位了。

importjava.awt.Panel;

@SuppressWarnings("serial")public class StartPanel extendsPanel{privateButton startGame;privateButton help;privateButton info;private GameHelp gh; //点击帮助按钮弹出的Frame

private Info ifo; //关于的窗口

private GameFrame gf; //与主窗口关联,游戏开始按钮 的时间监听 执行的动作 与其相关

publicStartPanel(GameFrame game) {super();

gf=game;

}publicStartPanel panelInit() {

startGame= new Button("开始游戏");

help= new Button("帮助");//因为 startPanel已经设置了布局管理,所以setSize,setLocation,setBounds就失效了。//给startGame 按钮增加监听,直接用lambda ,ActionListener是个函数式接口

startGame.addActionListener(e->{

gf.createGame();

});//给“帮助”按钮加上点击监听

help.addActionListener(e->{if (gh==null) {

gh= newGameHelp();

gh.helpInit(gf.getX(),gf.getY(),gf.getHeight());}elsegh.helpInit(gf.getX(),gf.getY(),gf.getHeight());

});

info= new Button("关于");//给关于按钮添加监听

info.addActionListener(e->{if (ifo==null) {

ifo= newInfo();

ifo.infoInit(gf.getX(),gf.getY(),gf.getHeight());}elseifo.infoInit(gf.getX(),gf.getY(),gf.getHeight());

});this.setLayout(new GridLayout(3,1,25,25)); //网格布局,三行一列

this.add(startGame);this.add(help);this.add(info);this.setVisible(true);return this;

}

}

3.help和info

package贪吃蛇;importjava.awt.Frame;importjava.awt.Graphics;importjava.awt.event.WindowAdapter;importjava.awt.event.WindowEvent;

@SuppressWarnings("serial")public class GameHelp extendsFrame{public void helpInit(int x,int y,intheight) {this.setBounds(x+height, y, height/2, height/2);this.setName("帮助");this.addWindowListener(newWindowAdapter() {//重写closing方法

public voidwindowClosing(WindowEvent e) {

setVisible(false);//close();//匿名内部类也是内部类,可以直接调用外部类的方法和成员

}

});this.setVisible(true);this.repaint(); //paint方法只能是系统调用,我们只能通过repaint来间接调用paint

}//这里其实应该用一个好的图片(带帮助)直接画上最好

public voidpaint(Graphics g) {

g.drawString("贪吃蛇游戏帮助", 50 , 50);

}

}

package贪吃蛇;//info的窗口

importjava.awt.Frame;importjava.awt.Graphics;importjava.awt.event.WindowAdapter;importjava.awt.event.WindowEvent;

@SuppressWarnings("serial")public class Info extendsFrame{public void infoInit(int x,int y,intheight) {this.setBounds(x+height, y+height/2, height/2,height/2);this.setName("关于");this.addWindowListener(newWindowAdapter() {//重写closing方法

public voidwindowClosing(WindowEvent e) {

Info.this.setVisible(false);//close();//匿名内部类也是内部类,可以直接调用外部类的方法和成员

}

});this.setVisible(true);this.repaint(); //paint方法只能是系统调用,我们只能通过repaint来间接调用paint

}//这里其实应该用一个好的图片(带帮助)直接画上最好

public voidpaint(Graphics g) {

g.drawString("作者:CP", 50 , 50);

}

}

4.location类(如果直接粘贴复制运行的话,注意修改package)

package贪吃蛇;import贪吃蛇.Snake.OritentionEum;public classLocation {//坐标类,不光记录坐标位置,必要的时候还记录方向信息

private intx;private inty;privateOritentionEum oritention;public Location(int x,inty) {this.x =x;this.y=y;

}public Location(int x,inty,OritentionEum oritention) {this(x, y);this.oritention =oritention;

}publicLocation(Location la,OritentionEum oritention) {this(la.getX(), la.getY());this.oritention =oritention;

}public intgetX() {returnx;

}public intgetY() {returny;

}public voidrecordOritention(OritentionEum oritention) {this.oritention =oritention;

}publicOritentionEum getRecordOritention() {return this.oritention;

}

}

5.OerationList类

package贪吃蛇;importjava.awt.Choice;importjava.awt.Font;importjava.awt.GridLayout;importjava.awt.Label;importjava.awt.Panel;importjava.awt.TextField;importjava.time.LocalTime;

@SuppressWarnings("serial")public class OerationList extendsPanel{private Label l = new Label("时间:");private TextField time = new TextField(15);private Label l1 = new Label("得分:");private TextField score = new TextField("0",15);private Label l2 = new Label("速度:");private Choice speed = newChoice();//private LocalTime lt = LocalTime.now();//获取当前时间 ,java8最新时间包Time

publicOerationList listInit() {

l.setFont(new Font("宋体",Font.PLAIN,15));

l1.setFont(new Font("宋体",Font.PLAIN,15));

l2.setFont(new Font("宋体",Font.PLAIN,15));

time.setFont(new Font("宋体",Font.PLAIN,15));

score.setFont(new Font("宋体",Font.PLAIN,15));

speed.setFont(new Font("宋体",Font.PLAIN,15));//游戏速度选择框

speed.add("一级");

speed.add("二级");

speed.add("三级");//时间框显示

this.updateTime();//得分要根据吃食物数量来定//全部加到ol中

this.add(l);this.add(time);this.add(l1);this.add(score);this.add(l2);this.add(speed);//this.setBounds((int)(grWidth*0.75), 0, (int)(grWidth*0.25), grHeight);

this.setLayout(new GridLayout(6,1,0,25)); //6行一列,水平间距50 ,垂直间距60

this.setVisible(true);return this;

}publicString getScore() {returnscore.getText();

}publicString getSpeed() {returnspeed.getSelectedItem();

}public voidupdateScore() {int i =Integer.parseInt(score.getText());

i+=5;

score.setText(String.valueOf(i));

}public voidupdateTime() {

time.setText(LocalTime.now().toString().split("\\.")[0]);//split是用正则表达式的 其中.表示任意字符 所以 .要用两个转义字符才能表示.本身

}

}

6.snake类

package贪吃蛇;importjava.awt.Color;importjava.awt.Graphics;importjava.util.LinkedList;public classSnake {//private int[][] snakeMap = new int[45][30]; 45行30列//将蛇身的坐标加入一个队列,从蛇尾巴开始加

public LinkedList snake = new LinkedList<>();//方向数组,用来确定蛇尾巴的方向 ,每次Frame监听到有效的方向按键,则记录位置并记录方向

public LinkedList oritention = new LinkedList<>();private boolean hasCrawl = true;//初始化数组,

{

snake.add(new Location(2,3)); //First remove

snake.add(new Location(2,4));

snake.add(new Location(2,5));

snake.add(new Location(2,6));

snake.add(new Location(2,7)); //Last 蛇头

}private OritentionEum oe = OritentionEum.RIGHT; //方向默认开始向右

private Location snakeHead =snake.getLast();private boolean isEat = false; //是否吃到//获取蛇身,将蛇尾是否增长计入里面

public LinkedListgetSnake(){this.growTail();returnsnake;

}//获取蛇尾位置

publicLocation getSnakeTail() {returnsnake.getFirst();

}//获取蛇头位置

publicLocation getSnakeHead() {returnsnake.getLast();

}//设置蛇头

public voidsetSnakeHead(Location loc) {this.snakeHead =loc;

}//蛇运动, Location的数组行索引其实对应的是画布的Y坐标

public voidsnakeCrawl() {

OritentionEum oe= this.getHeadOritention();

Location snakeHead= this.getSnakeHead();switch(oe) {case DOWN : snake.addLast(new Location(snakeHead.getX()+1,snakeHead.getY()));break;case UP : snake.addLast(new Location(snakeHead.getX()-1,snakeHead.getY()));break;case RIGHT : snake.addLast(new Location(snakeHead.getX(),snakeHead.getY()+1));break;case LEFT : snake.addLast(new Location(snakeHead.getX(),snakeHead.getY()-1));break;

}

snake.remove();this.hasCrawl = true; //蛇走完一部才设置为true,这样才允许方向的设置

if(!oritention.isEmpty()) {

Location tail= this.getSnakeTail();

Location la= oritention.getFirst(); //蛇头转向的标记点

if(tail.getX() == la.getX() && tail.getY()==la.getY()) { //蛇尾走到拐点

oritention.remove();

}

}

}//画蛇

public void drawSnake(Graphics g,intrate) {

g.setColor(Color.YELLOW);for(Location i: snake) {//g.fillRect(i.getX()*rate, i.getY()*rate, rate, rate);

g.fillRect(i.getY()*rate+10,i.getX()*rate+50, rate, rate);

}this.snakeCrawl();

}//设置方向,方向为右的时候只能设置方向为上下,为上下的时候只能设置方向为左右//设置方向的时候同时将将方向加入方向队列用来对蛇尾方向进行标记//存在一种情况,方向已经设置但是由于线程更新间隔大于按键监听间隔,//所以可能存在当蛇在横着走的时候可能先设置上或者下成功,但这时候绘画线程却没有更新(),在这极短的时间内又重新设置了左或者右//这时候就会发现蛇可能在水平方向来回运动的情况//设置一个标识变量 flag 设置方向的时候将其设置为false,蛇crawl之后设置为true

public voidsetOritention(OritentionEum oe) {if(this.hasCrawl) {

OritentionEum currentOe= this.getHeadOritention(); //获取当前蛇的方向

if(currentOe == OritentionEum.RIGHT || currentOe ==OritentionEum.LEFT) {if(oe==OritentionEum.UP || oe==OritentionEum.DOWN)

{oritention.add(new Location(this.getSnakeHead(),this.getHeadOritention()));this.oe = oe; this.hasCrawl=false;}

}else{if(oe==OritentionEum.RIGHT || oe==OritentionEum.LEFT)

{oritention.add(new Location(this.getSnakeHead(),this.getHeadOritention()));this.oe=oe;this.hasCrawl=false;}

}

}

}//获取当前蛇头的方向

publicOritentionEum getHeadOritention() {returnoe;

}//获取蛇尾方向,方向队列不为空,就按照队列First方向,否则就按照蛇头方向

publicOritentionEum getTailOritention() {if(!oritention.isEmpty()) {

Location la= oritention.getFirst(); //蛇头转向的标记点//Location tail = this.getSnakeTail();

returnla.getRecordOritention();

}else return this.getHeadOritention();

}//蛇吃食物,同时在蛇尾增加长度(需要根据方向来确定增加在哪里)

public booleaneatFood(Food d) {

Location fla=d.getFoodLocation(); //食物坐标

Location sla = this.getSnakeHead(); //蛇头坐标

if(sla.getX()==fla.getX() && fla.getY() ==sla.getY()) {

isEat= true;

d.setEat(true); //更新食物里面是否被吃的状态

return true;

}return false;

}//在蛇尾增加一个单位的长度//如果方向队列为空,则按照当前蛇前进的方向来反向增加//否则就按照蛇尾方向队列oritention的First元素来反向增加蛇尾长度

public voidgrowTail() {if(this.isEat) {

OritentionEum oe= this.getTailOritention();//System.out.println(oe);

Location la = this.getSnakeTail();switch(oe) {case UP: snake.addFirst(new Location(la.getX()+1,la.getY()));break;case DOWN: snake.addFirst(new Location(la.getX()-1,la.getY()));break;case LEFT: snake.addFirst(new Location(la.getX(),la.getY()+1));break;case RIGHT: snake.addFirst(new Location(la.getX(),la.getY()-1));break;

}//增长完后复位

this.isEat = false;

}

}//碰撞游戏结束

public booleancrashed() {

Location la= this.getSnakeHead();int x = la.getX(),y=la.getY();//只要蛇头没撞上就OK//分为撞墙和撞蛇身

if(x>=0 && x<=69 && y>=0 && y<=49) { //在画布范围里

boolean flag = false;for(int i=0;i

Location sla=snake.get(i);if(sla.getX()==x && sla.getY()==y) //蛇与自身碰撞了

flag = true;

}returnflag;

}else return true;

}//蛇运行方向枚举类

enumOritentionEum{//4个枚举方向的枚举实例

UP,DOWN,LEFT,RIGHT;

}public static voidmain(String [] args) {

Snake sk= newSnake();for(Location i : sk.snake) {

System.out.println(i.getX()+" "+i.getY());

}

System.out.println(sk.snake.getLast().getY());

}

}

7.food类

package贪吃蛇;importjava.awt.Color;importjava.awt.Graphics;importjava.util.Random;//定义食物的类,显示和随机生成

public classFood {private boolean iseat = false; //默认没有被吃

Location foodla = new Location(20,20); //食物的初始位置

public void drawFood(Graphics g,intrate) {

g.setColor(Color.RED);

g.fillRect(foodla.getY()*rate+10, foodla.getX()*rate+50, rate, rate);

}//获取食物的坐标

publicLocation getFoodLocation() {returnfoodla;

}//设定食物坐标

public voidsetLocation(Location x) {this.foodla =x;

}//食物是否被吃

public booleanisEat() {returniseat;

}//设定食物是否被吃状态

public void setEat(booleanb) {this.iseat =b;

}//如果食物被吃了,就更新食物坐标,食物坐标在(90,60)的范围且不与蛇身重合

public voidupdateFood() {//这里只是随机产生的坐标,有可能食物在蛇身子上,因为不想用遍历的方式来获取哪些坐标是空白的,有时间记得回来改

Random am = newRandom();

foodla= new Location(am.nextInt(70),am.nextInt(50));

}

}

另:游戏结束会面如下:

9c3c435e550c0d39224e816c10f89dd1.png

工作一年,从x=x+1都理解不了的萌新,到能自己刷leetcode(只是刷了简单级别的67题和几道medium的题),真羡慕那些初中就接触代码的人。自己也在一直补习组成原理、操作系统和网络的相关知识。数据结构也在看,看的是C语言版的,然后自己用java实现栈(链式和数组式),队列,avl树,B树等。希望自己坚持下来,解算法题也是会上瘾的,哈哈。

这篇关于java贪吃蛇_自己动手丰衣足食写java贪吃蛇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/154579

相关文章

JSON字符串转成java的Map对象详细步骤

《JSON字符串转成java的Map对象详细步骤》:本文主要介绍如何将JSON字符串转换为Java对象的步骤,包括定义Element类、使用Jackson库解析JSON和添加依赖,文中通过代码介绍... 目录步骤 1: 定义 Element 类步骤 2: 使用 Jackson 库解析 jsON步骤 3: 添

Java中注解与元数据示例详解

《Java中注解与元数据示例详解》Java注解和元数据是编程中重要的概念,用于描述程序元素的属性和用途,:本文主要介绍Java中注解与元数据的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参... 目录一、引言二、元数据的概念2.1 定义2.2 作用三、Java 注解的基础3.1 注解的定义3.2 内

Java中使用Java Mail实现邮件服务功能示例

《Java中使用JavaMail实现邮件服务功能示例》:本文主要介绍Java中使用JavaMail实现邮件服务功能的相关资料,文章还提供了一个发送邮件的示例代码,包括创建参数类、邮件类和执行结... 目录前言一、历史背景二编程、pom依赖三、API说明(一)Session (会话)(二)Message编程客

Java中List转Map的几种具体实现方式和特点

《Java中List转Map的几种具体实现方式和特点》:本文主要介绍几种常用的List转Map的方式,包括使用for循环遍历、Java8StreamAPI、ApacheCommonsCollect... 目录前言1、使用for循环遍历:2、Java8 Stream API:3、Apache Commons

JavaScript中的isTrusted属性及其应用场景详解

《JavaScript中的isTrusted属性及其应用场景详解》在现代Web开发中,JavaScript是构建交互式应用的核心语言,随着前端技术的不断发展,开发者需要处理越来越多的复杂场景,例如事件... 目录引言一、问题背景二、isTrusted 属性的来源与作用1. isTrusted 的定义2. 为

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在

Java CompletableFuture如何实现超时功能

《JavaCompletableFuture如何实现超时功能》:本文主要介绍实现超时功能的基本思路以及CompletableFuture(之后简称CF)是如何通过代码实现超时功能的,需要的... 目录基本思路CompletableFuture 的实现1. 基本实现流程2. 静态条件分析3. 内存泄露 bug

Java中Object类的常用方法小结

《Java中Object类的常用方法小结》JavaObject类是所有类的父类,位于java.lang包中,本文为大家整理了一些Object类的常用方法,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. public boolean equals(Object obj)2. public int ha

SpringBoot项目中Maven剔除无用Jar引用的最佳实践

《SpringBoot项目中Maven剔除无用Jar引用的最佳实践》在SpringBoot项目开发中,Maven是最常用的构建工具之一,通过Maven,我们可以轻松地管理项目所需的依赖,而,... 目录1、引言2、Maven 依赖管理的基础概念2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机

SpringBoot实现动态插拔的AOP的完整案例

《SpringBoot实现动态插拔的AOP的完整案例》在现代软件开发中,面向切面编程(AOP)是一种非常重要的技术,能够有效实现日志记录、安全控制、性能监控等横切关注点的分离,在传统的AOP实现中,切... 目录引言一、AOP 概述1.1 什么是 AOP1.2 AOP 的典型应用场景1.3 为什么需要动态插