?? snakemodel.java
字號(hào):
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Observable;
import java.util.Random;
import javax.swing.JOptionPane;
/**
* 游戲的Model類,負(fù)責(zé)所有游戲相關(guān)數(shù)據(jù)及運(yùn)行
*/
class SnakeModel extends Observable implements Runnable {
// 蛇運(yùn)行的方向常量
public static final int UP = 2;
public static final int DOWN = 4;
public static final int LEFT = 1;
public static final int RIGHT = 3;
// 指示位置上有沒蛇體或食物
private boolean[][] matrix;
// 蛇體
public LinkedList nodeArray = new LinkedList();
// 食物
public Node food;
// 蛇活動(dòng)的范圍
private int maxX;
private int maxY;
// 蛇運(yùn)行的方向
private int direction = UP;
// 運(yùn)行狀態(tài)
public boolean running = false;
// 時(shí)間間隔,毫秒
public int timeInterval = 200;
// 每次的速度變化率
public double speedChangeRate = 0.75;
// 暫停標(biāo)志
public boolean paused = false;
// 得分
public int score = 0;
// 吃到食物前移動(dòng)的次數(shù)
private int countMove = 0;
//構(gòu)造方法
public SnakeModel(int maxX, int maxY) {
this.maxX = maxX;
this.maxY = maxY;
reset();
}
// 重置游戲
public void reset() {
// 蛇運(yùn)行的方向初始向上
direction = SnakeModel.UP;
timeInterval = 200;
paused = false;
score = 0;
countMove = 0;
// 初始化蛇活動(dòng)的范圍矩陣, 全部清0
matrix = new boolean[maxX][maxY];
for (int i = 0; i < maxX; i++) {
matrix[i] = new boolean[maxY];
Arrays.fill(matrix[i], false);
}
// 初始化蛇體,如果橫向位置超過20個(gè),長度為10,否則為橫向位置的一半
int initArrayLength = maxX > 20 ? 10 : maxX / 2;
nodeArray.clear();
// 初始蛇體居中顯示
int x = maxX / 2;
int y = maxY / 2;
for (int i = 0; i < initArrayLength; i++) {
nodeArray.addLast(new Node(x, y));
matrix[x][y] = true;
x++;
}
// 創(chuàng)建食物
food = createFood();
matrix[food.x][food.y] = true;
}
// 改變蛇運(yùn)動(dòng)的方向
public void changeDirection(int newDirection) {
// 改變的方向不能與原來方向同向或反向
if (direction % 2 != newDirection % 2) {
direction = newDirection;
}
}
/**
* 蛇運(yùn)行一步
*/
public boolean moveOn() {
// 獲得蛇頭的位置
Node head = (Node) nodeArray.getFirst();
int headX = head.x;
int headY = head.y;
// 根據(jù)運(yùn)行方向增減坐標(biāo)值
switch (direction) {
case UP:
headY--;
break;
case DOWN:
headY++;
break;
case LEFT:
headX--;
break;
case RIGHT:
headX++;
break;
}
// 如果新坐標(biāo)落在有效范圍內(nèi),則進(jìn)行處理
if ((0 <= headX && headX < maxX) && (0 <= headY && headY < maxY)) {
if (matrix[headX][headY]) {
// 如果新坐標(biāo)的點(diǎn)上有東西(蛇體或者食物)
if (headX == food.x && headY == food.y) {
speedUp();
// 吃到食物,成功
nodeArray.addFirst(food); // 從蛇頭贈(zèng)長
// 分?jǐn)?shù)規(guī)則,與移動(dòng)改變方向的次數(shù)和速度兩個(gè)元素有關(guān)
int scoreGet = (10000 - 200 * countMove) / timeInterval;
score += scoreGet > 0 ? scoreGet : 10;
countMove = 0;
food = createFood(); // 創(chuàng)建新的食物
matrix[food.x][food.y] = true; // 設(shè)置食物所在位置
return true;
} else {
// 吃到蛇體自身,失敗
return false;
}
} else {
// 如果新坐標(biāo)的點(diǎn)上沒有東西(蛇體),移動(dòng)蛇體
nodeArray.addFirst(new Node(headX, headY));
matrix[headX][headY] = true;
head = (Node) nodeArray.removeLast();
matrix[head.x][head.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()) {
// Model通知View數(shù)據(jù)已經(jīng)更新,請更新試圖
setChanged();
notifyObservers();
} else {
JOptionPane.showMessageDialog(null, "you failed",
"Game Over", JOptionPane.INFORMATION_MESSAGE);
break;
}
}
}
if (!running){
JOptionPane.showMessageDialog(null, "you stoped the game",
"Game Over", JOptionPane.INFORMATION_MESSAGE);
}
}
// 創(chuàng)建食物
private Node createFood() {
int x = 0;
int y = 0;
// 隨機(jī)獲取一個(gè)有效區(qū)域內(nèi)的與蛇體和食物不重疊的位置
do {
Random r = new Random();
x = r.nextInt(maxX);
y = r.nextInt(maxY);
} while (matrix[x][y]);
return new Node(x, y);
}
// 加速運(yùn)行
public void speedUp() {
timeInterval *= speedChangeRate;
}
// 減速運(yùn)行
public void speedDown() {
timeInterval /= speedChangeRate;
}
// 改變暫停狀態(tài)
public void changePauseState() {
paused = !paused;
}
/**
* @return Returns the running.
*/
public boolean isRunning() {
return running;
}
/**
* @param running The running to set.
*/
public void setRunning(boolean running) {
this.running = running;
}
/**
* @return Returns the nodeArray.
*/
public LinkedList getNodeArray() {
return nodeArray;
}
/**
* @return Returns the food.
*/
public Node getFood() {
return food;
}
/**
* @return Returns the score.
*/
public int getScore() {
return score;
}
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;
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -