我是HullQin,公众号线下聚会游戏的作者(欢迎关注公众号,发送加微信,交个朋友),转发本文前需获得作者HullQin授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费没广告。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我 HullQin 噢~我有空了会分享做游戏的相关技术。
1. 问题描述
《五子棋》游戏,如何判断输赢呢?
这个问题是不是很简单?适合给代码初学者练手。
但是如果你真的只想快速开发一个五子棋,常年混迹开发业务、多年没摸算法的你,的确可能会在这个问题上头疼。
因为目标不一样:代码初学者愿意花好几个小时在这上面优化算法,但业务开发者只想5分钟内解决掉这个问题。
今天,我们作为业务开发者,5分钟实现它。
输入
当前棋盘上的棋子分布信息,分布信息通常有2种存储方式,见上篇文章《《五子棋》怎么存棋局信息?》。本文采用的是文中2.6节的方案一:
- 用一个列表存储已落的棋子,列表顺序表明棋子顺序,列表每一项的值代表棋子的位置,值为0-224(刚好15*15=225个值),奇数位置是黑棋,偶数位置是白棋。
以这局为例:https://game.hullqin.cn/wzq/?p=000110112021303140
注意:网址参数中,是用15进制表示棋子的。每2位是一个棋子。
// 网址参数对应这样的输入数据:
const input = [0, 1, 15, 16, 30, 31, 45, 46, 60];
// 分别是 00 01 10 11 20 21 30 31 40 奇数位置是黑棋,偶数位置是白棋
输出
有3种可能:
- 黑棋赢
- 白棋赢
- 没人赢(游戏应该继续)
(当然也有诉求判断是否平局,但场景不多,本文不考虑这种判断是否平局的诉求。另外也因为我游戏中有认输功能,不会出现棋盘下满导致双方无法做任何操作的情况)
基本假设
有且仅有最后一手棋,导致某方五联珠胜利。
也就是说:
- 如果最后一手是黑棋,那么当前白棋一定没赢,只需要判断黑棋是否赢,就知道输出是1还是3。
- 如果最后一手是白棋,那么当前黑棋一定没赢,只需要判断白棋是否赢,就知道输出是2还是3。
这个基本假设,符合真实的五子棋场景。
2. 解决方案
2.1 五分钟方案
如果你觉得这个问题又简单又恶心,只想快速做完,可以这样做:
先找到最后一手棋的颜色,拿到该颜色棋子的集合:
const input = [0, 1, 15, 16, 30, 31, 45, 46, 60];
const pieces = input.filter((piece, index) => input.length % 2 !== index % 2);
console.log(pieces);
比如input.length
是奇数,表明最后一手是黑棋,筛选出input
的所有第偶数项(从0开始)都是黑棋。
然后遍历这个集合,看看它上下左右斜共8个方向,有没有5连珠,若有,则他赢;否则他没赢。
const input = [0, 1, 15, 16, 30, 31, 45, 46, 60];
const pieces = input.filter((piece, index) => input.length % 2 !== index % 2);
console.log(pieces);
const judge = (pieces) => {
const pieceSet = new Set(pieces);
for (let i = 0; i < pieces.length; i++) {
const piece = pieces[i];
if (piece % 15 >= 4 && pieceSet.has(piece - 1) && pieceSet.has(piece - 2) && pieceSet.has(piece - 3) && pieceSet.has(piece - 4)) return true;
if (piece % 15 <=