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

相关文章

Spring @Scheduled注解及工作原理

《Spring@Scheduled注解及工作原理》Spring的@Scheduled注解用于标记定时任务,无需额外库,需配置@EnableScheduling,设置fixedRate、fixedDe... 目录1.@Scheduled注解定义2.配置 @Scheduled2.1 开启定时任务支持2.2 创建

SpringBoot中使用Flux实现流式返回的方法小结

《SpringBoot中使用Flux实现流式返回的方法小结》文章介绍流式返回(StreamingResponse)在SpringBoot中通过Flux实现,优势包括提升用户体验、降低内存消耗、支持长连... 目录背景流式返回的核心概念与优势1. 提升用户体验2. 降低内存消耗3. 支持长连接与实时通信在Sp

Spring Boot 实现 IP 限流的原理、实践与利弊解析

《SpringBoot实现IP限流的原理、实践与利弊解析》在SpringBoot中实现IP限流是一种简单而有效的方式来保障系统的稳定性和可用性,本文给大家介绍SpringBoot实现IP限... 目录一、引言二、IP 限流原理2.1 令牌桶算法2.2 漏桶算法三、使用场景3.1 防止恶意攻击3.2 控制资源

Mac系统下卸载JAVA和JDK的步骤

《Mac系统下卸载JAVA和JDK的步骤》JDK是Java语言的软件开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源,:本文主要介绍Mac系统下卸载JAVA和JDK的相关资料,需... 目录1. 卸载系统自带的 Java 版本检查当前 Java 版本通过命令卸载系统 Java2. 卸载自定

springboot下载接口限速功能实现

《springboot下载接口限速功能实现》通过Redis统计并发数动态调整每个用户带宽,核心逻辑为每秒读取并发送限定数据量,防止单用户占用过多资源,确保整体下载均衡且高效,本文给大家介绍spring... 目录 一、整体目标 二、涉及的主要类/方法✅ 三、核心流程图解(简化) 四、关键代码详解1️⃣ 设置

Java Spring ApplicationEvent 代码示例解析

《JavaSpringApplicationEvent代码示例解析》本文解析了Spring事件机制,涵盖核心概念(发布-订阅/观察者模式)、代码实现(事件定义、发布、监听)及高级应用(异步处理、... 目录一、Spring 事件机制核心概念1. 事件驱动架构模型2. 核心组件二、代码示例解析1. 事件定义

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再