Update index.html
Browse files- index.html +198 -51
index.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
-
<title>Go Game</title>
|
| 7 |
<style>
|
| 8 |
* {
|
| 9 |
margin: 0;
|
|
@@ -255,6 +255,7 @@
|
|
| 255 |
this.lastMove = null;
|
| 256 |
this.gameMode = 'pvp';
|
| 257 |
this.difficulty = 'easy';
|
|
|
|
| 258 |
this.initialize();
|
| 259 |
}
|
| 260 |
|
|
@@ -262,14 +263,14 @@
|
|
| 262 |
const boardElement = document.getElementById('board');
|
| 263 |
boardElement.innerHTML = '';
|
| 264 |
|
| 265 |
-
for(let i = 0; i < this.size; i++) {
|
| 266 |
-
for(let j = 0; j < this.size; j++) {
|
| 267 |
const intersection = document.createElement('div');
|
| 268 |
intersection.className = 'intersection';
|
| 269 |
intersection.dataset.row = i;
|
| 270 |
intersection.dataset.col = j;
|
| 271 |
|
| 272 |
-
if(this.isStarPoint(i, j)) {
|
| 273 |
intersection.classList.add('star-point');
|
| 274 |
}
|
| 275 |
|
|
@@ -293,45 +294,50 @@
|
|
| 293 |
|
| 294 |
isStarPoint(row, col) {
|
| 295 |
const starPoints = [
|
| 296 |
-
[3,3], [3,9], [3,15],
|
| 297 |
-
[9,3], [9,9], [9,15],
|
| 298 |
-
[15,3], [15,9], [15,15]
|
| 299 |
];
|
| 300 |
return starPoints.some(point => point[0] === row && point[1] === col);
|
| 301 |
}
|
| 302 |
|
| 303 |
handleMove(e) {
|
|
|
|
| 304 |
const row = parseInt(e.target.dataset.row);
|
| 305 |
const col = parseInt(e.target.dataset.col);
|
| 306 |
|
| 307 |
-
if(this.isValidMove(row, col)) {
|
| 308 |
this.placeStone(row, col);
|
| 309 |
-
|
| 310 |
-
if(this.gameMode === 'ai' && this.currentPlayer === 'white') {
|
| 311 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 312 |
}
|
| 313 |
}
|
| 314 |
}
|
| 315 |
|
| 316 |
isValidMove(row, col) {
|
| 317 |
-
if(this.board[row][col] !== null) return false;
|
| 318 |
-
|
| 319 |
this.board[row][col] = this.currentPlayer;
|
| 320 |
const captures = this.checkCaptures(row, col);
|
| 321 |
const suicide = this.isSuicideMove(row, col);
|
| 322 |
-
|
| 323 |
this.board[row][col] = null;
|
| 324 |
-
|
| 325 |
return !suicide || captures.length > 0;
|
| 326 |
}
|
| 327 |
|
| 328 |
placeStone(row, col) {
|
| 329 |
this.board[row][col] = this.currentPlayer;
|
| 330 |
this.renderStone(row, col);
|
| 331 |
-
|
| 332 |
const captures = this.checkCaptures(row, col);
|
| 333 |
this.removeCaptures(captures);
|
| 334 |
-
|
| 335 |
this.lastMove = [row, col];
|
| 336 |
this.currentPlayer = this.currentPlayer === 'black' ? 'white' : 'black';
|
| 337 |
this.updateDisplay();
|
|
@@ -343,25 +349,26 @@
|
|
| 343 |
stone.className = `stone ${this.currentPlayer}`;
|
| 344 |
intersection.appendChild(stone);
|
| 345 |
}
|
|
|
|
| 346 |
checkCaptures(row, col) {
|
| 347 |
const captures = [];
|
| 348 |
const opponent = this.currentPlayer === 'black' ? 'white' : 'black';
|
| 349 |
const neighbors = this.getNeighbors(row, col);
|
| 350 |
-
|
| 351 |
-
for(const [nRow, nCol] of neighbors) {
|
| 352 |
-
if(this.board[nRow][nCol] === opponent) {
|
| 353 |
const group = this.getGroup(nRow, nCol);
|
| 354 |
-
if(this.isGroupCaptured(group)) {
|
| 355 |
captures.push(...group);
|
| 356 |
}
|
| 357 |
}
|
| 358 |
}
|
| 359 |
-
|
| 360 |
return captures;
|
| 361 |
}
|
| 362 |
|
| 363 |
removeCaptures(captures) {
|
| 364 |
-
for(const [row, col] of captures) {
|
| 365 |
this.board[row][col] = null;
|
| 366 |
const intersection = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
|
| 367 |
intersection.innerHTML = '';
|
|
@@ -374,32 +381,32 @@
|
|
| 374 |
const group = [];
|
| 375 |
const visited = new Set();
|
| 376 |
const stack = [[row, col]];
|
| 377 |
-
|
| 378 |
-
while(stack.length > 0) {
|
| 379 |
const [r, c] = stack.pop();
|
| 380 |
const key = `${r},${c}`;
|
| 381 |
-
|
| 382 |
-
if(!visited.has(key)) {
|
| 383 |
visited.add(key);
|
| 384 |
group.push([r, c]);
|
| 385 |
-
|
| 386 |
const neighbors = this.getNeighbors(r, c);
|
| 387 |
-
for(const [nr, nc] of neighbors) {
|
| 388 |
-
if(this.board[nr][nc] === color) {
|
| 389 |
stack.push([nr, nc]);
|
| 390 |
}
|
| 391 |
}
|
| 392 |
}
|
| 393 |
}
|
| 394 |
-
|
| 395 |
return group;
|
| 396 |
}
|
| 397 |
|
| 398 |
isGroupCaptured(group) {
|
| 399 |
-
for(const [row, col] of group) {
|
| 400 |
const neighbors = this.getNeighbors(row, col);
|
| 401 |
-
for(const [nRow, nCol] of neighbors) {
|
| 402 |
-
if(this.board[nRow][nCol] === null) return false;
|
| 403 |
}
|
| 404 |
}
|
| 405 |
return true;
|
|
@@ -407,18 +414,18 @@
|
|
| 407 |
|
| 408 |
getNeighbors(row, col) {
|
| 409 |
const neighbors = [];
|
| 410 |
-
const directions = [[-1,0], [1,0], [0
|
| 411 |
-
|
| 412 |
-
for(const [dRow, dCol] of directions) {
|
| 413 |
const newRow = row + dRow;
|
| 414 |
const newCol = col + dCol;
|
| 415 |
-
|
| 416 |
-
if(newRow >= 0 && newRow < this.size &&
|
| 417 |
-
|
| 418 |
neighbors.push([newRow, newCol]);
|
| 419 |
}
|
| 420 |
}
|
| 421 |
-
|
| 422 |
return neighbors;
|
| 423 |
}
|
| 424 |
|
|
@@ -428,11 +435,16 @@
|
|
| 428 |
}
|
| 429 |
|
| 430 |
pass() {
|
|
|
|
| 431 |
this.currentPlayer = this.currentPlayer === 'black' ? 'white' : 'black';
|
| 432 |
this.updateDisplay();
|
| 433 |
-
|
| 434 |
-
if(this.gameMode === 'ai' && this.currentPlayer === 'white') {
|
| 435 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 436 |
}
|
| 437 |
}
|
| 438 |
|
|
@@ -441,18 +453,19 @@
|
|
| 441 |
this.currentPlayer = 'black';
|
| 442 |
this.captures = { black: 0, white: 0 };
|
| 443 |
this.lastMove = null;
|
|
|
|
| 444 |
this.initialize();
|
| 445 |
}
|
| 446 |
|
| 447 |
updateDisplay() {
|
| 448 |
-
document.getElementById('currentPlayer').textContent =
|
| 449 |
this.currentPlayer.charAt(0).toUpperCase() + this.currentPlayer.slice(1);
|
| 450 |
document.getElementById('blackCaptures').textContent = this.captures.black;
|
| 451 |
document.getElementById('whiteCaptures').textContent = this.captures.white;
|
| 452 |
}
|
| 453 |
|
| 454 |
makeAIMove() {
|
| 455 |
-
if(this.difficulty === 'easy') {
|
| 456 |
this.makeRandomMove();
|
| 457 |
} else {
|
| 458 |
this.makeStrategicMove();
|
|
@@ -461,15 +474,15 @@
|
|
| 461 |
|
| 462 |
makeRandomMove() {
|
| 463 |
const validMoves = [];
|
| 464 |
-
for(let i = 0; i < this.size; i++) {
|
| 465 |
-
for(let j = 0; j < this.size; j++) {
|
| 466 |
-
if(this.isValidMove(i, j)) {
|
| 467 |
validMoves.push([i, j]);
|
| 468 |
}
|
| 469 |
}
|
| 470 |
}
|
| 471 |
|
| 472 |
-
if(validMoves.length > 0) {
|
| 473 |
const [row, col] = validMoves[Math.floor(Math.random() * validMoves.length)];
|
| 474 |
this.placeStone(row, col);
|
| 475 |
} else {
|
|
@@ -478,11 +491,145 @@
|
|
| 478 |
}
|
| 479 |
|
| 480 |
makeStrategicMove() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 481 |
this.makeRandomMove();
|
| 482 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 483 |
}
|
| 484 |
|
| 485 |
const game = new GoGame();
|
| 486 |
</script>
|
| 487 |
</body>
|
| 488 |
-
</html>
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Go Game with Strategic AI</title>
|
| 7 |
<style>
|
| 8 |
* {
|
| 9 |
margin: 0;
|
|
|
|
| 255 |
this.lastMove = null;
|
| 256 |
this.gameMode = 'pvp';
|
| 257 |
this.difficulty = 'easy';
|
| 258 |
+
this.isProcessing = false; // NEW: μμ
μ€ μ¬λΆ νλκ·Έ
|
| 259 |
this.initialize();
|
| 260 |
}
|
| 261 |
|
|
|
|
| 263 |
const boardElement = document.getElementById('board');
|
| 264 |
boardElement.innerHTML = '';
|
| 265 |
|
| 266 |
+
for (let i = 0; i < this.size; i++) {
|
| 267 |
+
for (let j = 0; j < this.size; j++) {
|
| 268 |
const intersection = document.createElement('div');
|
| 269 |
intersection.className = 'intersection';
|
| 270 |
intersection.dataset.row = i;
|
| 271 |
intersection.dataset.col = j;
|
| 272 |
|
| 273 |
+
if (this.isStarPoint(i, j)) {
|
| 274 |
intersection.classList.add('star-point');
|
| 275 |
}
|
| 276 |
|
|
|
|
| 294 |
|
| 295 |
isStarPoint(row, col) {
|
| 296 |
const starPoints = [
|
| 297 |
+
[3, 3], [3, 9], [3, 15],
|
| 298 |
+
[9, 3], [9, 9], [9, 15],
|
| 299 |
+
[15, 3], [15, 9], [15, 15]
|
| 300 |
];
|
| 301 |
return starPoints.some(point => point[0] === row && point[1] === col);
|
| 302 |
}
|
| 303 |
|
| 304 |
handleMove(e) {
|
| 305 |
+
if (this.isProcessing) return; // NEW: ν΄λ¦ λ°©μ§
|
| 306 |
const row = parseInt(e.target.dataset.row);
|
| 307 |
const col = parseInt(e.target.dataset.col);
|
| 308 |
|
| 309 |
+
if (this.isValidMove(row, col)) {
|
| 310 |
this.placeStone(row, col);
|
| 311 |
+
|
| 312 |
+
if (this.gameMode === 'ai' && this.currentPlayer === 'white') {
|
| 313 |
+
this.isProcessing = true; // AI μμ
μμ
|
| 314 |
+
setTimeout(() => {
|
| 315 |
+
this.makeAIMove();
|
| 316 |
+
this.isProcessing = false; // AI μμ
μλ£
|
| 317 |
+
}, 500);
|
| 318 |
}
|
| 319 |
}
|
| 320 |
}
|
| 321 |
|
| 322 |
isValidMove(row, col) {
|
| 323 |
+
if (this.board[row][col] !== null) return false;
|
| 324 |
+
|
| 325 |
this.board[row][col] = this.currentPlayer;
|
| 326 |
const captures = this.checkCaptures(row, col);
|
| 327 |
const suicide = this.isSuicideMove(row, col);
|
| 328 |
+
|
| 329 |
this.board[row][col] = null;
|
| 330 |
+
|
| 331 |
return !suicide || captures.length > 0;
|
| 332 |
}
|
| 333 |
|
| 334 |
placeStone(row, col) {
|
| 335 |
this.board[row][col] = this.currentPlayer;
|
| 336 |
this.renderStone(row, col);
|
| 337 |
+
|
| 338 |
const captures = this.checkCaptures(row, col);
|
| 339 |
this.removeCaptures(captures);
|
| 340 |
+
|
| 341 |
this.lastMove = [row, col];
|
| 342 |
this.currentPlayer = this.currentPlayer === 'black' ? 'white' : 'black';
|
| 343 |
this.updateDisplay();
|
|
|
|
| 349 |
stone.className = `stone ${this.currentPlayer}`;
|
| 350 |
intersection.appendChild(stone);
|
| 351 |
}
|
| 352 |
+
|
| 353 |
checkCaptures(row, col) {
|
| 354 |
const captures = [];
|
| 355 |
const opponent = this.currentPlayer === 'black' ? 'white' : 'black';
|
| 356 |
const neighbors = this.getNeighbors(row, col);
|
| 357 |
+
|
| 358 |
+
for (const [nRow, nCol] of neighbors) {
|
| 359 |
+
if (this.board[nRow][nCol] === opponent) {
|
| 360 |
const group = this.getGroup(nRow, nCol);
|
| 361 |
+
if (this.isGroupCaptured(group)) {
|
| 362 |
captures.push(...group);
|
| 363 |
}
|
| 364 |
}
|
| 365 |
}
|
| 366 |
+
|
| 367 |
return captures;
|
| 368 |
}
|
| 369 |
|
| 370 |
removeCaptures(captures) {
|
| 371 |
+
for (const [row, col] of captures) {
|
| 372 |
this.board[row][col] = null;
|
| 373 |
const intersection = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
|
| 374 |
intersection.innerHTML = '';
|
|
|
|
| 381 |
const group = [];
|
| 382 |
const visited = new Set();
|
| 383 |
const stack = [[row, col]];
|
| 384 |
+
|
| 385 |
+
while (stack.length > 0) {
|
| 386 |
const [r, c] = stack.pop();
|
| 387 |
const key = `${r},${c}`;
|
| 388 |
+
|
| 389 |
+
if (!visited.has(key)) {
|
| 390 |
visited.add(key);
|
| 391 |
group.push([r, c]);
|
| 392 |
+
|
| 393 |
const neighbors = this.getNeighbors(r, c);
|
| 394 |
+
for (const [nr, nc] of neighbors) {
|
| 395 |
+
if (this.board[nr][nc] === color) {
|
| 396 |
stack.push([nr, nc]);
|
| 397 |
}
|
| 398 |
}
|
| 399 |
}
|
| 400 |
}
|
| 401 |
+
|
| 402 |
return group;
|
| 403 |
}
|
| 404 |
|
| 405 |
isGroupCaptured(group) {
|
| 406 |
+
for (const [row, col] of group) {
|
| 407 |
const neighbors = this.getNeighbors(row, col);
|
| 408 |
+
for (const [nRow, nCol] of neighbors) {
|
| 409 |
+
if (this.board[nRow][nCol] === null) return false;
|
| 410 |
}
|
| 411 |
}
|
| 412 |
return true;
|
|
|
|
| 414 |
|
| 415 |
getNeighbors(row, col) {
|
| 416 |
const neighbors = [];
|
| 417 |
+
const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
|
| 418 |
+
|
| 419 |
+
for (const [dRow, dCol] of directions) {
|
| 420 |
const newRow = row + dRow;
|
| 421 |
const newCol = col + dCol;
|
| 422 |
+
|
| 423 |
+
if (newRow >= 0 && newRow < this.size &&
|
| 424 |
+
newCol >= 0 && newCol < this.size) {
|
| 425 |
neighbors.push([newRow, newCol]);
|
| 426 |
}
|
| 427 |
}
|
| 428 |
+
|
| 429 |
return neighbors;
|
| 430 |
}
|
| 431 |
|
|
|
|
| 435 |
}
|
| 436 |
|
| 437 |
pass() {
|
| 438 |
+
if (this.isProcessing) return; // NEW: ν΄λ¦ λ°©μ§
|
| 439 |
this.currentPlayer = this.currentPlayer === 'black' ? 'white' : 'black';
|
| 440 |
this.updateDisplay();
|
| 441 |
+
|
| 442 |
+
if (this.gameMode === 'ai' && this.currentPlayer === 'white') {
|
| 443 |
+
this.isProcessing = true; // AI μμ
μμ
|
| 444 |
+
setTimeout(() => {
|
| 445 |
+
this.makeAIMove();
|
| 446 |
+
this.isProcessing = false; // AI μμ
μλ£
|
| 447 |
+
}, 500);
|
| 448 |
}
|
| 449 |
}
|
| 450 |
|
|
|
|
| 453 |
this.currentPlayer = 'black';
|
| 454 |
this.captures = { black: 0, white: 0 };
|
| 455 |
this.lastMove = null;
|
| 456 |
+
this.isProcessing = false; // μ΄κΈ°ν μ μμ
μν ν΄μ
|
| 457 |
this.initialize();
|
| 458 |
}
|
| 459 |
|
| 460 |
updateDisplay() {
|
| 461 |
+
document.getElementById('currentPlayer').textContent =
|
| 462 |
this.currentPlayer.charAt(0).toUpperCase() + this.currentPlayer.slice(1);
|
| 463 |
document.getElementById('blackCaptures').textContent = this.captures.black;
|
| 464 |
document.getElementById('whiteCaptures').textContent = this.captures.white;
|
| 465 |
}
|
| 466 |
|
| 467 |
makeAIMove() {
|
| 468 |
+
if (this.difficulty === 'easy') {
|
| 469 |
this.makeRandomMove();
|
| 470 |
} else {
|
| 471 |
this.makeStrategicMove();
|
|
|
|
| 474 |
|
| 475 |
makeRandomMove() {
|
| 476 |
const validMoves = [];
|
| 477 |
+
for (let i = 0; i < this.size; i++) {
|
| 478 |
+
for (let j = 0; j < this.size; j++) {
|
| 479 |
+
if (this.isValidMove(i, j)) {
|
| 480 |
validMoves.push([i, j]);
|
| 481 |
}
|
| 482 |
}
|
| 483 |
}
|
| 484 |
|
| 485 |
+
if (validMoves.length > 0) {
|
| 486 |
const [row, col] = validMoves[Math.floor(Math.random() * validMoves.length)];
|
| 487 |
this.placeStone(row, col);
|
| 488 |
} else {
|
|
|
|
| 491 |
}
|
| 492 |
|
| 493 |
makeStrategicMove() {
|
| 494 |
+
const opponent = this.currentPlayer === 'black' ? 'white' : 'black';
|
| 495 |
+
const captureMoves = this.findCaptureMoves(opponent);
|
| 496 |
+
if (captureMoves.length > 0) {
|
| 497 |
+
const [row, col] = captureMoves[0];
|
| 498 |
+
this.placeStone(row, col);
|
| 499 |
+
return;
|
| 500 |
+
}
|
| 501 |
+
|
| 502 |
+
const territoryMove = this.findTerritoryMove();
|
| 503 |
+
if (territoryMove) {
|
| 504 |
+
const [row, col] = territoryMove;
|
| 505 |
+
this.placeStone(row, col);
|
| 506 |
+
return;
|
| 507 |
+
}
|
| 508 |
+
|
| 509 |
+
const connectionMove = this.findConnectionMove();
|
| 510 |
+
if (connectionMove) {
|
| 511 |
+
const [row, col] = connectionMove;
|
| 512 |
+
this.placeStone(row, col);
|
| 513 |
+
return;
|
| 514 |
+
}
|
| 515 |
+
|
| 516 |
+
const separationMove = this.findSeparationMove(opponent);
|
| 517 |
+
if (separationMove) {
|
| 518 |
+
const [row, col] = separationMove;
|
| 519 |
+
this.placeStone(row, col);
|
| 520 |
+
return;
|
| 521 |
+
}
|
| 522 |
+
|
| 523 |
+
const eyeMove = this.findEyeMakingMove();
|
| 524 |
+
if (eyeMove) {
|
| 525 |
+
const [row, col] = eyeMove;
|
| 526 |
+
this.placeStone(row, col);
|
| 527 |
+
return;
|
| 528 |
+
}
|
| 529 |
+
|
| 530 |
this.makeRandomMove();
|
| 531 |
}
|
| 532 |
+
|
| 533 |
+
findCaptureMoves(opponent) {
|
| 534 |
+
const captureMoves = [];
|
| 535 |
+
|
| 536 |
+
for (let row = 0; row < this.size; row++) {
|
| 537 |
+
for (let col = 0; col < this.size; col++) {
|
| 538 |
+
if (this.board[row][col] === opponent) {
|
| 539 |
+
const group = this.getGroup(row, col);
|
| 540 |
+
if (this.isGroupCaptured(group)) {
|
| 541 |
+
const liberties = this.getLiberties(group);
|
| 542 |
+
captureMoves.push(...liberties);
|
| 543 |
+
}
|
| 544 |
+
}
|
| 545 |
+
}
|
| 546 |
+
}
|
| 547 |
+
|
| 548 |
+
return captureMoves.filter(([r, c]) => this.isValidMove(r, c));
|
| 549 |
+
}
|
| 550 |
+
|
| 551 |
+
findTerritoryMove() {
|
| 552 |
+
const importantPoints = [
|
| 553 |
+
[9, 9],
|
| 554 |
+
[3, 3], [3, 15], [15, 3], [15, 15],
|
| 555 |
+
[9, 3], [9, 15], [3, 9], [15, 9]
|
| 556 |
+
];
|
| 557 |
+
|
| 558 |
+
for (const [row, col] of importantPoints) {
|
| 559 |
+
if (this.isValidMove(row, col)) {
|
| 560 |
+
return [row, col];
|
| 561 |
+
}
|
| 562 |
+
}
|
| 563 |
+
|
| 564 |
+
return null;
|
| 565 |
+
}
|
| 566 |
+
|
| 567 |
+
findConnectionMove() {
|
| 568 |
+
for (let row = 0; row < this.size; row++) {
|
| 569 |
+
for (let col = 0; col < this.size; col++) {
|
| 570 |
+
if (this.isValidMove(row, col)) {
|
| 571 |
+
const neighbors = this.getNeighbors(row, col);
|
| 572 |
+
for (const [nRow, nCol] of neighbors) {
|
| 573 |
+
if (this.board[nRow][nCol] === this.currentPlayer) {
|
| 574 |
+
return [row, col];
|
| 575 |
+
}
|
| 576 |
+
}
|
| 577 |
+
}
|
| 578 |
+
}
|
| 579 |
+
}
|
| 580 |
+
|
| 581 |
+
return null;
|
| 582 |
+
}
|
| 583 |
+
|
| 584 |
+
findSeparationMove(opponent) {
|
| 585 |
+
for (let row = 0; row < this.size; row++) {
|
| 586 |
+
for (let col = 0; col < this.size; col++) {
|
| 587 |
+
if (this.isValidMove(row, col)) {
|
| 588 |
+
const neighbors = this.getNeighbors(row, col);
|
| 589 |
+
const opponentNeighbors = neighbors.filter(([nRow, nCol]) => this.board[nRow][nCol] === opponent);
|
| 590 |
+
if (opponentNeighbors.length >= 2) {
|
| 591 |
+
return [row, col];
|
| 592 |
+
}
|
| 593 |
+
}
|
| 594 |
+
}
|
| 595 |
+
}
|
| 596 |
+
|
| 597 |
+
return null;
|
| 598 |
+
}
|
| 599 |
+
|
| 600 |
+
findEyeMakingMove() {
|
| 601 |
+
for (let row = 0; row < this.size; row++) {
|
| 602 |
+
for (let col = 0; col < this.size; col++) {
|
| 603 |
+
if (this.isValidMove(row, col)) {
|
| 604 |
+
const group = this.getGroup(row, col);
|
| 605 |
+
const liberties = this.getLiberties(group);
|
| 606 |
+
if (liberties.length >= 2) {
|
| 607 |
+
return [row, col];
|
| 608 |
+
}
|
| 609 |
+
}
|
| 610 |
+
}
|
| 611 |
+
}
|
| 612 |
+
|
| 613 |
+
return null;
|
| 614 |
+
}
|
| 615 |
+
|
| 616 |
+
getLiberties(group) {
|
| 617 |
+
const liberties = new Set();
|
| 618 |
+
|
| 619 |
+
for (const [row, col] of group) {
|
| 620 |
+
const neighbors = this.getNeighbors(row, col);
|
| 621 |
+
for (const [nRow, nCol] of neighbors) {
|
| 622 |
+
if (this.board[nRow][nCol] === null) {
|
| 623 |
+
liberties.add(`${nRow},${nCol}`);
|
| 624 |
+
}
|
| 625 |
+
}
|
| 626 |
+
}
|
| 627 |
+
|
| 628 |
+
return Array.from(liberties).map((key) => key.split(',').map(Number));
|
| 629 |
+
}
|
| 630 |
}
|
| 631 |
|
| 632 |
const game = new GoGame();
|
| 633 |
</script>
|
| 634 |
</body>
|
| 635 |
+
</html>
|