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

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定