탐욕스러운 뱀의 Java 구현 코드 예
며칠의 자유시간을 이용해 뱀을 써보세요.
아래 코드에 질문이나 제안사항이 있으면 언제든지 메시지를 남겨주세요!
다운로드 주소(1포인트 필요, 포인트 사용을 원치 않으시면 아래 코드를 복사하시면 됩니다)
보드 클래스:
import java.awt.EventQueue;import java.awt.KeyEventPostProcessor;import javax.swing.*;import java.awt.*;import java.awt.event.KeyEvent;/** * * @author QuinnNorris * * */public class Board { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub // 开启一个线程,所有的Swing组件必须由事件分派线程进行配置,线程将鼠标点击和按键控制转移到用户接口组件。 EventQueue.invokeLater(new Runnable() { // 匿名内部类,是一个Runnable接口的实例,实现了run方法 public void run() { JFrame frame = new BoardFrame(); // 创建下面自己定义的SimpleFrame类对象,以便于调用构造器方法 frame.setTitle("Retro Snake"); // 设置标题 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 选择当用户关闭框架的时候进行的操作 ,在有些时候需要将窗口隐藏,不能直接退出需要用到这个方法 frame.setVisible(true); // 将窗口可见化,这样以便用户在第一次看见窗口之前我们能够向其中添加内容 } }); } } class BoardFrame extends JFrame { private Snake snk; // 在我们绘图的工作区域创建一个蛇对象引用 public static final int INTERVAL = Configure.INTERVAL; // 需要用到的睡眠间隔,决定了蛇的移动速度 // 从Configure文件中读取的游戏时间间隔 public BoardFrame() { snk = new Snake(); snk.setFood(new Food().getSnake(snk.getSnakeBody())); // 创建一个食物对象,调用getSnake方法判断该食物生成点不在蛇的身体上 // getSnake的返回类型是Food,可以这样直接调用 final KeyboardFocusManager manager = KeyboardFocusManager .getCurrentKeyboardFocusManager(); // 创建一个键盘监听相关类 // 因为我们要在下面开启线程,线程中只能获得final修饰的局部变量,所以这个变量是不可变的 new Thread(new Runnable() { // 开启线程来不断重绘蛇 // 之所以采用多线程,是为了让代码更加灵活,如果要改编成双人贪吃蛇更方便 public void run() { while (true) { BoardComponent bc = new BoardComponent(); bc.setSnake(snk); add(bc); // 创建JComponent的实例,将上面创建的蛇对象传入 MyKeyEventPostProcessor mke = new MyKeyEventPostProcessor(); mke.setSnk(snk); manager.addKeyEventPostProcessor(mke); // 创建监听键盘的实例,同样将蛇对象传入 try { Thread.sleep(INTERVAL); // 在运动之间需要间隔,用sleep方法达到停顿的效果 } catch (InterruptedException e) { e.printStackTrace(); } snk.snakeMove(); // 调用移动方法 pack(); // 绘制默认大小的窗口 } } }).start(); } } class MyKeyEventPostProcessor implements KeyEventPostProcessor { private Snake snk; public boolean postProcessKeyEvent(KeyEvent e) { Direction dir = null; // 创建一个Direction枚举类引用 switch (e.getKeyCode()) { case KeyEvent.VK_UP: dir = Direction.UP; break; case KeyEvent.VK_DOWN: dir = Direction.DOWN; break; case KeyEvent.VK_LEFT: dir = Direction.LEFT; break; case KeyEvent.VK_RIGHT: dir = Direction.RIGHT; break; } // 根据不同的方向键,将获取的值存放在dir中 if (dir != null) snk.setMoveDir(dir); // 如果获取到的值是上下左右四个方向键中一个,那么将dir存放到Snake类的moveDir变量中 return true; } public void setSnk(Snake snk) { this.snk = snk; } } class BoardComponent extends JComponent { public static final int Width = Configure.WIDTH; public static final int Height = Configure.HEIGTH; public static final int TileWidth = Configure.TILE_WIDTH; public static final int TileHeight = Configure.TILE_HEIGHT; public static final int Row = Configure.ROW; public static final int Column = Configure.COL; private static final int XOffset = (Width - Column * TileWidth) / 2; private static final int YOffset = (Height - Row * TileHeight) / 2; // 从Configure文件中读取的游戏数据 private Snake snk; public void setSnake(Snake snk) { this.snk = snk; } /** * 我们覆盖了这个以用来打印 * * @param g */ public void paintComponent(Graphics g) { drawDecoration(g); drawFill(g); } /** * 绘制实心的蛇身体以及食物 * * @param g */ public void drawFill(Graphics g) { g.setColor(Color.GREEN); for (SnakePos sp : snk.getSnakeBody()) g.fillRect(sp.col * TileWidth + XOffset, sp.row * TileHeight + YOffset, TileWidth, TileHeight); // 遍历蛇的身体,将每一块蛇都上色 Food fd = snk.getFood(); g.setColor(Color.BLUE); // 将当前的食物上色 g.fillRect(fd.col * TileWidth + XOffset, fd.row * TileHeight + YOffset, TileWidth, TileHeight); } /** * 绘制游戏的边界红色框 * * @param g */ public void drawDecoration(Graphics g) { g.setColor(Color.RED); g.drawRect(XOffset, YOffset, Column * TileWidth, Row * TileHeight); } /** * 我们覆盖了这个方法来表示出这个类的组件的大小 * * @return 返回这个类的组件本身应该有多大 */ public Dimension getPreferredSize() { return new Dimension(Width, Height); // 返回一个Dimension对象,表示这个组件的大小 } }
스네이크 클래스:
import java.util.LinkedList;/** * * @author QuinnNorris * * 蛇的实现类 */public class Snake { private Direction snakeDir; // 当前蛇头所向的方向 private Direction moveDir; // moveDir是从Board类中读取到的方向 // moveDir是在run方法的一个周期中,通过键盘读取的,蛇头想要改变的方向 // 这段的逻辑是:我们先从Board的键盘监听处读取玩家想要改变的蛇的方向,但是我们不直接把蛇的方向设置成获取的方向 // 因为如果玩家在run方法的一个周期中多次按下不同的方向键,可能会导致一些BUG,我们先记录“玩家想要改变成”的方向 // 然后在移动的时候,获取这个想要改变的方向(moveDir)与现在的方向(snakeDir)进行判断后再处理。 private Food food; // 当前蛇在游戏中的食物,会随着蛇吃下一个食物进行刷新 private LinkedList<SnakePos> snakeBody; // 蛇的身体,由一个个SnakePos单元构成 // 数据结构是链表,因为随机访问次数少,插入删除次数多 public static final int Row = Configure.ROW; public static final int Column = Configure.COL; // 从Configure文件中读取的游戏行列 public Snake() { snakeBody = new LinkedList<SnakePos>(); reset(); // 初始化蛇 } public Direction getSnakeDir() { return snakeDir; } public void setSnakeDir(Direction snakeDir) { this.snakeDir = snakeDir; } public LinkedList<SnakePos> getSnakeBody() { return snakeBody; } public Food getFood() { return food; } public void setFood(Food food) { this.food = food; } public void setMoveDir(Direction dir) { this.moveDir = dir; } /** * 此方法用来初始化蛇,让蛇变成一条竖直3格长度,方向向上的随机位置新蛇 */ public void reset() { snakeBody.clear(); // 清空链表 SnakePos beginPos = null; // 创建一格蛇头的引用 setMoveDir(null); // 将键盘监听的方向设置为null do { beginPos = this.RandomPos(); // 调用方法随机放置蛇头位置 } while (beginPos.row + 3 > Row); // 如果蛇头向下三行没接触到底边,这个生成是可以被接受的 snakeBody.add(beginPos); snakeBody.add(new SnakePos(beginPos.row + 1, beginPos.col)); snakeBody.add(new SnakePos(beginPos.row + 2, beginPos.col)); // 将三格蛇(包括蛇头)添加到SnakeBody链表中 setSnakeDir(Direction.UP); // 设置方向为向上 } /** * 创建一个蛇身体(SnakePos类)对象并随机设置行列,将其返回 * * @return 行列被随机的一个蛇身体对象 */ private SnakePos RandomPos() { int randomRow = (int) (Math.random() * Row); int randomCol = (int) (Math.random() * Column); return new SnakePos(randomRow, randomCol); } /** * 控制蛇的移动 */ public void snakeMove() { int addRow = snakeBody.getFirst().row; int addCol = snakeBody.getFirst().col; // 想要添加的新蛇头必定是原蛇头相邻某个方向的一块 // 先将新蛇头的行列设置为原蛇头的行列 Direction up = Direction.UP; Direction down = Direction.DOWN; Direction left = Direction.LEFT; Direction right = Direction.RIGHT; // 创建Direction枚举类的四个引用,为了少写几个字(嘿嘿) if ((moveDir != null) && !((snakeDir == up && moveDir == down) || (snakeDir == down && moveDir == up) || (snakeDir == left && moveDir == right) || (snakeDir == right && moveDir == left))) snakeDir = moveDir; // 如果符合条件,就将键盘监听的moveDir方向设置为最新的蛇头方向 switch (snakeDir) { case UP: addRow--; break; case DOWN: addRow++; break; case LEFT: addCol--; break; case RIGHT: addCol++; break; } // 根据最新蛇头方向,确定新的蛇头在哪个块生成,修改新蛇头的行列坐标 SnakePos addPos = new SnakePos(addRow, addCol); // 根据这个行列坐标,创建一个蛇身体(SnakePos)对象 if (!isFood(addPos)) snakeBody.removeLast(); // 如果不是食物,则去掉snakeBody链表中最后一个节点 else setFood(new Food().getSnake(snakeBody)); // 是食物就重新设置一个食物,不用去掉最后一个节点 if (isCollision(addPos)) reset(); // 如果碰撞了,把这条蛇重置 else snakeBody.addFirst(addPos); // 没碰撞就将刚才设置的新蛇头放进链表中 // 注意,即使是食物也会执行这一句话,因为遇到食物不算是碰撞 } /** * 判断一个格是不是食物 * * @param addPos * 要判断的格子 * @return 返回true表示是食物 */ private boolean isFood(SnakePos addPos) { if (food.row == addPos.row && food.col == addPos.col) return true; // 如果传入的行列坐标和这个类中的food变量的行列一样就表示是食物 return false; } /** * 碰撞检测,如果遇到墙壁或者蛇身体就认为碰撞 * * @param addPos * 要判断是否为墙壁(或蛇身体)的格子 * @return 会发生碰撞返回true */ private boolean isCollision(SnakePos addPos) { if (addPos.row < 0 || addPos.row > Row - 1 || addPos.col < 0 || addPos.col > Column - 1) return true; // 如果是墙壁返回true for (SnakePos sp : snakeBody) if ((sp.row == addPos.row) && (sp.col == addPos.col)) return true; // 如果是蛇身体返回true return false; } }
SnakePos 클래스:
/** * * @author QuinnNorris * * 格子类 (或者可以理解成表示蛇的一块身体的类) */public class SnakePos { public int col; public int row; // 一块蛇身体的位置坐标 // 设置为public方便调用 /** * 行列构造器,表示这一块身体在游戏盘中所处的行列 * * @param row * 所在的行 * @param col * 所在的列 */ SnakePos(int row, int col) { this.col = col; this.row = row; } /** * 留下一个无参的构造器,不是为了调用,而是为了为Food类做方便 */ SnakePos() { col = 0; row = 0; } }
음식 클래스:
import java.util.LinkedList;/** * * @author QuinnNorris * * 食物类 */public class Food extends SnakePos { public int row; public int col; // 表示食物所在的行列 public static final int Row = Configure.ROW; public static final int Column = Configure.COL; // 从Configure文件中读取的游戏行列 Food() { randomPos(); // 随机设置这个对象的行列变量 } /** * 获取蛇的snakeBody链表,让食物与蛇身不重叠 * * @param snakeBody * 表示蛇身体的链表 * @return 返回这个类实例化的对象本身 */ public Food getSnake(LinkedList<SnakePos> snakeBody) { while (checkSame(snakeBody)) randomPos(); // 如果发现食物的位置和蛇身体重叠,则重新随机食物的位置 return this; // 返回这个对象本身,为创建实例时带来方便 } /** * 检查蛇身体链表中是否有一块与当前食物坐标相同 * * @param snakeBody * 表示蛇身体的链表 * @return 如果有重复返回true */ private boolean checkSame(LinkedList<SnakePos> snakeBody) { for (SnakePos sp : snakeBody) if (sp.row == this.row && sp.col == this.col) return true; // 循环遍历是否有重复 return false; } /** * 随机该对象的行和列变量 */ private void randomPos() { this.row = (int) (Math.random() * Row); this.col = (int) (Math.random() * Column); } }
구성 클래스:
/** * * @author QuinnNorris * * configuration information */public class Configure { public static final int WIDTH = 400; public static final int HEIGTH = 300; // Height and width of window. public static final int TILE_WIDTH = 16; public static final int TILE_HEIGHT = 16; // The height and width of each snakePos. public static final int ROW = 15; public static final int COL = 20; // The number of rows and columns of the game. public static final int INTERVAL = 300; // Snake moving time interval.}
방향 클래스:
/** * * @author QuinnNorris * */public enum Direction { UP, DOWN, LEFT, RIGHT; // 上下左右四个方向}
위 내용은 탐욕스러운 뱀의 Java 구현 코드 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

Java 8은 스트림 API를 소개하여 데이터 컬렉션을 처리하는 강력하고 표현적인 방법을 제공합니다. 그러나 스트림을 사용할 때 일반적인 질문은 다음과 같은 것입니다. 기존 루프는 조기 중단 또는 반환을 허용하지만 스트림의 Foreach 메소드는이 방법을 직접 지원하지 않습니다. 이 기사는 이유를 설명하고 스트림 처리 시스템에서 조기 종료를 구현하기위한 대체 방법을 탐색합니다. 추가 읽기 : Java Stream API 개선 스트림 foreach를 이해하십시오 Foreach 메소드는 스트림의 각 요소에서 하나의 작업을 수행하는 터미널 작동입니다. 디자인 의도입니다

PHP는 서버 측에서 널리 사용되는 스크립팅 언어이며 특히 웹 개발에 적합합니다. 1.PHP는 HTML을 포함하고 HTTP 요청 및 응답을 처리 할 수 있으며 다양한 데이터베이스를 지원할 수 있습니다. 2.PHP는 강력한 커뮤니티 지원 및 오픈 소스 리소스를 통해 동적 웹 컨텐츠, 프로세스 양식 데이터, 액세스 데이터베이스 등을 생성하는 데 사용됩니다. 3. PHP는 해석 된 언어이며, 실행 프로세스에는 어휘 분석, 문법 분석, 편집 및 실행이 포함됩니다. 4. PHP는 사용자 등록 시스템과 같은 고급 응용 프로그램을 위해 MySQL과 결합 할 수 있습니다. 5. PHP를 디버깅 할 때 error_reporting () 및 var_dump ()와 같은 함수를 사용할 수 있습니다. 6. 캐싱 메커니즘을 사용하여 PHP 코드를 최적화하고 데이터베이스 쿼리를 최적화하며 내장 기능을 사용하십시오. 7

PHP와 Python은 각각 고유 한 장점이 있으며 선택은 프로젝트 요구 사항을 기반으로해야합니다. 1.PHP는 간단한 구문과 높은 실행 효율로 웹 개발에 적합합니다. 2. Python은 간결한 구문 및 풍부한 라이브러리를 갖춘 데이터 과학 및 기계 학습에 적합합니다.

PHP는 특히 빠른 개발 및 동적 컨텐츠를 처리하는 데 웹 개발에 적합하지만 데이터 과학 및 엔터프라이즈 수준의 애플리케이션에는 적합하지 않습니다. Python과 비교할 때 PHP는 웹 개발에 더 많은 장점이 있지만 데이터 과학 분야에서는 Python만큼 좋지 않습니다. Java와 비교할 때 PHP는 엔터프라이즈 레벨 애플리케이션에서 더 나빠지지만 웹 개발에서는 더 유연합니다. JavaScript와 비교할 때 PHP는 백엔드 개발에서 더 간결하지만 프론트 엔드 개발에서는 JavaScript만큼 좋지 않습니다.

PHP와 Python은 각각 고유 한 장점이 있으며 다양한 시나리오에 적합합니다. 1.PHP는 웹 개발에 적합하며 내장 웹 서버 및 풍부한 기능 라이브러리를 제공합니다. 2. Python은 간결한 구문과 강력한 표준 라이브러리가있는 데이터 과학 및 기계 학습에 적합합니다. 선택할 때 프로젝트 요구 사항에 따라 결정해야합니다.

캡슐은 3 차원 기하학적 그림이며, 양쪽 끝에 실린더와 반구로 구성됩니다. 캡슐의 부피는 실린더의 부피와 양쪽 끝에 반구의 부피를 첨가하여 계산할 수 있습니다. 이 튜토리얼은 다른 방법을 사용하여 Java에서 주어진 캡슐의 부피를 계산하는 방법에 대해 논의합니다. 캡슐 볼륨 공식 캡슐 볼륨에 대한 공식은 다음과 같습니다. 캡슐 부피 = 원통형 볼륨 2 반구 볼륨 안에, R : 반구의 반경. H : 실린더의 높이 (반구 제외). 예 1 입력하다 반경 = 5 단위 높이 = 10 단위 산출 볼륨 = 1570.8 입방 단위 설명하다 공식을 사용하여 볼륨 계산 : 부피 = π × r2 × h (4

phphassignificallyimpactedwebdevelopmentandextendsbeyondit

PHP가 많은 웹 사이트에서 선호되는 기술 스택 인 이유에는 사용 편의성, 강력한 커뮤니티 지원 및 광범위한 사용이 포함됩니다. 1) 배우고 사용하기 쉽고 초보자에게 적합합니다. 2) 거대한 개발자 커뮤니티와 풍부한 자원이 있습니다. 3) WordPress, Drupal 및 기타 플랫폼에서 널리 사용됩니다. 4) 웹 서버와 밀접하게 통합하여 개발 배포를 단순화합니다.
