这两天刷到一个吐槽:新上任的行政同学,手一抖,把领导的“私密吐槽”同步进了500人的全员大群。那种感觉我觉得跟线上把生产库密码贴到公告栏差不多,心跳直接起飞。
群里前一秒还在“收到”,后一秒集体静音,安静到像服务器宕机。最惨的是领导,当天就被老板叫去“喝茶”。
当事人已经开始脑补离职流程了:工牌交哪、电脑要不要格式化、午餐券还能不能用。
结果领导居然扛住了,没把锅甩回来,私下只丢了一句:“职场里,有些错,一次就够了。”我觉得这话比KPI还管用——以后发任何东西前,先检查三遍收件人,别让手滑变成全员围观的年度大戏。
昨天群里有人问我“贪吃蛇这题咋写啊,看着像小游戏,结果一上来就一堆坑”…我当时正排队买奶茶,脑子里还在想加不加珍珠,手一抖点成了去冰全糖,行吧,既然甜都吃了那就顺便把蛇也写了。
这题吧,别把它当“画面”,就当成“坐标搬运工”。蛇身是一串格子坐标,头往前怼一下,正常情况尾巴就往前挪一下;但如果这一步吃到了食物,尾巴就别动,相当于长度+1。最阴的是“撞自己”判断:因为尾巴可能会动走,你如果先判断占用再移尾巴,会把“踩到刚刚要移走的尾巴”误判成撞自己,哎这坑我也踩过,别问,问就是当年我也年轻。
所以做法就很直白:用 Deque 存蛇身,头在队尾(或者队首都行你别搞混),再用 HashSet 存占用格子做 O(1) 碰撞。每次 move: 1)算新头坐标 2)如果没吃到食物:先把尾巴弹出,并从 set 里删掉(关键!先腾位置) 3)再检查新头是不是越界/撞 set 4)把新头塞进去、set 加进去 5)如果吃到食物:分数+1,食物指针往后挪(尾巴那步本来就没动)
核心代码我给个能跑的骨架,别整花里胡哨 GUI 了,面试官也不看你画得像不像蛇,他看你会不会死:
import java.util.*;/** 经典贪吃蛇模拟:move 返回当前得分,撞墙/撞自己返回 -1 */publicclassSnakeGame{privatefinalint width, height;privatefinalint[][] food;privateint foodIdx = 0;// 蛇身:这里用队列,队头=尾巴,队尾=脑袋privatefinal Deque<Integer> body = new ArrayDeque<>();privatefinal Set<Integer> occ = new HashSet<>();// 方向映射privatestaticfinal Map<Character, int[]> DIR = new HashMap<>();static { DIR.put('U', newint[]{-1, 0}); DIR.put('D', newint[]{ 1, 0}); DIR.put('L', newint[]{ 0,-1}); DIR.put('R', newint[]{ 0, 1}); }publicSnakeGame(int width, int height, int[][] food){this.width = width;this.height = height;this.food = food == null ? newint[0][0] : food;// 初始蛇在 (0,0)int start = encode(0, 0); body.addLast(start); occ.add(start); }publicintmove(String direction){if (direction == null || direction.isEmpty()) return score();char d = direction.charAt(0);int[] delta = DIR.get(d);if (delta == null) return -1; // 非法方向就当结束,省得扯皮int head = body.peekLast();int hr = head / width, hc = head % width;int nr = hr + delta[0];int nc = hc + delta[1];// 先判断是否吃到食物boolean eat = (foodIdx < food.length && food[foodIdx][0] == nr && food[foodIdx][1] == nc);// 不吃就先挪尾巴,给“踩尾巴那格”留条活路if (!eat) {int tail = body.pollFirst(); occ.remove(tail); }// 撞墙if (nr < 0 || nr >= height || nc < 0 || nc >= width) return -1;int nh = encode(nr, nc);// 撞自己(注意:尾巴已经可能被移走了)if (occ.contains(nh)) return -1;// 进位:新头入队 body.addLast(nh); occ.add(nh);if (eat) foodIdx++;return score(); }privateintscore(){return body.size() - 1; // 初始长度1,得分从0算 }privateintencode(int r, int c){return r * width + c; }}
你看,整题就一个“先移尾巴再判撞自己”的小心机,别的都挺朴素。哦对了,编码坐标那块我用 r*width+c,别用 r*10000+c 这种“我感觉够大”,面试官一听就知道你经常靠感觉写线上,哈哈…行我不毒舌了。
反正你把这个骨架背下来,再自己手敲两遍,基本就稳了。哎我奶茶也快喝完了,等会儿血糖飙了我还得去走两圈…要不然我也像蛇一样撞墙了。