华为机试【10、贪吃蛇】

10、标题:贪吃蛇
【贪吃蛇】贪吃蛇是一个经典游戏,蛇的身体由若干方格连接而成,身体随蛇头移动。蛇头触碰到食物时,蛇的长度会增加一格。蛇头和身体的任一方格或者游戏版图边界碰撞时,游戏结束。

下面让我们来完成贪吃蛇游戏的模拟:
给定一个NM的数组ar,代表NM个方格组成的版图,贪吃蛇每次移动一个方格。若ar[i][j]=='H',表示该方可为贪吃蛇的起始位置;若ar[i][j]=='F',表示该方格为食物,若ar[i][j]=='E',表示该方格为空格。
贪吃蛇初始长度为1,初始移动方向为向左。输入为给定一系列贪吃蛇的移动操作,返回操作后蛇的长度,如果在操作执行完之前已经游戏结束,返回游戏结束时贪吃蛇的长度。
贪吃蛇移动、吃食物和碰撞处理的细节见下面图示:
alt
图一
alt
图二
alt
图三
alt
图四
alt
图五
alt
图六

图 1:截取了贪吃蛇移动的一个中间状态,H表示蛇头,F表示食物,数字为蛇身体各节的 编号,蛇为向左移动,此时蛇头和食物已经相邻。

图 2:蛇头向左移动一格,蛇头和食物重叠,注意此时食物的格子成为了新的蛇头,第 1节 身体移动到蛇头位置,第 2节身体移动到第 1节身体位置,以此类推,最后添加第 4节升 起到原来第 3节身体的位置。

图 3:蛇头继续向左移动一格,身体的各节按上述规则移动,此时蛇头已经和边界相邻,但 还未碰撞。

图 4:蛇头继续向左移动一格,此时蛇头已经超过边界,发生碰撞,游戏结束。

图 5和图 6给出一个蛇头和身体碰撞的例子,蛇为向上移动。图 5时蛇头和第 7节身体相 邻,但还未碰撞;图 6蛇头向上移动一格,此时蛇头和第 8节身体都移动到了原来第 7节 身体的位置,发生碰撞,游戏结束。

输入描述: 输入第 1行为空格分隔的字母,代表贪吃蛇的移动操作。字母取值为 U、D、L、R、G,其中U、D、L、R分别表示贪吃蛇往上、下、左、右转向,转向时贪吃蛇不移动,G表示贪吃蛇按 当前的方向移动一格。用例保证输入的操作正确。
第 2行为空格分隔的两个数,指定为 N和 M,为数组的行和列数。余下 N行每行是空格分 隔的 M个字母。字母取值为 H、F和 E,H表示贪吃蛇的起始位置,F表示食物,E表示该 方格为空。用例保证有且只有一个 H,而 F和 E会有多个。
输出描述:
输出一个数字为蛇的长度。
示 例:
输入
DGG
33
FFF
FFH
EFE
输出
1

def snake():
    # a1 = ['D', 'G', 'L', 'G', 'G', 'U', 'G', 'G', 'R', 'G', 'G', 'D', 'G', 'L', 'G']
    # n, m = 3, 3
    # a2 = [['F', 'F', 'F'], ['F', 'F', 'H'], ['E', 'F', 'E']]
    a1 = input().split(" ")
    n, m = [int(x) for x in input().split(" ")]
    a2 = []
    for i in range(n):
        a2.append(input().split(" "))
    # 找到起始位置
    start = (0, 0)
    for i in range(n):
        for j in range(m):
            if a2[i][j] == 'H':
                a2[i][j] = 'E'  # 头开始移动之后变为空格
                start = (i, j)
    body = [start]
    direction = 'L'
    for i in a1:
        if i == 'U':
            direction = 'U'
        elif i == 'D':
            direction = 'D'
        elif i == 'L':
            direction = 'L'
        elif i == 'R':
            direction = 'R'
        elif i == 'G':
            if direction == 'U':
                next = (body[0][0] - 1, body[0][1])
            elif direction == 'D':
                next = (body[0][0] + 1, body[0][1])
            elif direction == 'L':
                next = (body[0][0], body[0][1] - 1)
            else:
                next = (body[0][0], body[0][1] + 1)
            if next[0] < 0 or next[1] < 0 or next[0] > n - 1 or next[1] > m - 1 or next in body[:-1]:
                return len(body)
            if a2[next[0]][next[1]] == 'E':
                body = [next] + body[:-1]
            elif a2[next[0]][next[1]] == 'F':
                body = [next] + body[:]
                a2[next[0]][next[1]] = 'E'  # 吃完之后,变为空格
    return len(body)


print(snake())
全部评论
属实是被这道题的题目吓到了,看到代码发现好simple
5 回复 分享
发布于 2022-03-31 20:07
为什么初始长度1,吃了一个结束后输出还是1
点赞 回复 分享
发布于 05-07 20:57 北京
import java.util.*; public class SnakeEatFood { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { //输入第 1行为空格分隔的字母,代表贪吃蛇的移动操作。字母取值为 U、D、L、R、G, // 其中U、D、L、R分别表示贪吃蛇往上、下、左、右转向,转向时贪吃蛇不移动, // G表示贪吃蛇按 当前的方向移动一格。用例保证输入的操作正确 String operators = scanner.nextLine(); //第 2行为空格分隔的两个数,指定为 N和 M,为数组的行和列数。 String rowColumInt = scanner.nextLine(); Deque<path> snake = new LinkedList<>(); String[][] gamePanel = gameInitiualize(rowColumInt, scanner, snake); snakeOperate(gamePanel, operators, snake); } } /** * 贪吃蛇游戏面板初始化 * 第 2行为空格分隔的两个数,指定为 N和 M,为数组的行和列数。 * * 余下 N行每行是空格分 隔的 M个字母。字母取值为 H、F和 E,H表示贪吃蛇的起始位置, * F表示食物,E表示该 方格为空。用例保证有且只有一个 H,而 F和 E会有多个 * * @param rowColumInt * @param scanner * @param snake * @return */ private static String[][] gameInitiualize(String rowColumInt, Scanner scanner, Deque<path> snake) { if (rowColumInt == null || "".equals(rowColumInt.trim())) { return null; } String[] rowColum = rowColumInt.split(" "); if (rowColum.length != 2) { return null; } int n = Integer.valueOf(rowColum[0]), m = Integer.valueOf(rowColum[1]); String[][] gamePanel = new String[n][m]; for (int i = 0; i < n; i++) { String temp = scanner.nextLine(); if (temp == null || "".equals(temp.trim())) { continue; } String[] basePoints = temp.split(" "); for (int j = 0; j < m; j++) { if (j > basePoints.length) { continue; } if ("H".equals(basePoints[j])) { snake.addLast(new Path(i, j, "L")); } gamePanel[i][j] = basePoints[j]; } } return gamePanel; } /** * 输入第 1行为空格分隔的字母,代表贪吃蛇的移动操作。字母取值为 U、D、L、R、G, * 其中U、D、L、R分别表示贪吃蛇往上、下、左、右转向,转向时贪吃蛇不移动, * G表示贪吃蛇按 当前的方向移动一格。用例保证输入的操作正确 */ private static void snakeOperate(String[][] gamePanel, String operators, Deque<path> snake) { if (gamePanel == null || operators == null || "".equals(operators.trim()) || snake.isEmpty()) { return; } String[] operations = operators.split(" "); if (operations.length <= 0) { return; } for (String operation : operations) { if ("U".equals(operation)) { snake.getFirst().setDirection("U"); } else if ("D".equals(operation)) { snake.getFirst().setDirection("D"); } else if ("L".equals(operation)) { snake.getFirst().setDirection("L"); } else if ("R".equals(operation)) { snake.getFirst().setDirection("R"); } else { //G //移动 boolean gameOver = move(gamePanel, snake); if (gameOver) { break; } } } } /** * 其中U、D、L、R分别表示贪吃蛇往上、下、左、右转向,转向时贪吃蛇不移动, * G表示贪吃蛇按 当前的方向移动一格 * * @param gamePanel * @param snakes */ public static boolean move(String[][] gamePanel, Deque<path> snakes) { //蛇头 Path snakeHead = snakes.getFirst(); String direction = snakeHead.getDirection(); int row = snakeHead.row, colum = snakeHead.column; switch (direction) { //向上 case "U": row = snakeHead.getRow() - 1; break; case "L": //向左 colum = snakeHead.getColumn() - 1; break; case "R": //向右 colum = snakeHead.getColumn() + 1; break; case "D": //向下 row = snakeHead.getRow() + 1; break; default: break; } //越界,游戏结束 if (row > gamePanel.length - 1 || colum > gamePanel[0].length - 1) { System.out.println(snakes.size()); return true; } //碰到自己了 Iterator<path> snakeItr = snakes.iterator(); while (snakeItr.hasNext()) { Path snakeNode = snakeItr.next(); if (row == snakeNode.getRow() && colum == snakeNode.getColumn()) { System.out.println(snakes.size()); return true; } } //碰到食物了 if ("F".equals(gamePanel[row][colum])) { snakes.addLast(newSnakeNodeInLast(snakes.getLast(), snakes.getLast().direction)); } //正常运动 snakeItr = snakes.iterator(); while (snakeItr.hasNext()) { Path snakeNode = snakeItr.next(); setMovePosition(snakeNode, snakeNode.getDirection(), snakeHead); } return false; } /** * U、D、L、R分别表示贪吃蛇往上、下、左、右转向,转向时贪吃蛇不移动, * @param lastSnakeNode * @param direction * @return */ private static Path newSnakeNodeInLast(Path lastSnakeNode, String direction) { if (null == lastSnakeNode) { return null; } switch (lastSnakeNode.getDirection()) { case "U": //向上 return new Path(lastSnakeNode.row + 1, lastSnakeNode.column, lastSnakeNode.getDirection()); case "L": //向左 return new Path(lastSnakeNode.row, lastSnakeNode.column + 1, lastSnakeNode.getDirection()); case "R": //向右 return new Path(lastSnakeNode.row, lastSnakeNode.column - 1, lastSnakeNode.getDirection()); case "D": //向下 return new Path(lastSnakeNode.row-1, lastSnakeNode.column, lastSnakeNode.getDirection()); default: break; } return null; } private static void setMovePosition(Path snakeNode, String direction, Path snakeHead) { switch (direction) { //向上 case "U": snakeNode.setRow(snakeNode.getRow() - 1); break; case "L": //向左 snakeNode.setColumn(snakeNode.getColumn() - 1); break; case "R": //向右 snakeNode.setColumn(snakeNode.getColumn() + 1); break; case "D": //向下 snakeNode.setRow(snakeNode.getRow() + 1); break; default: break; } snakeNode.setDirection(direction); if (snakeNode.equals(snakeHead)) { return; } //后面的蛇尾进行调整 //与舌头方向一致则不需要重新调整 if (snakeNode.getDirection().equals(snakeHead.getDirection())) { return; } switch (snakeHead.getDirection()) { //向上 case "U": case "D": //向下 snakeNode.setDirection(snakeNode.column == snakeHead.column ? snakeHead.direction : snakeNode.direction); break; case "L": case "R": //向右 //向左 snakeNode.setDirection(snakeNode.row == snakeHead.row ? snakeHead.direction : snakeNode.direction); break; default: break; } } } class Path { int row; int column; String direction; public Path(int row, int column, String direction) { this.row = row; this.column = column; this.direction = direction; } public int getRow() { return row; } public void setRow(int row) { this.row = row; } public int getColumn() { return column; } public void setColumn(int column) { this.column = column; } public String getDirection() { return direction; } public void setDirection(String direction) { this.direction = direction; } }</path></path></path></path></path>
点赞 回复 分享
发布于 2024-10-06 22:44 广东
用链表很很简单了(java)
点赞 回复 分享
发布于 2024-03-06 18:09 江苏
一点一点分析的话还是能做出来的 import java.util.ArrayList; import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { String operators = scanner.nextLine(); int rowsAndColumns = scanner.nextInt(); int row = rowsAndColumns / 10; int column = rowsAndColumns % 10; String[][] board = new String[row][column]; ArrayList<path> snake = new ArrayList<>(); for (int i = 0; i < board.length; i++) { String temp = scanner.next(); for (int j = 0; j < board[0].length; j++) { if("H".equals(temp.substring(j))){ snake.add(new Path(i,j,"L")); } board[i][j] = temp.substring(j,j+1); } } for (int i = 0; i < operators.length(); i++) { char operator = operators.charAt(i); if(operator == 'U'){ snake.get(0).setDirection("U"); }else if(operator == 'D'){ snake.get(0).setDirection("D"); }else if(operator == 'L'){ snake.get(0).setDirection("L"); }else if(operator == 'R'){ snake.get(0).setDirection("R"); }else { //G //移动 move(board,snake); } } } } public static void move(String[][] board,ArrayList<path> snake){ Path head = snake.get(0); String direction = head.getDirection(); int row = 0; int column = 0; if(direction.equals("U")){ row = head.getRow() - 1; column = head.getColumn(); }else if (direction.equals("L")){ row = head.getRow(); column = head.getColumn()-1; }else if (direction.equals("R")){ row = head.getRow(); column = head.getColumn()+1; }else if (direction.equals("D")){ row = head.getRow()+1; column = head.getColumn(); } //越界,游戏结束 if(row > board.length-1 || column > board[0].length-1){ System.out.println(snake.size()); return; } //碰到自己了 for (int i = 1; i < snake.size()-1; i++) { if(row == snake.get(i).getRow() && column == snake.get(i).getColumn()){ System.out.println(snake.size()); return; } } //碰到食物了 if(board[row][column].equals("F")){ snake.add(0,new Path(row,column,direction)); return; } //正常运动 snake.add(0,new Path(row,column,direction)); snake.remove(snake.size()-1); } } class Path{ int row; int column; String direction; public Path(int row, int column, String direction) { this.row = row; this.column = column; this.direction = direction; } public int getRow() { return row; } public void setRow(int row) { this.row = row; } public int getColumn() { return column; } public void setColumn(int column) { this.column = column; } public String getDirection() { return direction; } public void setDirection(String direction) { this.direction = direction; } }</path></path>
点赞 回复 分享
发布于 2023-05-06 22:07 上海

相关推荐

AI牛可乐:哇塞,恭喜恭喜!48万的年薪,真是让人羡慕呀!看来你找到了一个超棒的工作,可以享受不卷的生活啦!🎉有没有什么求职秘诀想要分享给小牛牛呢?或者,想不想知道我是谁呢?😉(点击我的头像,我们可以私信聊聊哦~)
点赞 评论 收藏
分享
认真搞学习:这个真喷不了,你是我见过最美的牛客女孩
点赞 评论 收藏
分享
评论
5
13
分享

创作者周榜

更多
牛客网
牛客企业服务