棋子合法移动
Chess piece legal moves
我用 vue.js
做了一个国际象棋游戏,现在我想弄清楚每一个棋子的可能走法。我能够修复 knight, pawn and bishop
.
的合法移动验证
在处理主教验证时,我遇到了一个问题。就是可以验证,如果有一块站在主教面前。
请看图片了解更多。
你看红色的数字是如何越过棋子继续向上的。它应该停在典当人偶处。
这是我的主教计算代码。如果可能的话,如果你也能为女王提供验证,其他的部分将非常有帮助。
var el = { };
// sample Data
el.whiteMoves = [{"x":1,"y":1,"type":"Rook1","name":"1A","cleanType":"rook"},{"x":8,"y":1,"type":"Rook2","name":"1H","cleanType":"rook"},{"x":2,"y":1,"type":"Knight1","name":"1B","cleanType":"knight"},{"x":7,"y":1,"type":"Knight2","name":"1G","cleanType":"knight"},{"x":3,"y":1,"type":"Bishop1","name":"1C","cleanType":"bishop"},{"x":6,"y":1,"type":"Bishop2","name":"1F","cleanType":"bishop"},{"x":4,"y":1,"type":"Queen","name":"1D","cleanType":"queen"},{"x":5,"y":1,"type":"King","name":"1E","cleanType":"king"},{"x":1,"y":2,"type":"Pawn1","name":"2A","cleanType":"pawn"},{"x":2,"y":2,"type":"Pawn2","name":"2B","cleanType":"pawn"},{"x":3,"y":2,"type":"Pawn3","name":"2C","cleanType":"pawn"},{"x":4,"y":2,"type":"Pawn4","name":"2D","cleanType":"pawn"},{"x":5,"y":2,"type":"Pawn5","name":"2E","cleanType":"pawn"},{"x":6,"y":2,"type":"Pawn6","name":"2F","cleanType":"pawn"},{"x":7,"y":2,"type":"Pawn7","name":"2G","cleanType":"pawn"},{"x":8,"y":2,"type":"Pawn8","name":"2H","cleanType":"pawn"}];
el.blackMoves = [{"x":1,"y":8,"type":"Rook1","name":"8A","cleanType":"rook"},{"x":8,"y":8,"type":"Rook2","name":"8H","cleanType":"rook"},{"x":2,"y":8,"type":"Knight1","name":"8B","cleanType":"knight"},{"x":7,"y":8,"type":"Knight2","name":"8G","cleanType":"knight"},{"x":3,"y":8,"type":"Bishop1","name":"8C","cleanType":"bishop"},{"x":6,"y":8,"type":"Bishop2","name":"8F","cleanType":"bishop"},{"x":4,"y":8,"type":"Queen","name":"8D","cleanType":"queen"},{"x":5,"y":8,"type":"King","name":"8E","cleanType":"king"},{"x":1,"y":7,"type":"Pawn1","name":"7A","cleanType":"pawn"},{"x":2,"y":7,"type":"Pawn2","name":"7B","cleanType":"pawn"},{"x":3,"y":7,"type":"Pawn3","name":"7C","cleanType":"pawn"},{"x":4,"y":7,"type":"Pawn4","name":"7D","cleanType":"pawn"},{"x":5,"y":7,"type":"Pawn5","name":"7E","cleanType":"pawn"},{"x":6,"y":7,"type":"Pawn6","name":"7F","cleanType":"pawn"},{"x":7,"y":7,"type":"Pawn7","name":"7G","cleanType":"pawn"},{"x":8,"y":7,"type":"Pawn8","name":"7H","cleanType":"pawn"}]
el.rank = ["A", "B", "C", "D", "E", "F", "G", "H"];
var result = []
type = "white";
piece= "bishop";
var x = 5;
var y = 1;
var v = {
// the validation methods
bishop: function () {
var offSet = [];
for (var i = 1; i <= 8; i++) {
if (x + i < 8 && y + i < 8)
offSet.push({ x: x + i, y: y + i });
if (x + i < 8 && y - i < 8)
offSet.push({ x: x + i, y: y - i });
if (x - i < 8 && y + i < 8)
offSet.push({ x: x - i, y: y + i });
if (x - i < 8 && y - i < 8)
offSet.push({ x: x - i, y: y - i });
}
if (type == "white")
result = offSet.flatMap((item) => item.y + el.rank[item.x]).filter((item) => el.whiteMoves.filter((x) => x.name == item).length <= 0);
else result = offSet.flatMap((item) => item.y + el.rank[item.x]).filter((item) => el.blackMoves.filter((x) => x.name == item).length <= 0);
return result;
}
}
v[piece]();
// there is some invalid values like -5A or NaN but its not a problem these will be removed later on
console.log(result);
您的 for
循环根本不包含检测碰撞的代码。它一直走到棋盘的边缘。考虑将循环分成四个单独的 for
循环,每个循环在板的边缘或检测到碰撞时终止。同色棋子(非法走子)或异色棋子(夺取)需要分别处理碰撞。
var dx = +1, dy = +1;
do {
x += dx;
y += dy;
// Running into any color piece terminates the loop.
// However, running into an opposite color piece adds one last legal move.
var onBoard = (x >= 0) && (x < 8) && (y >= 0) && (y < 8);
var samePiece = onBoard ? (detect_collision_with_same_color_piece) : false;
var oppPiece = onBoard ? (detect_collision_with_opp_color_piece) : false;
if (onBoard && !samePiece) {
offSet.push({ x: x, y: y });
}
} while (onBoard && !samePiece && !oppPiece);
很难提供准确的碰撞检测代码,所以我在那里留下了一些占位符。一些额外的想法:
- 显然,您应该参数化
dx
和 dy
以循环遍历所有 +1 和 -1 组合,这样您就不会重复上面的代码四次。
- 如果内存不是问题,您可以在矩阵的所有四个边上填充一些特殊值,这样您就不需要每次都检查
x
和 y
的正确性.例如,如果要走白棋,你用白棋填满矩阵,那么你可以把onBoard
一起去掉;当 samePiece
变为真时,循环将终止。这确实会将您的棋盘从 64 个方块增加到 100 个,这在您添加换位表后可能会很重要。
- 更好的是,考虑看看 rotated bitboards,这是一种完全不同且更快的移动生成方法。
我用 vue.js
做了一个国际象棋游戏,现在我想弄清楚每一个棋子的可能走法。我能够修复 knight, pawn and bishop
.
在处理主教验证时,我遇到了一个问题。就是可以验证,如果有一块站在主教面前。
请看图片了解更多。
你看红色的数字是如何越过棋子继续向上的。它应该停在典当人偶处。
这是我的主教计算代码。如果可能的话,如果你也能为女王提供验证,其他的部分将非常有帮助。
var el = { };
// sample Data
el.whiteMoves = [{"x":1,"y":1,"type":"Rook1","name":"1A","cleanType":"rook"},{"x":8,"y":1,"type":"Rook2","name":"1H","cleanType":"rook"},{"x":2,"y":1,"type":"Knight1","name":"1B","cleanType":"knight"},{"x":7,"y":1,"type":"Knight2","name":"1G","cleanType":"knight"},{"x":3,"y":1,"type":"Bishop1","name":"1C","cleanType":"bishop"},{"x":6,"y":1,"type":"Bishop2","name":"1F","cleanType":"bishop"},{"x":4,"y":1,"type":"Queen","name":"1D","cleanType":"queen"},{"x":5,"y":1,"type":"King","name":"1E","cleanType":"king"},{"x":1,"y":2,"type":"Pawn1","name":"2A","cleanType":"pawn"},{"x":2,"y":2,"type":"Pawn2","name":"2B","cleanType":"pawn"},{"x":3,"y":2,"type":"Pawn3","name":"2C","cleanType":"pawn"},{"x":4,"y":2,"type":"Pawn4","name":"2D","cleanType":"pawn"},{"x":5,"y":2,"type":"Pawn5","name":"2E","cleanType":"pawn"},{"x":6,"y":2,"type":"Pawn6","name":"2F","cleanType":"pawn"},{"x":7,"y":2,"type":"Pawn7","name":"2G","cleanType":"pawn"},{"x":8,"y":2,"type":"Pawn8","name":"2H","cleanType":"pawn"}];
el.blackMoves = [{"x":1,"y":8,"type":"Rook1","name":"8A","cleanType":"rook"},{"x":8,"y":8,"type":"Rook2","name":"8H","cleanType":"rook"},{"x":2,"y":8,"type":"Knight1","name":"8B","cleanType":"knight"},{"x":7,"y":8,"type":"Knight2","name":"8G","cleanType":"knight"},{"x":3,"y":8,"type":"Bishop1","name":"8C","cleanType":"bishop"},{"x":6,"y":8,"type":"Bishop2","name":"8F","cleanType":"bishop"},{"x":4,"y":8,"type":"Queen","name":"8D","cleanType":"queen"},{"x":5,"y":8,"type":"King","name":"8E","cleanType":"king"},{"x":1,"y":7,"type":"Pawn1","name":"7A","cleanType":"pawn"},{"x":2,"y":7,"type":"Pawn2","name":"7B","cleanType":"pawn"},{"x":3,"y":7,"type":"Pawn3","name":"7C","cleanType":"pawn"},{"x":4,"y":7,"type":"Pawn4","name":"7D","cleanType":"pawn"},{"x":5,"y":7,"type":"Pawn5","name":"7E","cleanType":"pawn"},{"x":6,"y":7,"type":"Pawn6","name":"7F","cleanType":"pawn"},{"x":7,"y":7,"type":"Pawn7","name":"7G","cleanType":"pawn"},{"x":8,"y":7,"type":"Pawn8","name":"7H","cleanType":"pawn"}]
el.rank = ["A", "B", "C", "D", "E", "F", "G", "H"];
var result = []
type = "white";
piece= "bishop";
var x = 5;
var y = 1;
var v = {
// the validation methods
bishop: function () {
var offSet = [];
for (var i = 1; i <= 8; i++) {
if (x + i < 8 && y + i < 8)
offSet.push({ x: x + i, y: y + i });
if (x + i < 8 && y - i < 8)
offSet.push({ x: x + i, y: y - i });
if (x - i < 8 && y + i < 8)
offSet.push({ x: x - i, y: y + i });
if (x - i < 8 && y - i < 8)
offSet.push({ x: x - i, y: y - i });
}
if (type == "white")
result = offSet.flatMap((item) => item.y + el.rank[item.x]).filter((item) => el.whiteMoves.filter((x) => x.name == item).length <= 0);
else result = offSet.flatMap((item) => item.y + el.rank[item.x]).filter((item) => el.blackMoves.filter((x) => x.name == item).length <= 0);
return result;
}
}
v[piece]();
// there is some invalid values like -5A or NaN but its not a problem these will be removed later on
console.log(result);
您的 for
循环根本不包含检测碰撞的代码。它一直走到棋盘的边缘。考虑将循环分成四个单独的 for
循环,每个循环在板的边缘或检测到碰撞时终止。同色棋子(非法走子)或异色棋子(夺取)需要分别处理碰撞。
var dx = +1, dy = +1;
do {
x += dx;
y += dy;
// Running into any color piece terminates the loop.
// However, running into an opposite color piece adds one last legal move.
var onBoard = (x >= 0) && (x < 8) && (y >= 0) && (y < 8);
var samePiece = onBoard ? (detect_collision_with_same_color_piece) : false;
var oppPiece = onBoard ? (detect_collision_with_opp_color_piece) : false;
if (onBoard && !samePiece) {
offSet.push({ x: x, y: y });
}
} while (onBoard && !samePiece && !oppPiece);
很难提供准确的碰撞检测代码,所以我在那里留下了一些占位符。一些额外的想法:
- 显然,您应该参数化
dx
和dy
以循环遍历所有 +1 和 -1 组合,这样您就不会重复上面的代码四次。 - 如果内存不是问题,您可以在矩阵的所有四个边上填充一些特殊值,这样您就不需要每次都检查
x
和y
的正确性.例如,如果要走白棋,你用白棋填满矩阵,那么你可以把onBoard
一起去掉;当samePiece
变为真时,循环将终止。这确实会将您的棋盘从 64 个方块增加到 100 个,这在您添加换位表后可能会很重要。 - 更好的是,考虑看看 rotated bitboards,这是一种完全不同且更快的移动生成方法。