kolaslab commited on
Commit
736a552
β€’
1 Parent(s): 32a8ea3

Update index.html

Browse files
Files changed (1) hide show
  1. 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
- setTimeout(() => this.makeAIMove(), 500);
 
 
 
 
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,-1], [0,1]];
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
- newCol >= 0 && newCol < this.size) {
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
- setTimeout(() => this.makeAIMove(), 500);
 
 
 
 
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>