<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
我寫的這個”貪吃蛇“和小時候玩的”貪吃蛇“有點不一樣,以往的”貪吃蛇“吃了食物蛇身就會變長,而我寫的這個吃了“食物”蛇身會變短,並且勝利條件就是“把蛇變沒”,嘻嘻~
這裡的“食物”其實是“藥丸”,初始時,蛇身很長,你要通過食用“藥丸”,來讓自己的身體變短,直到自己消失不見,你就獲勝了。
“藥丸”共有三種,分別為“紅色藥丸、藍色藥丸、綠色藥丸”,對應分值“5分、2分、1分”,蛇吃了“藥丸”會減掉對應分值數量的身體,並累計分值。
座標 Point.java
記錄橫縱座標值。
package cn.xeblog.snake.model; import java.util.Objects; /** * 座標 * * @author anlingyi * @date 2022/8/2 3:35 PM */ public class Point { public int x; public int y; public Point(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Point point = (Point) o; return x == point.x && y == point.y; } @Override public int hashCode() { return Objects.hash(x, y); } @Override public String toString() { return "Point{" + "x=" + x + ", y=" + y + '}'; } }
移動方向 Direction.java
提供上、下、左、右四個移動方向的列舉。
package cn.xeblog.snake.model; /** * @author anlingyi * @date 2022/8/2 5:25 PM */ public enum Direction { UP, DOWN, LEFT, RIGHT }
蛇 Snake.java
儲存蛇身座標資訊,提供蛇身移動、移除蛇尾座標、獲取蛇頭、蛇尾座標、蛇身長度等方法。
這裡講一下蛇移動的實現原理:遊戲開始時,會固定一個移動方向,蛇會一直朝著這個方向移動,我們可以通過方向鍵改變蛇的移動方向,蛇的移動其實就是將蛇身的座標移動一下位置,比如蛇身長度(不包含蛇頭)為6,移動時,只需將蛇身位置為5的座標移到位置為6的座標去,位置為4的座標移動到位置為5的座標去,簡單來說就是將前一個的座標換到它後面一個去,這是蛇身的移動,蛇頭的移動需要單獨計算,如果是上下方向移動,那就是對y座標的加減操作,向上運動需要減一個蛇身的高度,向下則與之相反,需要加一個蛇身的高度,左右運動同理。
package cn.xeblog.snake.model; import java.util.List; /** * 蛇 * * @author anlingyi * @date 2022/8/2 3:32 PM */ public class Snake { public static int width = 10; public static int height = 10; /** * 蛇身座標列表 */ public List<Point> body; public Snake(List<Point> body) { this.body = body; } /** * 新增蛇身座標 * * @param x * @param y */ public void add(int x, int y) { this.body.add(new Point(x * width, y * height)); } /** * 移除蛇尾座標 */ public void removeLast() { int size = size(); if (size == 0) { return; } this.body.remove(size - 1); } /** * 獲取蛇頭座標 * * @return */ public Point getHead() { if (size() > 0) { return this.body.get(0); } return null; } /** * 獲取蛇尾座標 * * @return */ public Point getTail() { int size = size(); if (size > 0) { return this.body.get(size - 1); } return null; } /** * 蛇身長度 * * @return */ public int size() { return this.body.size(); } /** * 蛇移動 * * @param direction 移動方向 */ public void move(Direction direction) { if (size() == 0) { return; } for (int i = this.size() - 1; i > 0; i--) { // 從蛇尾開始向前移動 Point point = this.body.get(i); Point nextPoint = this.body.get(i - 1); point.x = nextPoint.x; point.y = nextPoint.y; } // 蛇頭移動 Point head = getHead(); switch (direction) { case UP: head.y -= height; break; case DOWN: head.y += height; break; case LEFT: head.x -= width; break; case RIGHT: head.x += width; break; } } }
藥丸 Pill.java
儲存“藥丸“的座標、型別資訊。
package cn.xeblog.snake.model; /** * 藥丸 * * @author anlingyi * @date 2022/8/2 4:49 PM */ public class Pill { public static int width = 10; public static int height = 10; /** * 座標 */ public Point point; /** * 藥丸型別 */ public PillType pillType; public enum PillType { /** * 紅色藥丸 */ RED(5), /** * 藍色藥丸 */ BLUE(2), /** * 綠色藥丸 */ GREEN(1), ; /** * 分數 */ public int score; PillType(int score) { this.score = score; } } public Pill(int x, int y, PillType pillType) { this.point = new Point(x * width, y * height); this.pillType = pillType; } }
初始化一些資訊,比如遊戲介面的寬高、定時器、一些狀態標識(是否停止遊戲、遊戲是否勝利)、監聽一些按鍵事件(空格鍵開始/暫停遊戲、四個方向鍵控制蛇移動的方向),繪製遊戲畫面。
當檢測到遊戲開始時,初始化蛇、“藥丸”的位置資訊,然後啟動定時器每隔一段時間重新繪製遊戲畫面,讓蛇可以動起來。
當檢測到蛇咬到自己或者是蛇撞牆時,遊戲狀態將會被標記為“遊戲失敗”,繪製遊戲結束畫面,並且定時器停止,如果蛇身為0,則遊戲結束,遊戲狀態標記為“遊戲勝利”。
package cn.xeblog.snake.ui; import cn.xeblog.snake.model.Direction; import cn.xeblog.snake.model.Pill; import cn.xeblog.snake.model.Point; import cn.xeblog.snake.model.Snake; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.ArrayList; import java.util.Collections; import java.util.Random; /** * @author anlingyi * @date 2022/8/2 3:51 PM */ public class SnakeGameUI extends JPanel implements ActionListener { /** * 寬度 */ private int width; /** * 高度 */ private int height; /** * 蛇 */ private Snake snake; /** * 藥丸 */ private Pill pill; /** * 移動方向 */ private Direction direction; /** * 停止遊戲標記 */ private boolean stop; /** * 遊戲狀態 0.初始化 1.遊戲勝利 2.遊戲失敗 */ private int state = -1; /** * 定時器 */ private Timer timer; /** * 移動速度 */ private int speed = 100; /** * 分數 */ private int score; /** * 特殊藥丸列表 */ private ArrayList<Pill.PillType> specialPill; public SnakeGameUI(int width, int height) { this.width = width; this.height = height; this.timer = new Timer(speed, this); this.stop = true; initPanel(); } /** * 初始化 */ private void init() { this.score = 0; this.state = 0; this.stop = true; this.timer.setDelay(speed); initSnake(); initPill(); generatePill(); repaint(); } /** * 初始化遊戲面板 */ private void initPanel() { this.setPreferredSize(new Dimension(this.width, this.height)); this.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (stop && e.getKeyCode() != KeyEvent.VK_SPACE) { return; } switch (e.getKeyCode()) { case KeyEvent.VK_UP: if (direction == Direction.DOWN) { break; } direction = Direction.UP; break; case KeyEvent.VK_DOWN: if (direction == Direction.UP) { break; } direction = Direction.DOWN; break; case KeyEvent.VK_LEFT: if (direction == Direction.RIGHT) { break; } direction = Direction.LEFT; break; case KeyEvent.VK_RIGHT: if (direction == Direction.LEFT) { break; } direction = Direction.RIGHT; break; case KeyEvent.VK_SPACE: if (state != 0) { init(); } stop = !stop; if (!stop) { timer.start(); } break; } } }); } /** * 初始化蛇 */ private void initSnake() { this.direction = Direction.LEFT; int maxX = this.width / Snake.width; int maxY = this.height / Snake.height; this.snake = new Snake(new ArrayList<>()); this.snake.add(maxX - 2, 3); this.snake.add(maxX - 1, 3); this.snake.add(maxX - 1, 2); this.snake.add(maxX - 1, 1); for (int i = maxX - 1; i > 0; i--) { this.snake.add(i, 1); } for (int i = 1; i < maxY - 1; i++) { this.snake.add(1, i); } for (int i = 1; i < maxX - 1; i++) { this.snake.add(i, maxY - 2); } } /** * 初始化藥丸 */ private void initPill() { this.specialPill = new ArrayList<>(); for (int i = 0; i < 5; i++) { this.specialPill.add(Pill.PillType.RED); } for (int i = 0; i < 10; i++) { this.specialPill.add(Pill.PillType.BLUE); } Collections.shuffle(specialPill); } /** * 生成藥丸 */ private void generatePill() { // 是否獲取特殊藥丸 boolean getSpecialPill = new Random().nextInt(6) == 3; Pill.PillType pillType; if (getSpecialPill && this.specialPill.size() > 0) { // 生成特殊藥丸 int index = new Random().nextInt(this.specialPill.size()); pillType = this.specialPill.get(index); this.specialPill.remove(index); } else { // 生成綠色藥丸 pillType = Pill.PillType.GREEN; } // 隨機座標 int x = new Random().nextInt(this.width / Pill.width - 1); int y = new Random().nextInt(this.height / Pill.height - 1); this.pill = new Pill(x, y, pillType); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(new Color(66, 66, 66)); g2.fillRect(0, 0, this.width, this.height); if (this.snake != null) { // 畫蛇 g2.setColor(new Color(255, 255, 255)); for (int i = this.snake.size() - 1; i >= 0; i--) { Point point = this.snake.body.get(i); if (i == 0) { // 蛇頭 g2.setColor(new Color(255, 92, 92)); } else { g2.setColor(new Color(215, 173, 173)); } g2.fillRect(point.x, point.y, Snake.width, Snake.height); } } if (this.pill != null) { // 畫藥丸 Color pillColor; switch (this.pill.pillType) { case RED: pillColor = new Color(255, 41, 41); break; case BLUE: pillColor = new Color(20, 250, 243); break; default: pillColor = new Color(97, 255, 113); break; } g2.setColor(pillColor); g2.fillOval(pill.point.x, pill.point.y, Pill.width, Pill.height); } if (state > 0) { // 顯示遊戲結果 String tips = "遊戲失敗!"; if (state == 1) { tips = "遊戲勝利!"; } g2.setFont(new Font("", Font.BOLD, 20)); g2.setColor(new Color(208, 74, 74)); g2.drawString(tips, this.width / 3, this.height / 3); g2.setFont(new Font("", Font.PLAIN, 18)); g2.setColor(Color.WHITE); g2.drawString("得分:" + this.score, this.width / 2, this.height / 3 + 50); } if (stop) { g2.setFont(new Font("", Font.PLAIN, 18)); g2.setColor(Color.WHITE); g2.drawString("按空格鍵開始/暫停遊戲!", this.width / 4, this.height - 50); } } @Override public void actionPerformed(ActionEvent e) { // 是否吃藥 boolean isAte = false; if (!this.stop) { // 移動蛇 this.snake.move(this.direction); Point head = this.snake.getHead(); if (head.equals(this.pill.point)) { // 吃藥了 isAte = true; // 藥丸分數 int getScore = this.pill.pillType.score; // 累計分數 this.score += getScore; for (int i = 0; i < getScore; i++) { // 移除蛇尾 this.snake.removeLast(); if (this.snake.size() == 0) { // 遊戲勝利 this.state = 1; this.stop = true; break; } } pill = null; if (this.score % 10 == 0) { int curSpeed = this.timer.getDelay(); if (curSpeed > 30) { // 加速 this.timer.setDelay(curSpeed - 10); } } } if (state == 0) { // 判斷蛇有沒有咬到自己或是撞牆 int maxWidth = this.width - this.snake.width; int maxHeight = this.height - this.snake.height; boolean isHitWall = head.x > maxWidth || head.x < 0 || head.y > maxHeight || head.y < 0; boolean isBiting = false; for (int i = this.snake.size() - 1; i > 0; i--) { if (head.equals(this.snake.body.get(i))) { isBiting = true; break; } } if (isHitWall || isBiting) { // 遊戲失敗 this.state = 2; this.stop = true; } } } if (this.stop) { this.timer.stop(); } else if (isAte) { // 重新生成藥丸 generatePill(); } repaint(); } }
遊戲啟動入口。
package cn.xeblog.snake; import cn.xeblog.snake.ui.SnakeGameUI; import javax.swing.*; /** * 啟動遊戲 * * @author anlingyi * @date 2022/8/2 3:41 PM */ public class StartGame { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setVisible(true); frame.setResizable(false); frame.setTitle("不貪吃蛇"); frame.setSize(400, 320); frame.setLocationRelativeTo(null); JPanel gamePanel = new SnakeGameUI(400, 300); frame.add(gamePanel); gamePanel.requestFocus(); } }
剛開始蛇身很長,蛇身移動緩慢,後面會隨著得分的越來越高,蛇身會移動的越來越快,看著挺容易,真玩起來,還真有“億”點難,目前我玩了好幾把,沒有贏過,最開始那張圖就是我目前的最高分了,嘻嘻~
完整程式碼:https://github.com/anlingyi/NonGluttonousSnake
到此這篇關於利用Java編寫個"不貪吃蛇"小遊戲的文章就介紹到這了,更多相關Java不貪吃蛇遊戲內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45