1. 程式人生 > >在Java中通過面向物件的方式寫貪吃蛇

在Java中通過面向物件的方式寫貪吃蛇

在接觸程式設計之前, 一直想著能在初期階段動手寫幾個小玩具, 不過彼時其實連需要學點什麼來實現都不知道. 如今學習Java已經月餘, 這個念頭還是蠢蠢欲動. 稍作分析, 其實貪吃蛇的結構非常簡單, 所需要的大部分工具目前也都已經掌握了, 缺少的主要有兩點, 一個是拿來顯示圖形介面的Swing類的簡單運用, 一個是用於接收鍵盤控制的監聽功能(當然, 後來才知道後者也是Swing的一部分). 按目前的計劃, 如果等到學到這個部分恐怕還要一兩週, 所幸需要的方法並不複雜, 於是乎網上查詢一番, 自己動手豐衣足食:

幾經嘗試終於勉強實現, 奈何實現的過程非常醜陋, 所有程式碼都擠在三個類裡, 類與類, 類與方法, 方法與方法之間的關係也是修修補補, 頭痛醫頭腳痛醫腳, 既不美觀, 也不利於維護和增加功能.
後來在網上找到了這個線上教程: 

https://course.tianmaying.com/java-snake 照著寫了一遍, 覺得確實對於剛開始接觸面向物件程式設計的學習者有所幫助, 對這種思維方式的理解清晰了一些.

以上就是第二次實現的效果圖, 當然了, 光看圖片完全不能體現二者的不同, 畢竟只是繪圖引數設定上的一點不同(不過動圖做都做了...), 下面還是來簡單介紹一下如何用面向物件的思想完成一個貪吃蛇遊戲:

*注: 該貪吃蛇基本上完全是照著前述網路教程寫的, 只在個別地方上有小幅度改動, 有興趣可以點進去看.

===========以下是正文============

要用面向物件的方式寫貪吃蛇, 首先我們要有一條蛇:

 1 package com.chang4.newsnake;
 2 
 3 import java.util.LinkedList;
 4 
 5 public class Snake {
 6     private LinkedList<Node> body = new LinkedList<>();
 7     
 8     private Direction snakeDirection = Direction.RIGHT;
 9 
10 
11 //    public Node eat(Node egg) {
12 //        if(isNeighbor(egg, this.getHead())) {
13 // this.body.addFirst(egg); 14 // return egg; 15 // } else 16 // return null; 17 // } 18 // 19 // private boolean isNeighbor(Node a, Node b) { 20 // return Math.abs(a.getX() - b.getX()) + Math.abs(a.getY() - b.getY()) == 1; 21 // } 22 23 public Direction getDirection() { 24 return snakeDirection; 25 } 26 public Node move(Direction direction) { 27 switch (direction) { 28 case UP: 29 this.body.addFirst(new Node(getHead().getX(), getHead().getY() - 1)); 30 break; 31 case RIGHT: 32 this.body.addFirst(new Node(getHead().getX() + 1, getHead().getY())); 33 break; 34 case DOWN: 35 this.body.addFirst(new Node(getHead().getX(), getHead().getY() + 1)); 36 break; 37 case LEFT: 38 this.body.addFirst(new Node(getHead().getX() - 1, getHead().getY())); 39 break; 40 41 default: 42 break; 43 } 44 return this.body.removeLast(); 45 } 46 47 public Node getHead() { 48 return body.getFirst(); 49 } 50 51 public Node addTail(Node area) { 52 this.body.addLast(area); 53 return area; 54 } 55 56 public LinkedList<Node> getBody() { 57 return this.body; 58 } 59 60 public void changeDirection(Direction newDirection) { 61 if(this.snakeDirection.compatibleWith(newDirection)) 62 this.snakeDirection = newDirection; 63 } 64 }
Snake

大家都玩過貪吃蛇, 應該知道貪吃蛇是在一個棋盤式的網格上移動, 蛇的每一節身體佔據棋盤上的一個格子, 因此蛇的身體本身其實就是一個由每節身體的座標構成的集合. 在蛇的移動中, 每移動一格的過程實際上是在蛇頭的前面一格新增一節新的身體, 然後刪除尾巴一格的身體, 這樣操作要比單獨改變每一節身體的座標有效率得多, 因此我們定義一個連結串列式的LinkedList成員變數body來儲存貪吃蛇身體的資訊, 這樣就可以呼叫.addFirst()和.removeLast()來方便地實現貪吃蛇的移動.

不止儲存蛇