Java寫的小游戲貪吃蛇代碼

jopen 12年前發布 | 142K 次閱讀 Java Java開發

import java.awt.;
import java.awt.event.;
import javax.swing.;
import java.util.;

//Main Class

public class GreedSnake extends KeyAdapter {

JFrame mainFrame;

Canvas paintCanvas;

JLabel labelScore;// 計分牌

SnakeModel snakeModel = null;// 蛇

public static final int DEFAULT_WIDTH = 500;

public static final int DEFAULT_HEIGHT = 300;

public static final int nodeWidth = 10;

public static final int nodeHeight = 10;

// GreedSnake():初始化游戲界面

public GreedSnake() {

    // 設置界面元素
    mainFrame = new JFrame("貪吃蛇游戲");
    Container cp = mainFrame.getContentPane();
    labelScore = new JLabel("所得分數為:", JLabel.CENTER);
    cp.add(labelScore, BorderLayout.NORTH);
    paintCanvas = new Canvas();
    paintCanvas.setSize(DEFAULT_WIDTH + 1, DEFAULT_HEIGHT + 1);
    paintCanvas.addKeyListener(this);
    cp.add(paintCanvas, BorderLayout.CENTER);
    JPanel panelButtom = new JPanel();
    panelButtom.setLayout(new BorderLayout());
    JLabel labelHelp;// 幫助信息
    labelHelp = new JLabel("按 PageUP 或 PageDown 鍵改變速度", JLabel.CENTER);
    panelButtom.add(labelHelp, BorderLayout.NORTH);
    labelHelp = new JLabel("按 Enter 或 S 鍵重新開始游戲", JLabel.CENTER);
    panelButtom.add(labelHelp, BorderLayout.CENTER);
    labelHelp = new JLabel("按 SPACE 鍵或 P 鍵暫停游戲", JLabel.CENTER);
    panelButtom.add(labelHelp, BorderLayout.SOUTH);
    cp.add(panelButtom, BorderLayout.SOUTH);
    mainFrame.addKeyListener(this);
    mainFrame.pack();
    mainFrame.setResizable(false);// 設置窗口大小不能變化
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.setVisible(true);
    begin();
}

// keyPressed():按鍵檢測

public void keyPressed(KeyEvent e) {

    int keyCode = e.getKeyCode();
    if (snakeModel.running)
        switch (keyCode) {
        case KeyEvent.VK_UP:
            snakeModel.changeDirection(SnakeModel.UP);
            break;
        case KeyEvent.VK_DOWN:
            snakeModel.changeDirection(SnakeModel.DOWN);
            break;
        case KeyEvent.VK_LEFT:
            snakeModel.changeDirection(SnakeModel.LEFT);
            break;
        case KeyEvent.VK_RIGHT:
            snakeModel.changeDirection(SnakeModel.RIGHT);
            break;
        case KeyEvent.VK_ADD:
        case KeyEvent.VK_PAGE_UP:
            snakeModel.speedUp();// 加速
            break;
        case KeyEvent.VK_SUBTRACT:
        case KeyEvent.VK_PAGE_DOWN:
            snakeModel.speedDown();// 減速
            break;
        case KeyEvent.VK_SPACE:
        case KeyEvent.VK_P:
            snakeModel.changePauseState();// 暫停或繼續
            break;
        default:
        }
    // 重新開始
    if (keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_ENTER) {
        snakeModel.running = false;
        begin();
    }
}

// repaint():繪制游戲界面(包括蛇和食物)

void repaint() {
    Graphics g = paintCanvas.getGraphics();
    // draw background
    g.setColor(Color.LIGHT_GRAY);
    g.fillRect(0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT);
    // draw the snake
    g.setColor(Color.BLACK);
    LinkedList na = snakeModel.nodeArray;
    Iterator it = na.iterator();
    while (it.hasNext()) {

        Node n = (Node) it.next();
        drawNode(g, n);
    }
    // draw the food
    g.setColor(Color.RED);
    Node n = snakeModel.food;
    drawNode(g, n);
    updateScore();
}

// drawNode():繪畫某一結點(蛇身或食物)

private void drawNode(Graphics g, Node n) {
    g.fillRect(n.x * nodeWidth, n.y * nodeHeight, nodeWidth - 1, nodeHeight - 1);
}

// updateScore():改變計分牌

public void updateScore() {
    String s = "所得分數為: " + snakeModel.score;
    labelScore.setText(s);
}

// begin():游戲開始,放置貪吃蛇

void begin() {

    if (snakeModel == null || !snakeModel.running) {
        snakeModel = new SnakeModel(this, DEFAULT_WIDTH / nodeWidth, DEFAULT_HEIGHT / nodeHeight);
        (new Thread(snakeModel)).start();
    }
}

// main():主函數

public static void main(String[] args) {

    GreedSnake gs = new GreedSnake();
}

}

// Node:結點類

class Node { int x;

int y;

Node(int x, int y) {
    this.x = x;
    this.y = y;
}

}

// SnakeModel:貪吃蛇模型

class SnakeModel implements Runnable {

GreedSnake gs;

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和DOWN是偶數,RIGHT和LEFT是奇數
public static final int UP = 2;

public static final int DOWN = 4;

public static final int LEFT = 1;

public static final int RIGHT = 3;

// GreedModel():初始化界面

public SnakeModel(GreedSnake gs, int maxX, int maxY) {

    this.gs = gs;
    this.maxX = maxX;
    this.maxY = maxY;
    matrix = new boolean[maxX][];
    for (int i = 0; i < maxX; ++i) {
        matrix[i] = new boolean[maxY];
        Arrays.fill(matrix[i], false);// 沒有蛇和食物的地區置false
    }
    // 初始化貪吃蛇
    int initArrayLength = maxX > 20 ? 10 : maxX / 2;
    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;// 蛇身處置true
    }
    food = createFood();
    matrix[food.x][food.y] = true;// 食物處置true
}

// changeDirection():改變運動方向

public void changeDirection(int newDirection) {

    if (direction % 2 != newDirection % 2) {// 避免沖突
        direction = newDirection;
    }
}

// moveOn():貪吃蛇運動函數

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;// 越界(撞到墻壁)
}

/* 發了一份貪吃蛇游戲的代碼,誰能幫我解釋一下,貪吃蛇程序的運行過程,運行步驟 */
// run():貪吃蛇運動線程

public void run() {
    running = true;
    while (running) {
        try {
            Thread.sleep(timeInterval);
        } catch (Exception e) {
            break;
        }
        if (!paused) {

            if (moveOn()) {// 未結束
                gs.repaint();
            } else {// 游戲結束
                JOptionPane.showMessageDialog(null, "GAME OVER", "Game Over", JOptionPane.INFORMATION_MESSAGE);
                break;
            }
        }
    }
    running = false;
}

// createFood():生成食物及放置地點

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);
}

// speedUp():加快蛇運動速度

public void speedUp() {
    timeInterval *= speedChangeRate;
}

// speedDown():放慢蛇運動速度

public void speedDown() {

    timeInterval /= speedChangeRate;
}

// changePauseState(): 改變游戲狀態(暫停或繼續)

public void changePauseState() {

    paused = !paused;
}

}</pre>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!