By menji40ji26
Question: How to check if chess pieces are being surrounded in Go?
Rule: If the local group of chess pieces does not have any Liberty(The connecting space that has not been occupied by opponent’s piece), this one or this group of chess pieces would be removed.
This is the rule of Gconnect which uses the same capture method as Go. Could anyone please shed some light on what to do capture detection in JavaScript? Thanks!
This is my code, which does not work:
let grid;
let rows;
let cols;
//Add a state machine;
let whosTurn;
let winner;
let bKoList;
let wKoList;
//Testing
let wStones;
let wDead;
function setup() {
restart();
}
function mouseClicked() {
if(!winner){
let x = findNearestIndex(mouseX);
let y = findNearestIndex(mouseY);
//Check ko list
if(whosTurn == "b"){
for (let i = 0; i < bKoList.length; i++) {
if(x == bKoList[i].x && y == bKoList[i].y){
showWarnning();
return;
}
}
}
//Track which intersections are occupied
if(grid[x][y] == "empty") {
//SetStoneFaction
grid[x][y] = whosTurn;
//findLiberty();
//clearGroup();
//removeDead();
//Testing
findStoneGroup();
clearAndDrawBoard();
drawStone();
checkWin();
//refresh ko List
if(whosTurn=="b"){
}
//Track whose turn it is
//Set next player
if(whosTurn == "b")
whosTurn = "w";
else whosTurn = "b";
} else {
console.log(grid[x][y]);
}
} else {
restart();
}
showHint();
}
//Detect a vertical or horizontal win
function checkWin() {
let bStones;
let wStones;
//Check vertical
for (let i = 0; i < grid.length; i++) {
bStones = 0;
wStones = 0;
for (let j = 0; j < grid.length; j++) {
if(grid[i][j] == "b"){
bStones ++;
if(bStones == rows){
console.log("Black Won");
winner = "black";
}
} else if(grid[i][j] == "w"){
wStones ++;
if(wStones == rows){
console.log("White Won");
winner = "white";
}
}
}
}
//Check horizontal
for (let i = 0; i < grid.length; i++) {
bStones = 0;
wStones = 0;
for (let j = 0; j < grid.length; j++) {
if(grid[j][i] == "b"){
bStones ++;
if(bStones == cols){
console.log("Black Won");
winner = "black";
}
} else if(grid[j][i] == "w"){
wStones ++;
if(wStones == cols){
console.log("White Won");
winner = "white";
}
}
}
}
}
//Add "game over" and "game restart" states
function restart() {
rows = 6;
cols = 6;
grid = [];
whosTurn = "b";
winner = null;
bKoList = [];
wKoList = [];
for (let i = 0; i < cols; i++) {
grid[i] = [];
for (let j = 0; j < rows; j++) {
grid[i][j] = "empty";
}
}
createCanvas(600, 700);
clearAndDrawBoard();
showHint();
}
function stone(x, y, f) {
this.x = x;
this.y = y;
this.faction = f;
}
function findStoneGroup() {
wStones = [];
wDead = [];
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
if(grid[i][j] == "w"){
wStones.push(new stone(i,j, "w"));
wDead.push(new stone(i,j, "w"));
}
}
}
for (let i = 0; i < wStones.length; i++) {
if(grid[wStones[i].x][wStones[i].y - 1] == "empty"
|| grid[wStones[i].x][wStones[i].y + 1] == "empty"
|| grid[wStones[i].x - 1][wStones[i].y] == "empty"
|| grid[wStones[i].x + 1][wStones[i].y] == "empty" ){
wDead.pop(wStones[i]);
}
}
console.log(wDead.length);
}
function findLiberty() {
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
if(grid[i][j] == "w" || grid[i][j] == "wGroup" ) {
if(j>0) {
if(grid[i][j-1] == "w") {
grid[i][j-1] = "wGroup";
grid[i][j] = "wGroup";
}
}
if(j<5) {
if(grid[i][j+1] == "w") {
grid[i][j+1] = "wGroup";
grid[i][j] = "wGroup";
}
}
if(i>0) {
if(grid[i-1][j] == "w") {
grid[i-1][j] = "wGroup";
grid[i][j] = "wGroup";
}
}
if(i<5) {
if(grid[i+1][j] == "w") {
grid[i+1][j] = "wGroup";
grid[i][j] = "wGroup";
}
}
}
}
}
}
function clearGroup(){
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
if(grid[i][j] != "empty"){
if(i > 0 && i < cols - 1 && j > 0 && j < rows - 1) {
if(grid[i][j-1] == "empty"
|| grid[i][j+1] == "empty"
|| grid[i-1][j] == "empty"
|| grid[i+1][j] == "empty" ){
if(grid[i][j] == "wGroup" || grid[i][j] == "w"){
if(j>0)
if(grid[i][j-1] == "wGroup" || grid[i][j-1] == "w") {
grid[i][j-1] = "w";
grid[i][j] = "w";
}
if(j<5)
if(grid[i][j+1] == "wGroup" || grid[i][j+1] == "w") {
grid[i][j+1] = "w";
grid[i][j] = "w";
}
if(i>0)
if(grid[i-1][j] == "wGroup" || grid[i-1][j] == "w") {
grid[i-1][j] = "w";
grid[i][j] = "w";
}
if(i<5)
if(grid[i+1][j] == "wGroup" || grid[i+1][j] == "w") {
grid[i+1][j] = "w";
grid[i][j] = "w";
}
}
}
}
}
}
}
}
function removeDead(){
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
if(grid[i][j] == "wGroup") {
grid[i][j] = "empty";
}
}
}
}
function checkLiberty(x, y) {
}
function koStone(x, y) {
this.x = x;
this.y = y;
}
function findNearestIndex(pt) {
let nearest = Math.round(pt / 100 - 0.5);
return nearest;
}
function drawStone() {
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[i].length; j++) {
if(grid[i][j] != "empty"){
let stoneColor;
//Check whos turn
if(grid[i][j] == "b"){
stoneColor = 20;
}
else if(grid[i][j] == "w") {
stoneColor = 230;
}
fill(120, 100, 30, 100);
ellipse(((i + .5) * 100) - 5, ((j + .5) * 100) + 5, 65, 65);
fill(stoneColor);
ellipse((i + .5) * 100, (j + .5) * 100, 65, 65);
}
}
}
}
function clearAndDrawBoard() {
background(180, 130, 70);
stroke(100, 100, 80, 160);
strokeWeight(3);
for (let i = 0; i < 6; i++) {
line((i + .5) * 100, 50, (i + .5) * 100, 550);
line(50, (i + .5) * 100, 550, (i + .5) * 100);
}
noStroke();
}
function showWarnning() {
fill(150,60,10);
textSize(18);
text("* KO! Invalid Move! \n Can't Place on Where Your Chess Was Just Being Captured. \n Please Place on Another Intersection. *", 55,285);
}
function showHint() {
fill(255);
textSize(18);
if(whosTurn == "b" && !winner)
text("Black's turn. Click a grid intersection.", 50,610);
else if(whosTurn == "w" && !winner)
text("White's turn. Click a grid intersection.", 50,610);
if(winner == "black")
text("Black Won! Click to restart...", 50,610);
else if(winner == "white")
text("White Won! Click to restart...", 50,610);
}
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Hi there,
Here are some suggestion on how to update your code and added a captureStones function that should help detect and remove surrounded stones.
Add the captureStones function to your code:
function captureStones(x, y, color) {
const opponentColor = color === "b" ? "w" : "b";
const directions = [
{ x: -1, y: 0 },
{ x: 1, y: 0 },
{ x: 0, y: -1 },
{ x: 0, y: 1 },
];
for (const dir of directions) {
const newX = x + dir.x;
const newY = y + dir.y;
if (
newX >= 0 &&
newX < cols &&
newY >= 0 &&
newY < rows &&
grid[newX][newY] === opponentColor
) {
const captured = [];
const toVisit = [{ x: newX, y: newY }];
let hasLiberty = false;
while (toVisit.length > 0) {
const current = toVisit.pop();
const { x: cx, y: cy } = current;
if (grid[cx][cy] === "empty") {
hasLiberty = true;
break;
}
if (grid[cx][cy] !== opponentColor) {
continue;
}
captured.push(current);
grid[cx][cy] = "visited";
for (const dir of directions) {
const nx = cx + dir.x;
const ny = cy + dir.y;
if (
nx >= 0 &&
nx < cols &&
ny >= 0 &&
ny < rows &&
grid[nx][ny] !== "visited"
) {
toVisit.push({ x: nx, y: ny });
}
}
}
if (!hasLiberty) {
for (const { x: cx, y: cy } of captured) {
grid[cx][cy] = "empty";
}
} else {
for (const { x: cx, y: cy } of captured) {
grid[cx][cy] = opponentColor;
}
}
}
}
}
Then, modify the mouseClicked function by adding a call to captureStones after setting the stone:
// ...
if (grid[x][y] == "empty") {
//SetStoneFaction
grid[x][y] = whosTurn;
captureStones(x, y, whosTurn); // Add this line
// ...
}
// ...
This should now detect and remove surrounded stones correctly. The captureStones function checks in all four directions around the placed stone for any opponent stones. If found, it tries to determine if the opponent’s connected group has any liberties. If there are no liberties, the connected group is captured and removed from the board.
Best,
Bobby
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.