📜  设计蛇游戏

📅  最后修改于: 2022-05-13 01:57:05.731000             🧑  作者: Mango

设计蛇游戏

让我们看看如何设计一个提供以下功能的基本贪吃蛇游戏:
• 蛇可以向给定的方向移动,当它吃掉食物时,蛇的长度会增加。
• 当蛇越过自己时,游戏结束。
• 食物将在给定的时间间隔内生成。
提问:亚马逊、微软和更多采访
这个问题在面试中被问到,以判断候选人的面向对象设计技能。所以,首先,我们应该考虑类。
主要课程将是:
1.蛇
2. 细胞
3. 董事会
4. 游戏
Game 类代表我们程序的主体。它存储有关蛇和棋盘的信息。
Cell 类表示显示/板的一个点。它包含行号、列号和有关它的信息,即它是空的、上面有食物还是蛇体的一部分?

Java
// To represent a cell of display board.
public class Cell {
 
    private final int row, col;
    private CellType cellType;
 
    public Cell(int row, int col)
    {
        this.row = row;
        this.col = col;
    }
 
    public CellType getCellType()
    {
        return cellType;
    }
 
    public void setCellType(CellType cellType)
    {
        this.cellType = cellType;
    }
 
    public int getRow()
    {
        return row;
    }
 
    public int getCol()
    {
        return col;
    }
}


Java
// Enum for different cell types
 
public enum CellType {
 
    EMPTY,
    FOOD,
    SNAKE_NODE;
}


Java
// To represent a snake
import java.util.LinkedList;
 
public class Snake {
 
    private LinkedList snakePartList
        = new LinkedList<>();
    private Cell head;
 
    public Snake(Cell initPos)
    {
        head = initPos;
        snakePartList.add(head);
        head.setCellType(CellType.SNAKE_NODE);
    }
 
    public void grow() { snakePartList.add(head); }
 
    public void move(Cell nextCell)
    {
        System.out.println("Snake is moving to "
                           + nextCell.getRow() + " "
                           + nextCell.getCol());
        Cell tail = snakePartList.removeLast();
        tail.setCellType(CellType.EMPTY);
 
        head = nextCell;
        head.setCellType(CellType.SNAKE_NODE);
        snakePartList.addFirst(head);
    }
 
    public boolean checkCrash(Cell nextCell)
    {
        System.out.println("Going to check for Crash");
        for (Cell cell : snakePartList) {
            if (cell == nextCell) {
                return true;
            }
        }
 
        return false;
    }
 
    public LinkedList getSnakePartList()
    {
        return snakePartList;
    }
 
    public void
    setSnakePartList(LinkedList snakePartList)
    {
        this.snakePartList = snakePartList;
    }
 
    public Cell getHead() { return head; }
 
    public void setHead(Cell head) { this.head = head; }
}


Java
public class Board {
 
    final int ROW_COUNT, COL_COUNT;
    private Cell[][] cells;
 
    public Board(int rowCount, int columnCount)
    {
        ROW_COUNT = rowCount;
        COL_COUNT = columnCount;
 
        cells = new Cell[ROW_COUNT][COL_COUNT];
        for (int row = 0; row < ROW_COUNT; row++) {
            for (int column = 0; column < COL_COUNT; column++) {
                cells[row][column] = new Cell(row, column);
            }
        }
    }
 
    public Cell[][] getCells()
    {
        return cells;
    }
 
    public void setCells(Cell[][] cells)
    {
        this.cells = cells;
    }
 
    public void generateFood()
    {
        System.out.println("Going to generate food");
        while(true){
            int row = (int)(Math.random() * ROW_COUNT);
            int column = (int)(Math.random() * COL_COUNT);
            if(cells[row][column].getCellType()!=CellType.SNAKE_NODE)
                 break;
        }
        cells[row][column].setCellType(CellType.FOOD);
        System.out.println("Food is generated at: " + row + " " + column);
    }
}


Java
// To represent Snake Game
public class Game {
 
    public static final int DIRECTION_NONE = 0, DIRECTION_RIGHT = 1,
    DIRECTION_LEFT = -1, DIRECTION_UP = 2, DIRECTION_DOWN = -2;
    private Snake snake;
    private Board board;
    private int direction;
    private boolean gameOver;
 
    public Game(Snake snake, Board board)
    {
        this.snake = snake;
        this.board = board;
    }
 
    public Snake getSnake()
    {
        return snake;
    }
 
    public void setSnake(Snake snake)
    {
        this.snake = snake;
    }
 
    public Board getBoard()
    {
        return board;
    }
 
    public void setBoard(Board board)
    {
        this.board = board;
    }
 
    public boolean isGameOver()
    {
        return gameOver;
    }
 
    public void setGameOver(boolean gameOver)
    {
        this.gameOver = gameOver;
    }
 
    public int getDirection()
    {
        return direction;
    }
 
    public void setDirection(int direction)
    {
        this.direction = direction;
    }
 
    // We need to update the game at regular intervals,
    // and accept user input from the Keyboard.
    public void update()
    {
        System.out.println("Going to update the game");
        if (!gameOver) {
            if (direction != DIRECTION_NONE) {
                Cell nextCell = getNextCell(snake.getHead());
 
                if (snake.checkCrash(nextCell)) {
                    setDirection(DIRECTION_NONE);
                    gameOver = true;
                }
                else {
                    snake.move(nextCell);
                    if (nextCell.getCellType() == CellType.FOOD) {
                        snake.grow();
                        board.generateFood();
                    }
                }
            }
        }
    }
 
    private Cell getNextCell(Cell currentPosition)
    {
        System.out.println("Going to find next cell");
        int row = currentPosition.getRow();
        int col = currentPosition.getCol();
 
        if (direction == DIRECTION_RIGHT) {
            col++;
        }
        else if (direction == DIRECTION_LEFT) {
            col--;
        }
        else if (direction == DIRECTION_UP) {
            row--;
        }
        else if (direction == DIRECTION_DOWN) {
            row++;
        }
 
        Cell nextCell = board.getCells()[row][col];
 
        return nextCell;
    }
 
    public static void main(String[] args)
    {
 
        System.out.println("Going to start game");
 
        Cell initPos = new Cell(0, 0);
        Snake initSnake = new Snake(initPos);
        Board board = new Board(10, 10);
        Game newGame = new Game(initSnake, board);
        newGame.gameOver = false;
        newGame.direction = DIRECTION_RIGHT;
 
        // We need to update the game at regular intervals,
        // and accept user input from the Keyboard.
 
        // here I have just called the different methods
        // to show the functionality
        for (int i = 0; i < 5; i++) {
            if (i == 2)
                newGame.board.generateFood();
            newGame.update();
            if (i == 3)
                newGame.direction = DIRECTION_RIGHT;
            if (newGame.gameOver == true)
                break;
        }
    }
}


Java

// Enum for different cell types
 
public enum CellType {
 
    EMPTY,
    FOOD,
    SNAKE_NODE;
}

现在,包含身体和头部的 Snake 类。
我们使用链表来存储正文,因为我们可以在 O(1) 中添加一个单元格。
当它吃到食物时,会调用 Grow 方法。其他方法是不言自明的。

Java

// To represent a snake
import java.util.LinkedList;
 
public class Snake {
 
    private LinkedList snakePartList
        = new LinkedList<>();
    private Cell head;
 
    public Snake(Cell initPos)
    {
        head = initPos;
        snakePartList.add(head);
        head.setCellType(CellType.SNAKE_NODE);
    }
 
    public void grow() { snakePartList.add(head); }
 
    public void move(Cell nextCell)
    {
        System.out.println("Snake is moving to "
                           + nextCell.getRow() + " "
                           + nextCell.getCol());
        Cell tail = snakePartList.removeLast();
        tail.setCellType(CellType.EMPTY);
 
        head = nextCell;
        head.setCellType(CellType.SNAKE_NODE);
        snakePartList.addFirst(head);
    }
 
    public boolean checkCrash(Cell nextCell)
    {
        System.out.println("Going to check for Crash");
        for (Cell cell : snakePartList) {
            if (cell == nextCell) {
                return true;
            }
        }
 
        return false;
    }
 
    public LinkedList getSnakePartList()
    {
        return snakePartList;
    }
 
    public void
    setSnakePartList(LinkedList snakePartList)
    {
        this.snakePartList = snakePartList;
    }
 
    public Cell getHead() { return head; }
 
    public void setHead(Cell head) { this.head = head; }
}

Board 类表示显示。它是一个细胞矩阵。它有一个方法 generate Food 生成
食物在随机位置。

Java

public class Board {
 
    final int ROW_COUNT, COL_COUNT;
    private Cell[][] cells;
 
    public Board(int rowCount, int columnCount)
    {
        ROW_COUNT = rowCount;
        COL_COUNT = columnCount;
 
        cells = new Cell[ROW_COUNT][COL_COUNT];
        for (int row = 0; row < ROW_COUNT; row++) {
            for (int column = 0; column < COL_COUNT; column++) {
                cells[row][column] = new Cell(row, column);
            }
        }
    }
 
    public Cell[][] getCells()
    {
        return cells;
    }
 
    public void setCells(Cell[][] cells)
    {
        this.cells = cells;
    }
 
    public void generateFood()
    {
        System.out.println("Going to generate food");
        while(true){
            int row = (int)(Math.random() * ROW_COUNT);
            int column = (int)(Math.random() * COL_COUNT);
            if(cells[row][column].getCellType()!=CellType.SNAKE_NODE)
                 break;
        }
        cells[row][column].setCellType(CellType.FOOD);
        System.out.println("Food is generated at: " + row + " " + column);
    }
}

保存 Snake 和 Board 实例的主类(Game)。它的方法“update”需要以固定的时间间隔调用(在用户输入的帮助下)。

Java

// To represent Snake Game
public class Game {
 
    public static final int DIRECTION_NONE = 0, DIRECTION_RIGHT = 1,
    DIRECTION_LEFT = -1, DIRECTION_UP = 2, DIRECTION_DOWN = -2;
    private Snake snake;
    private Board board;
    private int direction;
    private boolean gameOver;
 
    public Game(Snake snake, Board board)
    {
        this.snake = snake;
        this.board = board;
    }
 
    public Snake getSnake()
    {
        return snake;
    }
 
    public void setSnake(Snake snake)
    {
        this.snake = snake;
    }
 
    public Board getBoard()
    {
        return board;
    }
 
    public void setBoard(Board board)
    {
        this.board = board;
    }
 
    public boolean isGameOver()
    {
        return gameOver;
    }
 
    public void setGameOver(boolean gameOver)
    {
        this.gameOver = gameOver;
    }
 
    public int getDirection()
    {
        return direction;
    }
 
    public void setDirection(int direction)
    {
        this.direction = direction;
    }
 
    // We need to update the game at regular intervals,
    // and accept user input from the Keyboard.
    public void update()
    {
        System.out.println("Going to update the game");
        if (!gameOver) {
            if (direction != DIRECTION_NONE) {
                Cell nextCell = getNextCell(snake.getHead());
 
                if (snake.checkCrash(nextCell)) {
                    setDirection(DIRECTION_NONE);
                    gameOver = true;
                }
                else {
                    snake.move(nextCell);
                    if (nextCell.getCellType() == CellType.FOOD) {
                        snake.grow();
                        board.generateFood();
                    }
                }
            }
        }
    }
 
    private Cell getNextCell(Cell currentPosition)
    {
        System.out.println("Going to find next cell");
        int row = currentPosition.getRow();
        int col = currentPosition.getCol();
 
        if (direction == DIRECTION_RIGHT) {
            col++;
        }
        else if (direction == DIRECTION_LEFT) {
            col--;
        }
        else if (direction == DIRECTION_UP) {
            row--;
        }
        else if (direction == DIRECTION_DOWN) {
            row++;
        }
 
        Cell nextCell = board.getCells()[row][col];
 
        return nextCell;
    }
 
    public static void main(String[] args)
    {
 
        System.out.println("Going to start game");
 
        Cell initPos = new Cell(0, 0);
        Snake initSnake = new Snake(initPos);
        Board board = new Board(10, 10);
        Game newGame = new Game(initSnake, board);
        newGame.gameOver = false;
        newGame.direction = DIRECTION_RIGHT;
 
        // We need to update the game at regular intervals,
        // and accept user input from the Keyboard.
 
        // here I have just called the different methods
        // to show the functionality
        for (int i = 0; i < 5; i++) {
            if (i == 2)
                newGame.board.generateFood();
            newGame.update();
            if (i == 3)
                newGame.direction = DIRECTION_RIGHT;
            if (newGame.gameOver == true)
                break;
        }
    }
}

参考:
http://massivetechinterview.blogspot.com/2015/10/snake-game-design.html