算法游戏玩法及汇总
本站的首要目标是效率,希望读者快速掌握算法,搞定面试笔试。
在这个基础之上,我还希望能让读者学习的过程尽可能有趣一些,如果是单纯地为了刷题应付面试,多少有点枯燥。
如果能让读者直观地感受到算法的魅力,发自内心地认为学习算法是一个探索的过程,那么就可以产生内驱力,不仅能提高学习效率,也能提升一点趣味性。
这年头找工作其实挺心累的,手撕算法又成了几乎所有技术岗的标配,那何不自己找点乐子呢?
经过调研,我认为把算法学习和游戏结合起来是个很好的思路。因为这样不仅有意思,而且还能让读者了解到算法在实际场景中的应用,可谓一举两得。
游戏化 vs 可视化
有了 可视化面板,为什么还需要算法游戏?
我有思考过这个问题,认为还是需要的,因为它们解决的问题不一样。
算法可视化面板回答这类问题:这段代码的执行过程是怎样的?这个变量 n
为什么要 +1,而不是 +2?
算法游戏回答这类问题:哪些实际场景中可以考虑使用这个算法?怎么用?
所以在我设计的游戏场景中,不是简单地将算法可视化出来,而是结合游戏场景,要求玩家灵活地组合数据结构和算法来完成任务,在游戏中体现算法的作用。
下面简单介绍一下本站配套游戏面板的使用方法。
游戏面板的用法
在面板右上方有一个全屏
面板左侧是游戏界面,右侧的上半部分是题目说明,下半部分是代码编辑器。你需要在代码编辑器中编写代码完成题目的要求,然后点击「提交」按钮将代码提交给游戏引擎运行,你可以与游戏交互,检验是否符合预期。
下面是一个「贪吃蛇」游戏面板,点击「Begin」按钮开始游戏后,蛇并不会移动,因为这道题目考察双链表的实际应用,需要你来完成贪吃蛇的移动逻辑。
你需要在代码编辑器中编写正确的算法让蛇移动,点击「提交」按钮将代码提交给游戏引擎,最后点击「Begin」按钮,游戏就会正常运行,这样就获得了一个可玩的小游戏:
参考解法:
// 游戏面板仅支持提交 JavaScript 代码
// Java 解法仅供参考,方便读者理解算法逻辑
public void move(List<Point> snake, String direction, Point foodPosition) {
Point currentHead = snake.get(0);
// 计算新头部位置
Point newHeadPos = new Point(currentHead.x, currentHead.y);
switch (direction) {
case "right":
newHeadPos.x += 1;
break;
case "left":
newHeadPos.x -= 1;
break;
case "up":
newHeadPos.y += 1;
break;
case "down":
newHeadPos.y -= 1;
break;
default:
throw new IllegalArgumentException("Invalid direction");
}
// 添加新的头部节点
snake.add(0, newHeadPos);
if (!newHeadPos.equals(foodPosition)) {
// 如果不是吃到食物,则删除尾部节点
snake.remove(snake.size() - 1);
}
}
// 游戏面板仅支持提交 JavaScript 代码
// C++ 解法仅供参考,方便读者理解算法逻辑
void move(vector<Point>& snake, const string& direction, const Point& foodPosition) {
Point currentHead = snake.front();
// 计算新头部位置
Point newHeadPos(currentHead.x, currentHead.y);
if (direction == "right") {
newHeadPos.x += 1;
} else if (direction == "left") {
newHeadPos.x -= 1;
} else if (direction == "up") {
newHeadPos.y += 1;
} else if (direction == "down") {
newHeadPos.y -= 1;
} else {
throw invalid_argument("Invalid direction");
}
// 添加新的头部节点
snake.insert(snake.begin(), newHeadPos);
if (!newHeadPos.equals(foodPosition)) {
// 如果不是吃到食物,则删除尾部节点
snake.pop_back();
}
}
# 游戏面板仅支持提交 JavaScript 代码
# python 解法仅供参考,方便读者理解算法逻辑
def move(snake, direction, food_position):
current_head = snake[0]
# 计算新头部位置
new_head_pos = Point(current_head.x, current_head.y)
if direction == 'right':
new_head_pos.x += 1
elif direction == 'left':
new_head_pos.x -= 1
elif direction == 'up':
new_head_pos.y += 1
elif direction == 'down':
new_head_pos.y -= 1
else:
raise ValueError('Invalid direction')
# 添加新的头部节点
snake.insert(0, new_head_pos)
if not new_head_pos.equals(food_position):
# 如果不是吃到食物,则删除尾部节点
snake.pop()
// 游戏面板仅支持提交 JavaScript 代码
// Go 解法仅供参考,方便读者理解算法逻辑
func move(snake *[]Point, direction string, foodPosition Point) {
currentHead := (*snake)[0]
// 计算新头部位置
newHeadPos := Point{X: currentHead.X, Y: currentHead.Y}
switch direction {
case "right":
newHeadPos.X += 1
case "left":
newHeadPos.X -= 1
case "up":
newHeadPos.Y += 1
case "down":
newHeadPos.Y -= 1
default:
panic("Invalid direction")
}
// 添加新的头部节点
*snake = append([]Point{newHeadPos}, *snake...)
if !newHeadPos.Equals(foodPosition) {
// 如果不是吃到食物,则删除尾部节点
*snake = (*snake)[:len(*snake)-1]
}
}
var move = function(snake, direction, foodPosition) {
const currentHead = snake[0]
// 计算新头部位置
const newHeadPos = new Point(currentHead.x, currentHead.y)
switch (direction) {
case 'right':
newHeadPos.x += 1
break
case 'left':
newHeadPos.x -= 1
break
case 'up':
newHeadPos.y += 1
break
case 'down':
newHeadPos.y -= 1
break
default:
throw new Error('Invalid direction')
}
// 添加新的头部节点
snake.unshift(newHeadPos)
if (!newHeadPos.equals(foodPosition)) {
// 如果不是吃到食物,则删除尾部节点
snake.pop()
}
}
游戏汇总
游戏章节散落在本站目录中(标有
游戏功能还在内测,我有很多有趣的设想,但目前只上线了一部分,更多有趣的游戏敬请期待~
贪吃蛇游戏
考察双链表的实际运用,详见 实现贪吃蛇游戏:
华容道
华容道游戏是 BFS 算法框架 中数字谜题的进阶问题,非常有意思,建议开启游戏 BGM 尝试求解。解法详见 实现华容道游戏:
连连看
连连看游戏会考察 BFS 算法,详见 实现连连看游戏:
一笔画游戏
一笔画游戏会考察欧拉图,详见 欧拉图和一笔画游戏:
扫雷游戏
扫雷游戏会考察多种算法。
首先考察随机算法,你需要掌握洗牌算法、水塘抽样算法,详见 实现扫雷游戏:
我们一般用蒙特卡洛方法验证随机算法的均匀性,网站也配套了一个蒙特卡洛验证器,可以把生成扫雷地图的随机算法输入进去进行验证:
扫雷游戏还可以考察 DFS 算法,详见 实现扫雷游戏 II:
你还可以思考一下,如何把扫雷游戏的求解过程写成算法,实现一个「扫雷作弊器」:
数独游戏
用回溯算法解决任意难度的数独题目,详见 实现数独游戏:
迷宫游戏
用 DFS/BFS 算法求解迷宫,详见 完成迷宫游戏:
用随机算法生成迷宫的地图,可以使用 DFS、最小生成树算法或递归切分算法:
生命游戏
生命游戏考察简单的数组操作以及位运算优化方法,详见 实现生命游戏: