?? snakemodel.java
字號:
//----------------------------------------------------------------------
// SnakeModel.java
import javax.swing.*;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Observable;
import java.util.Random;
/**
* 游戲的Model類,負責所有游戲相關數據及運行
*/
class SnakeModel extends Observable implements Runnable {
boolean[][] matrix; // 指示位置上有沒蛇體或食物
LinkedList nodeArray = new LinkedList(); // 蛇體
Node food;
int maxX;
int maxY;
int direction = 2; // 蛇運行的方向
boolean running = false; // 運行狀態
int timeInterval = 200; // 時間間隔,毫秒
double speedChangeRate = 0.75; // 每次得速度變化率
boolean paused = false; // 暫停標志
int score = 0; // 得分
int countMove = 0; // 吃到食物前移動的次數
// UP and DOWN should be even
// RIGHT and LEFT should be odd
public static final int UP = 2;
public static final int DOWN = 4;
public static final int LEFT = 1;
public static final int RIGHT = 3;
public SnakeModel( int maxX, int maxY) {
this.maxX = maxX;
this.maxY = maxY;
reset();
}
public void reset(){
direction = SnakeModel.UP; // 蛇運行的方向
timeInterval = 200; // 時間間隔,毫秒
paused = false; // 暫停標志
score = 0; // 得分
countMove = 0; // 吃到食物前移動的次數
// initial matirx, 全部清0
matrix = new boolean[maxX][];
for (int i = 0; i < maxX; ++i) {
matrix[i] = new boolean[maxY];
Arrays.fill(matrix[i], false);
}
// initial the snake
// 初始化蛇體,如果橫向位置超過20個,長度為10,否則為橫向位置的一半
int initArrayLength = maxX > 20 ? 10 : maxX / 2;
nodeArray.clear();
for (int i = 0; i < initArrayLength; ++i) {
int x = maxX / 2 + i;
int y = maxY / 2;
nodeArray.addLast(new Node(x, y));
matrix[x][y] = true;
}
// 創建食物
food = createFood();
matrix[food.x][food.y] = true;
}
public void changeDirection(int newDirection) {
// 改變的方向不能與原來方向同向或反向
if (direction % 2 != newDirection % 2) {
direction = newDirection;
}
}
/**
* 運行一次
* @return
*/
public boolean moveOn() {
Node n = (Node) nodeArray.getFirst();
int x = n.x;
int y = n.y;
// 根據方向增減坐標值
switch (direction) {
case UP:
y--;
break;
case DOWN:
y++;
break;
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
}
// 如果新坐標落在有效范圍內,則進行處理
if ((0 <= x && x < maxX) && (0 <= y && y < maxY)) {
if (matrix[x][y]) { // 如果新坐標的點上有東西(蛇體或者食物)
if (x == food.x && y == food.y) { // 吃到食物,成功
nodeArray.addFirst(food); // 從蛇頭贈長
// 分數規則,與移動改變方向的次數和速度兩個元素有關
int scoreGet = (10000 - 200 * countMove) / timeInterval;
score += scoreGet > 0 ? scoreGet : 10;
countMove = 0;
food = createFood(); // 創建新的食物
matrix[food.x][food.y] = true; // 設置食物所在位置
return true;
} else // 吃到蛇體自身,失敗
return false;
} else { // 如果新坐標的點上沒有東西(蛇體),移動蛇體
nodeArray.addFirst(new Node(x, y));
matrix[x][y] = true;
n = (Node) nodeArray.removeLast();
matrix[n.x][n.y] = false;
countMove++;
return true;
}
}
return false; // 觸到邊線,失敗
}
public void run() {
running = true;
while (running) {
try {
Thread.sleep(timeInterval);
} catch (Exception e) {
break;
}
if (!paused) {
if (moveOn()) {
setChanged(); // Model通知View數據已經更新
notifyObservers();
} else {
JOptionPane.showMessageDialog(null,
"you failed",
"Game Over",
JOptionPane.INFORMATION_MESSAGE);
break;
}
}
}
running = false;
}
private Node createFood() {
int x = 0;
int y = 0;
// 隨機獲取一個有效區域內的與蛇體和食物不重疊的位置
do {
Random r = new Random();
x = r.nextInt(maxX);
y = r.nextInt(maxY);
} while (matrix[x][y]);
return new Node(x, y);
}
public void speedUp() {
timeInterval *= speedChangeRate;
}
public void speedDown() {
timeInterval /= speedChangeRate;
}
public void changePauseState() {
paused = !paused;
}
public String toString() {
String result = "";
for (int i = 0; i < nodeArray.size(); ++i) {
Node n = (Node) nodeArray.get(i);
result += "[" + n.x + "," + n.y + "]";
}
return result;
}
}
class Node {
int x;
int y;
Node(int x, int y) {
this.x = x;
this.y = y;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -