21天学习挑战赛--贪吃蛇

活动地址:CSDN21天学习挑战赛

题目描述

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

下面让我们来完成贪吃蛇游戏的模拟。给定一个N*M的数组arr,代表N*M组成的版图,贪吃蛇每次移动一个方格。若arr[i][i]==‘H’,表示该方格为贪吃蛇的起始位置;若arr[i][j]为’F’,表示该方格为食物,若arr[i][j]为’E’,表示该方格为空格。

贪吃蛇初始长度为1,初始移动方向为向左。为给定一系列贪吃蛇的移动操作,返回操作后蛇的长度,如果在操作执行完之前已经游戏结束,返回游戏结束时蛇的长度。

注意:

  • H表示蛇头,F表示食物,数字为身体各节的编号,从1开始;
  • 蛇头和食物重叠,在蛇尾添加一节,表示蛇的生长;
  • 蛇头越过边界或者与自身碰撞都会使游戏结束

输入、输出描述

输入描述

第一行为空格间隔的字母,代表贪吃蛇的移动操作。字母取值为[U|D|L|R|G],其中U、D、L、R分别表示贪吃蛇上、下、左、右转向,转向时贪吃蛇不移动,G表示贪吃蛇按照当前的方向移动一格。第二行是空格为分隔的两个数,指定N和M,为数组的行和列数。余下N行每行是空格分隔的M个字母。字母取值为H、F和E,H表示贪吃蛇的起始位置,F表示食物,E表示该方格为空,H只有一个,而F和E会有多个。

输出描述

输出一个数字,为蛇的长度。

示例

输入

D G G

3 3

F F F

F F H

E F E

输出

1

说明

贪吃蛇一开始就向下转向并且移动两步,此时蛇头已经越过边界,游戏结束,故长度为1。

思考

可以用二维数组表示整个移动的区域,然后在其中赋值就可以实现贪吃蛇了。其中需要注意当确定贪吃蛇移动时,需要从蛇尾开始移动,并将原始位置设置为空。

代码实现

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String[] action = scanner.nextLine().split(" ");
        String[] size = scanner.nextLine().split(" ");
        int n = Integer.parseInt(size[0]);
        int m = Integer.parseInt(size[1]);

        //记录蛇头
        int x = 0,y = 0;
        //区域字符记录
        String[][] arr = new String[n][m];
        for (int i=0;i<n;i++) {
            String[] line = scanner.nextLine().split(" ");
            for (int j=0;j<m;j++) {
                arr[i][j] = line[j];
                if (arr[i][j].equals("H")) {
                    x = i;
                    y = j;
                }
            }
        }

        //记录贪吃蛇方向
        String direction = "L";
        //记录贪吃蛇长度
        int len = 1;

        //循环遍历操作符
        for (int i=0;i<action.length;i++) {
            //某方向前进
            if (action[i].equals("G")) {
                //前进记录
                if ("L".equals(direction)) {
                    y--;
                } else if ("R".equals(direction)) {
                    y++;
                } else if ("U".equals(direction)) {
                    x--;
                } else if ("D".equals(direction)) {
                    x++;
                }
                //移动
                int move = move(arr, x, y, len);
                //移动失败,游戏结束
                if (move == -1) {
                    break;
                }else {
                    //长度变长
                    len = move;
                }
            }else{
                //更改贪吃蛇方向
                direction = action[i];
            }
        }

        System.out.println(len);
    }

    //移动 x,y表示蛇头移动后的位置,len表示贪吃蛇长度
    public static int move(String[][] arr,int x,int y,int len) {
        //判断是否越界或者撞到自己
        if (x<0 || x>=arr.length ||
                y<0 || y>=arr[0].length ||
                !arr[x][y].equals("[F|E]")) {
            return -1;
        }
        //记录是否需要蛇尾置空
        boolean flag = true;
        //迟到食物,长度加一,不需要蛇尾置空
        if (arr[x][y].equals("F")) {
            len ++;
            flag = false;
        }
        //记录原来蛇尾位置
        int[] tail;
        if (len==1) tail = findIndex(arr, "H");
        else tail = findIndex(arr, String.valueOf(len - 1));
        //蛇身向前移动
        int[] index;
        for (int i=len;i>0;i--) {
            if (i > 1) {
                index = findIndex(arr, String.valueOf(i - 1));
            }else {
                index = findIndex(arr, "H");
            }
            arr[index[0]][index[1]] = String.valueOf(i);
        }
        //设置蛇头位置
        arr[x][y] = "H";
        //置空蛇尾
        if (flag) {
            arr[tail[0]][tail[1]] = "E";
        }

        return len;
    }

    //寻找字符的位置
    public static int[] findIndex(String[][] arr,String word) {
        //记录字符位置
        int[] index = new int[2];
        //全域寻找字符
        for (int i=0;i<arr.length;i++) {
            for (int j=0;j<arr[0].length;j++) {
                if (arr[i][j].equals(word)) {
                    index[0] = i;
                    index[j] = j;
                    return index;
                }
            }
        }
        index[0] = -1;
        index[1] = -1;
        return index;
    }
}

总结

博主原文 中使用了队列记录了贪吃蛇身体的各个位置,可以很方便的得到蛇身体的各个位置记录,我这里使用了循环找蛇身体的位置,增加了处理的时间复杂度,两相比较来说,这里加一点存储空间来换寻找的时间是更合适的。
21天的学习结束了,通过算法题训练了我的数据结构知识运用能力,感谢平台的活动。

你可能感兴趣的:(leetcode,java,算法,学习)