Raven7 commited on
Commit
81f24ba
Β·
verified Β·
1 Parent(s): 11faca4

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +105 -199
index.html CHANGED
@@ -459,46 +459,21 @@
459
  }
460
  }
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 {
476
- this.pass();
477
- }
478
- }
479
-
480
- makeStrategicMove() {
481
- const depth = this.difficulty === 'hard' ? 3 : 1;
482
- let bestMove = this.findBestMove(depth);
483
 
484
- if(bestMove) {
485
- this.placeStone(bestMove[0], bestMove[1]);
486
- } else {
487
- this.pass();
488
- }
489
- }
490
-
491
- findBestMove(depth) {
492
  let bestScore = -Infinity;
493
  let bestMove = null;
494
 
495
- // 전체 λ³΄λ“œλ₯Ό 평가
496
  for(let i = 0; i < this.size; i++) {
497
  for(let j = 0; j < this.size; j++) {
498
  if(this.isValidMove(i, j)) {
499
- // μž„μ‹œλ‘œ λŒμ„ 놓아보고 평가
500
  this.board[i][j] = 'white';
501
- const score = this.minimax(depth - 1, false);
502
  this.board[i][j] = null;
503
 
504
  if(score > bestScore) {
@@ -509,169 +484,116 @@ findBestMove(depth) {
509
  }
510
  }
511
 
512
- return bestMove;
513
- }
514
-
515
- minimax(depth, isMaximizing) {
516
- if(depth === 0) {
517
- return this.evaluateBoard();
518
- }
519
-
520
- if(isMaximizing) {
521
- let maxScore = -Infinity;
522
- for(let i = 0; i < this.size; i++) {
523
- for(let j = 0; j < this.size; j++) {
524
- if(this.isValidMove(i, j)) {
525
- this.board[i][j] = 'white';
526
- const score = this.minimax(depth - 1, false);
527
- this.board[i][j] = null;
528
- maxScore = Math.max(maxScore, score);
529
- }
530
- }
531
- }
532
- return maxScore;
533
  } else {
534
- let minScore = Infinity;
535
- for(let i = 0; i < this.size; i++) {
536
- for(let j = 0; j < this.size; j++) {
537
- if(this.isValidMove(i, j)) {
538
- this.board[i][j] = 'black';
539
- const score = this.minimax(depth - 1, true);
540
- this.board[i][j] = null;
541
- minScore = Math.min(minScore, score);
542
- }
543
- }
544
- }
545
- return minScore;
546
  }
547
  }
548
 
549
  evaluateBoard() {
550
- return this.evaluateTerritory() +
551
- this.evaluateInfluence() +
552
- this.evaluateCaptureThreats() +
553
- this.evaluateConnectivity();
 
 
 
554
  }
555
 
556
- evaluateTerritory() {
557
  let score = 0;
558
- const visited = new Set();
559
 
560
- for(let i = 0; i < this.size; i++) {
561
- for(let j = 0; j < this.size; j++) {
562
- if(!visited.has(`${i},${j}`) && this.board[i][j] === null) {
563
- const territory = this.floodFillTerritory(i, j, visited);
564
- const owner = this.determineTerritorySide(territory);
565
- if(owner === 'white') score += territory.size;
566
- else if(owner === 'black') score -= territory.size;
567
- }
568
- }
569
- }
 
 
 
 
570
 
571
  return score;
572
  }
573
 
574
- floodFillTerritory(row, col, visited) {
575
- const territory = new Set();
576
- const stack = [[row, col]];
577
- const borders = new Set();
578
 
579
- while(stack.length > 0) {
580
- const [r, c] = stack.pop();
581
- const key = `${r},${c}`;
582
-
583
- if(!visited.has(key)) {
584
- visited.add(key);
585
- if(this.board[r][c] === null) {
586
- territory.add(key);
587
-
588
- const neighbors = this.getNeighbors(r, c);
589
- for(const [nr, nc] of neighbors) {
590
- if(this.board[nr][nc] === null) {
591
- stack.push([nr, nc]);
592
- } else {
593
- borders.add(`${nr},${nc}`);
594
- }
595
- }
596
  }
597
  }
598
  }
599
-
600
- territory.borders = borders;
601
- return territory;
602
  }
603
 
604
- determineTerritorySide(territory) {
605
- let blackCount = 0;
606
- let whiteCount = 0;
607
 
608
- for(const pos of territory.borders) {
609
- const [row, col] = pos.split(',').map(Number);
610
- if(this.board[row][col] === 'black') blackCount++;
611
- else if(this.board[row][col] === 'white') whiteCount++;
 
 
612
  }
613
-
614
- if(blackCount > whiteCount) return 'black';
615
- if(whiteCount > blackCount) return 'white';
616
- return null;
617
  }
618
 
619
- evaluateInfluence() {
620
  let score = 0;
 
621
 
622
- for(let i = 0; i < this.size; i++) {
623
- for(let j = 0; j < this.size; j++) {
624
- if(this.board[i][j] === 'white') {
625
- score += this.calculateInfluence(i, j, 3);
626
- } else if(this.board[i][j] === 'black') {
627
- score -= this.calculateInfluence(i, j, 3);
628
- }
629
  }
630
  }
631
 
632
  return score;
633
  }
634
 
635
- calculateInfluence(row, col, radius) {
636
- let influence = 0;
 
 
637
 
638
- for(let i = -radius; i <= radius; i++) {
639
- for(let j = -radius; j <= radius; j++) {
640
- const distance = Math.abs(i) + Math.abs(j);
641
- if(distance <= radius) {
642
- const newRow = row + i;
643
- const newCol = col + j;
644
-
645
- if(newRow >= 0 && newRow < this.size &&
646
- newCol >= 0 && newCol < this.size) {
647
- influence += (radius - distance + 1) / radius;
648
- }
649
- }
650
- }
651
- }
652
 
653
- return influence;
654
  }
655
 
656
- evaluateCaptureThreats() {
657
  let score = 0;
658
 
659
- for(let i = 0; i < this.size; i++) {
660
- for(let j = 0; j < this.size; j++) {
661
- if(this.board[i][j]) {
662
- const group = this.getGroup(i, j);
663
- const liberties = this.countLiberties(group);
664
-
665
- if(this.board[i][j] === 'white') {
666
- score += liberties * 2;
667
- if(liberties === 1) score -= 10;
668
- } else {
669
- score -= liberties * 2;
670
- if(liberties === 1) score += 10;
671
- }
672
- }
673
- }
674
- }
675
 
676
  return score;
677
  }
@@ -691,57 +613,41 @@ countLiberties(group) {
691
  return liberties.size;
692
  }
693
 
694
- evaluateConnectivity() {
695
- let score = 0;
696
-
697
- for(let i = 0; i < this.size; i++) {
698
- for(let j = 0; j < this.size; j++) {
699
- if(this.board[i][j] === 'white') {
700
- score += this.evaluateStoneConnectivity(i, j);
701
- } else if(this.board[i][j] === 'black') {
702
- score -= this.evaluateStoneConnectivity(i, j);
703
- }
704
- }
705
- }
706
-
707
- return score;
708
- }
709
-
710
- evaluateStoneConnectivity(row, col) {
711
- let connectivity = 0;
712
  const neighbors = this.getNeighbors(row, col);
713
- const diagonalNeighbors = this.getDiagonalNeighbors(row, col);
 
714
 
715
  for(const [nRow, nCol] of neighbors) {
716
- if(this.board[nRow][nCol] === this.board[row][col]) {
717
- connectivity += 2;
718
- }
719
  }
720
 
721
- for(const [nRow, nCol] of diagonalNeighbors) {
722
- if(this.board[nRow][nCol] === this.board[row][col]) {
723
- connectivity += 1;
724
- }
725
- }
 
 
 
 
726
 
727
- return connectivity;
 
 
 
728
  }
729
 
730
- getDiagonalNeighbors(row, col) {
731
- const neighbors = [];
732
- const directions = [[-1,-1], [-1,1], [1,-1], [1,1]];
733
 
734
- for(const [dRow, dCol] of directions) {
735
- const newRow = row + dRow;
736
- const newCol = col + dCol;
737
-
738
- if(newRow >= 0 && newRow < this.size &&
739
- newCol >= 0 && newCol < this.size) {
740
- neighbors.push([newRow, newCol]);
741
- }
742
- }
743
 
744
- return neighbors;
745
  }
746
  }
747
 
 
459
  }
460
  }
461
 
462
+ // GoGame 클래슀 λ‚΄μ˜ makeStrategicMove λ©”μ†Œλ“œλ₯Ό λ‹€μŒκ³Ό 같이 μˆ˜μ •
463
+ makeStrategicMove() {
464
+ // ν˜„μž¬ λ³΄λ“œ μƒνƒœ 평가
465
+ const boardScore = this.evaluateBoard();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
466
 
467
+ // κ°€λŠ₯ν•œ λͺ¨λ“  수의 점수λ₯Ό 계산
 
 
 
 
 
 
 
468
  let bestScore = -Infinity;
469
  let bestMove = null;
470
 
 
471
  for(let i = 0; i < this.size; i++) {
472
  for(let j = 0; j < this.size; j++) {
473
  if(this.isValidMove(i, j)) {
474
+ // κ°€μƒμœΌλ‘œ λŒμ„ 놓아보고 점수 계산
475
  this.board[i][j] = 'white';
476
+ const score = this.calculateMoveScore(i, j, boardScore);
477
  this.board[i][j] = null;
478
 
479
  if(score > bestScore) {
 
484
  }
485
  }
486
 
487
+ if(bestMove) {
488
+ this.placeStone(bestMove[0], bestMove[1]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
489
  } else {
490
+ this.pass();
 
 
 
 
 
 
 
 
 
 
 
491
  }
492
  }
493
 
494
  evaluateBoard() {
495
+ const evaluation = {
496
+ territory: this.evaluateTerritory(),
497
+ influence: this.evaluateInfluence(),
498
+ connections: this.evaluateConnections(),
499
+ captures: this.captures
500
+ };
501
+ return evaluation;
502
  }
503
 
504
+ calculateMoveScore(row, col, boardScore) {
505
  let score = 0;
 
506
 
507
+ // 1. μ˜ν†  점수
508
+ score += this.calculateTerritoryScore(row, col) * 2;
509
+
510
+ // 2. μ—°κ²°μ„± 점수
511
+ score += this.calculateConnectionScore(row, col) * 1.5;
512
+
513
+ // 3. 곡격/λ°©μ–΄ 점수
514
+ score += this.calculateTacticalScore(row, col);
515
+
516
+ // 4. μœ„ν—˜ νšŒν”Ό 점수
517
+ score += this.calculateSafetyScore(row, col);
518
+
519
+ // 5. μ „λž΅μ  μœ„μΉ˜ 점수
520
+ score += this.calculateStrategicScore(row, col);
521
 
522
  return score;
523
  }
524
 
525
+ calculateTerritoryScore(row, col) {
526
+ let score = 0;
527
+ const radius = 3;
 
528
 
529
+ for(let i = Math.max(0, row-radius); i <= Math.min(this.size-1, row+radius); i++) {
530
+ for(let j = Math.max(0, col-radius); j <= Math.min(this.size-1, col+radius); j++) {
531
+ const distance = Math.abs(row-i) + Math.abs(col-j);
532
+ if(distance <= radius) {
533
+ if(this.board[i][j] === null) score += (radius - distance + 1);
534
+ else if(this.board[i][j] === 'white') score += 2;
535
+ else score -= 1;
 
 
 
 
 
 
 
 
 
 
536
  }
537
  }
538
  }
539
+ return score;
 
 
540
  }
541
 
542
+ calculateConnectionScore(row, col) {
543
+ let score = 0;
544
+ const neighbors = this.getNeighbors(row, col);
545
 
546
+ for(const [nRow, nCol] of neighbors) {
547
+ if(this.board[nRow][nCol] === 'white') {
548
+ score += 10;
549
+ // 두 돌이 μ—°κ²°λ˜λ©΄ 더 높은 점수
550
+ if(this.areConnected(row, col, nRow, nCol)) score += 5;
551
+ }
552
  }
553
+ return score;
 
 
 
554
  }
555
 
556
+ calculateTacticalScore(row, col) {
557
  let score = 0;
558
+ const neighbors = this.getNeighbors(row, col);
559
 
560
+ // μƒλŒ€ 돌 곡격 기회 확인
561
+ for(const [nRow, nCol] of neighbors) {
562
+ if(this.board[nRow][nCol] === 'black') {
563
+ const group = this.getGroup(nRow, nCol);
564
+ const liberties = this.countLiberties(group);
565
+ if(liberties <= 2) score += (20 - liberties * 5);
 
566
  }
567
  }
568
 
569
  return score;
570
  }
571
 
572
+ calculateSafetyScore(row, col) {
573
+ let score = 0;
574
+ const group = [[row, col]];
575
+ const liberties = this.countLiberties(group);
576
 
577
+ score += liberties * 5;
578
+
579
+ // 눈 ν˜•μ„± κ°€λŠ₯μ„± 체크
580
+ if(this.canFormEye(row, col)) score += 15;
 
 
 
 
 
 
 
 
 
 
581
 
582
+ return score;
583
  }
584
 
585
+ calculateStrategicScore(row, col) {
586
  let score = 0;
587
 
588
+ // 쀑앙 지역 μ„ ν˜Έ
589
+ const centerDistance = Math.abs(row - 9) + Math.abs(col - 9);
590
+ score += Math.max(0, 10 - centerDistance);
591
+
592
+ // 변에 뢙지 μ•Šλ„λ‘
593
+ if(row === 0 || row === 18 || col === 0 || col === 18) score -= 5;
594
+
595
+ // μŠ€νƒ€ν¬μΈνŠΈ 근처 μ„ ν˜Έ
596
+ if(this.isNearStarPoint(row, col)) score += 3;
 
 
 
 
 
 
 
597
 
598
  return score;
599
  }
 
613
  return liberties.size;
614
  }
615
 
616
+ canFormEye(row, col) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
617
  const neighbors = this.getNeighbors(row, col);
618
+ let whiteCount = 0;
619
+ let emptyCount = 0;
620
 
621
  for(const [nRow, nCol] of neighbors) {
622
+ if(this.board[nRow][nCol] === 'white') whiteCount++;
623
+ else if(this.board[nRow][nCol] === null) emptyCount++;
 
624
  }
625
 
626
+ return whiteCount >= 2 && emptyCount >= 1;
627
+ }
628
+
629
+ isNearStarPoint(row, col) {
630
+ const starPoints = [
631
+ [3,3], [3,9], [3,15],
632
+ [9,3], [9,9], [9,15],
633
+ [15,3], [15,9], [15,15]
634
+ ];
635
 
636
+ return starPoints.some(point =>
637
+ Math.abs(point[0] - row) <= 1 &&
638
+ Math.abs(point[1] - col) <= 1
639
+ );
640
  }
641
 
642
+ areConnected(row1, col1, row2, col2) {
643
+ const diagonal = Math.abs(row1 - row2) === 1 && Math.abs(col1 - col2) === 1;
644
+ if(!diagonal) return true;
645
 
646
+ // λŒ€κ°μ„  λ°©ν–₯ μ—°κ²° 확인
647
+ const mid1 = this.board[row1][col2];
648
+ const mid2 = this.board[row2][col1];
 
 
 
 
 
 
649
 
650
+ return mid1 === null || mid2 === null;
651
  }
652
  }
653