2014年5月13日火曜日

グループ番号表示の棋譜再生

 右の画像は、私が自作したブループ番号を表示するSGFファイル形式の棋譜データを再生するソフトを実行している様子だ。
 画像では見にくいかもしれないが、実際には石を打つ時に点滅したり、グループになる時に若干の間があり、見やすくなっている。
 ただ、勝敗は計算していないので、棋譜データの中にあるRE[ ]を見て、以下で判断するか、別の棋譜再生ソフトを利用する必要がある。ただ、日本ルールと中国ルールなどの違いがあり、勝敗は違っている場合がある。

持碁の時→"0" (zero)
黒勝ちの時→"B+何目かの数値"
白勝ちの時→"W+何目かの数値"

 黒 : 林 有美
 白 : 本因坊 秀策

黒: 65
白: 25
結果: 黒  40目勝ち

 以下はHSP言語(http://hsp.tv/)で作成したグループ番号
表示の棋譜再生ソフトのソースコードだ。
 HSP言語はBASIC言語に近いプログラム言語で、最新の
バージョンではC言語への変換やスマホでも利用できるソフトが
作成できるらしい。
 私の使っているバージョンは3.32だが、標準的な命令しか
使っていないので、どのバージョンでもコンパイル、実行できる
はずだ。(古いバージョンHSP2.61では、MacOS及び、
Linux版もあるらしい)
 実行ファイル(EXE形式のファイル)も作成できるのだが、
ダウンロードするようにしなければいけないのは面倒なので、ソー
スコードでの公開にした。

 コンパイル、実行すると、いきなりファイルダイアログが表示
されるので、SGFファイルを選択して読み込めば、再生を開始
する。(SGFファイルはネットで検索すればいくらでも見つか
る)
 なお、囲碁のハンデキャップがある場合、最初に黒石を連続で
打っていくので誤動作と間違えないように。
 ストップはないのでウィンドウの「×」をクリックして終了す
るか、再生がすべて終了するとダイアログが表示されるので、そ
こでボタンを選択する。

;グループ番号表示の棋譜再生ソフト(HSP言語)
;

*soki

    screen 0,600,600,0
   
    objmode 2
    font "", 15, 1

    randomize
   
    sdim buf,65000            ; テキストのバッファを確保
    buf=""                    ; バッファをクリア
   
    sdim handbuf,1000        ; ハンデキャップ用のバッファを確保

    sdim results,32,1000
    sdim zx0,2,1000
    sdim zy0,2,1000
    sdim zx1,2,1000
    sdim zy1,2,1000
    dim szx0,1000
    dim szy0,1000
    dim szx1,1000
    dim szy1,1000
    dim isi,1000
   
    dim ax,20,20
    dim ay,20,20
    dim sta,20,20
    dim grup0,20,20
    dim grup1,20,20

    gp0=1
    gp1=1
   
    color 0,0,0
   
    repeat 19      ;碁盤の作成と座標設定、石の有無の状態を初期化
          tt=cnt                ;縦の座標
        y=tt*30+30
        repeat 19
        yk=cnt                ;横の座標
        x=yk*30+30
        ax(yk,tt)=x
        ay(yk,tt)=y
        sta(yk,tt)=10
        if yk < 18 and tt < 18{
            line x,y,x+30,y
            line x+30,y,x+30,y+30
            line x+30,y+30,x,y+30
            line x,y+30,x,y
        }
        loop
    loop
   
    color 0,0,0                                      ;星の位置
    circle ax(3,3)-5,ay(3,3)-5,ax(3,3)+5,ay(3,3)+5,1        ;[dd]
    circle ax(9,3)-5,ay(9,3)-5,ax(9,3)+5,ay(9,3)+5,1        ;[jd]
    circle ax(15,3)-5,ay(15,3)-5,ax(15,3)+5,ay(15,3)+5,1    ;[pd]
    circle ax(3,9)-5,ay(3,9)-5,ax(3,9)+5,ay(3,9)+5,1        ;[dj]
    circle ax(9,9)-5,ay(9,9)-5,ax(9,9)+5,ay(9,9)+5,1        ;[jj]
    circle ax(15,9)-5,ay(15,9)-5,ax(15,9)+5,ay(15,9)+5,1    ;[pj]
    circle ax(3,15)-5,ay(3,15)-5,ax(3,15)+5,ay(3,15)+5,1    ;[dp]
    circle ax(9,15)-5,ay(9,15)-5,ax(9,15)+5,ay(9,15)+5,1    ;[jp]
    circle ax(15,15)-5,ay(15,15)-5,ax(15,15)+5,ay(15,15)+5,1 ;[pp]
   
    gosub *file_load                    ;SGFファイルのロードへ

*main

    yk=0
    tt=0
   
    cng=0
   
    sgfa=strtrim(buf,3)
   
    handa=""
    handc=""
    handb=0
    gocnt=0

    sgfc=instr(sgfa,0,"HA[")+3     ; ハンデキャップのデータの場所を調べる
    handa=strmid(sgfa,sgfc,1)
    sgfc=instr(sgfa,0,"Handicap/:")+10   ; 同じくハンデキャップのデータの場所を調べる
    handc=strmid(sgfa,sgfc,1)

    if (handa != "") or (handc != "") {
        if handa != "" {
            handb=int(handa)
        }
        if handc != "" {
            handb=int(handc)
        }
        handbuf=""
        gosub *hanchk        ; ハンデキャップの処理へ
    }

    if handbuf != "" {
        sgfc=instr(sgfa,0,";W[")        ;白石のデータの場所を調べる
        size=strlen(buf)
        sgfb=strmid(sgfa,sgfc,size)
        sgfb=handbuf+sgfb
    } else {
        sgfc=instr(sgfa,0,";B[")        ;黒石のデータの場所を調べる
        size=strlen(buf)
        sgfb=strmid(sgfa,sgfc,size)
    }

    split sgfb, ";", results        ;区切り文字「;」を見つけ配列にする

    repeat stat                 ;黒石と白石を別々に管理する
        za=strmid(results(cnt),0,2)
        if za == "B[" {
            zx0(gocnt)=strmid(results(cnt),2,1)
            if zx0(gocnt) != "t" {
                suhen=zx0(gocnt)
                gosub *suhenkan
                szx0(gocnt)=int(suhen)
           
                zy0(gocnt)=strmid(results(cnt),3,1)
                suhen=zy0(gocnt)
                gosub *suhenkan
                szy0(gocnt)=int(suhen)
                isi(gocnt)=0
                gocnt++
            }
        }
        if za == "W[" {
            zx1(gocnt)=strmid(results(cnt),2,1)
            if zx1(gocnt) != "t" {
                suhen=zx1(gocnt)
                gosub *suhenkan
                szx1(gocnt)=int(suhen)
           
                zy1(gocnt)=strmid(results(cnt),3,1)
                suhen=zy1(gocnt)
                gosub *suhenkan
                szy1(gocnt)=int(suhen)
                isi(gocnt)=1
                gocnt++
            }
        }
       
    loop

    repeat gocnt     ;棋譜データのすべてが表示されるまで繰り返す
        cng=isi(cnt)            ;石の判別 0;黒 1;白

        redraw 0         ;画面を一旦非表示にして、ちらつき防止

*modl

        if cng == 0 {
            yk=szx0(cnt)-1
            tt=szy0(cnt)-1
        } else {
            yk=szx1(cnt)-1
            tt=szy1(cnt)-1
        }

        redraw 1         ;画面を一旦表示して石を置く時に点滅する
        repeat 9
            if cng == 0 {
                color 0,0,0
                circle ax(yk,tt)-15,ay(yk,tt)-15,ax(yk,tt)+15,ay(yk,tt)+15,1
            }
            if cng == 1 {
                color 255,255,255
                circle ax(yk,tt)-15,ay(yk,tt)-15,ax(yk,tt)+15,ay(yk,tt)+15,1
                color 0,0,0
                circle ax(yk,tt)-15,ay(yk,tt)-15,ax(yk,tt)+15,ay(yk,tt)+15,0
            }
            await 100
            color 0,255,0
            circle ax(yk,tt)-15,ay(yk,tt)-15,ax(yk,tt)+15,ay(yk,tt)+15,1
            await 100
        loop
        redraw 0


        if cng == 0 {            ;黒石を打つ場合の表示処理
            sta(yk,tt)=0
            grup0(yk,tt)=gp0
            color 0,0,0
            circle ax(yk,tt)-15,ay(yk,tt)-15,ax(yk,tt)+15,ay(yk,tt)+15,1
            color 255,255,255
            if grup0(yk,tt) < 10 : pos ax(yk,tt)-5,ay(yk,tt)-9
            if (grup0(yk,tt) > 9) and (grup0(yk,tt) < 100) : pos ax(yk,tt)-9,ay(yk,tt)-9
            if grup0(yk,tt) > 99 : pos ax(yk,tt)-12,ay(yk,tt)-9
            mes grup0(yk,tt)
            gp0++
        }else{                    ;白石を打つ場合の表示処理
            sta(yk,tt)=1
            grup1(yk,tt)=gp1
            color 255,255,255
            circle ax(yk,tt)-15,ay(yk,tt)-15,ax(yk,tt)+15,ay(yk,tt)+15,1
            color 0,0,0
            circle ax(yk,tt)-15,ay(yk,tt)-15,ax(yk,tt)+15,ay(yk,tt)+15,0
            if grup1(yk,tt) < 10 : pos ax(yk,tt)-5,ay(yk,tt)-9
            if (grup1(yk,tt) > 9) and (grup1(yk,tt) < 100) : pos ax(yk,tt)-9,ay(yk,tt)-9
            if grup1(yk,tt) > 99 : pos ax(yk,tt)-12,ay(yk,tt)-9
            mes grup1(yk,tt)
            gp1++
        }
   
        gosub *ana        ;石が囲まれているかの判断処理
   

        redraw 1        ;画面を表示する
        await 1000        ; 全体のスピード調節
    loop

    dialog "棋譜再生終了"+"\n終わりますか?",2
    if stat == 6 : end
    if stat == 7 {
        mref sokika,64
        sokika=0
        goto *soki
    }

end

*ana                ;石が囲まれているかの判断処理

    repeat 19
          tt=cnt
        repeat 19
            yk=cnt
           
            if sta(yk,tt) == 0 {      ;黒石の上下左右をチェックする

                if (yk+1) <= 18 {
                    if sta(yk+1,tt) == 0 {
                        if grup0(yk,tt) < grup0(yk+1,tt) {
                            gra=grup0(yk,tt)
                            grb=grup0(yk+1,tt)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp0    ;同じ色の石があればグループ番号統一処理
                            yk=oldyk
                            tt=oldtt
                        }
                        if grup0(yk,tt) > grup0(yk+1,tt) {
                            gra=grup0(yk+1,tt)
                            grb=grup0(yk,tt)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp0
                            yk=oldyk
                            tt=oldtt
                        }
                    }
                }
                if (tt+1) <= 18 {
                    if sta(yk,tt+1) == 0 {
                        if grup0(yk,tt) < grup0(yk,tt+1) {
                            gra=grup0(yk,tt)
                            grb=grup0(yk,tt+1)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp0
                            yk=oldyk
                            tt=oldtt
                        }
                        if grup0(yk,tt) > grup0(yk,tt+1) {
                            gra=grup0(yk,tt+1)
                            grb=grup0(yk,tt)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp0
                            yk=oldyk
                            tt=oldtt
                        }
                    }
                }
                if (yk-1) >= 0 {
                    if sta(yk-1,tt) == 0 {
                        if grup0(yk,tt) < grup0(yk-1,tt) {
                            gra=grup0(yk,tt)
                            grb=grup0(yk-1,tt)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp0
                            yk=oldyk
                            tt=oldtt
                        }
                        if grup0(yk,tt) > grup0(yk-1,tt) {
                            gra=grup0(yk-1,tt)
                            grb=grup0(yk,tt)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp0
                            yk=oldyk
                            tt=oldtt
                        }
                    }
                }
                if (tt-1) >= 0 {
                    if sta(yk,tt-1) == 0 {
                        if grup0(yk,tt) < grup0(yk,tt-1) {
                            gra=grup0(yk,tt)
                            grb=grup0(yk,tt-1)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp0
                            yk=oldyk
                            tt=oldtt
                        }
                        if grup0(yk,tt) > grup0(yk,tt-1) {
                            gra=grup0(yk,tt-1)
                            grb=grup0(yk,tt)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp0
                            yk=oldyk
                            tt=oldtt
                        }
                    }
                }
            }

           
            if sta(yk,tt) == 1 {     ;白石の上下左右をチェックする

                if (yk+1) <= 18 {
                    if sta(yk+1,tt) == 1 {
                        if grup1(yk,tt) < grup1(yk+1,tt) {
                            gra=grup1(yk,tt)
                            grb=grup1(yk+1,tt)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp1    ;同じ色の石があればグループ番号統一処理
                            yk=oldyk
                            tt=oldtt
                        }
                        if grup1(yk,tt) > grup1(yk+1,tt) {
                            gra=grup1(yk+1,tt)
                            grb=grup1(yk,tt)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp1
                            yk=oldyk
                            tt=oldtt
                        }
                    }
                }
                if (tt+1) <= 18 {
                    if sta(yk,tt+1) == 1 {
                        if grup1(yk,tt) < grup1(yk,tt+1) {
                            gra=grup1(yk,tt)
                            grb=grup1(yk,tt+1)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp1
                            yk=oldyk
                            tt=oldtt
                        }
                        if grup1(yk,tt) > grup1(yk,tt+1) {
                            gra=grup1(yk,tt+1)
                            grb=grup1(yk,tt)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp1
                            yk=oldyk
                            tt=oldtt
                        }
                    }
                }
                if (yk-1) >= 0 {
                    if sta(yk-1,tt) == 1 {
                        if grup1(yk,tt) < grup1(yk-1,tt) {
                            gra=grup1(yk,tt)
                            grb=grup1(yk-1,tt)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp1
                            yk=oldyk
                            tt=oldtt
                        }
                        if grup1(yk,tt) > grup1(yk-1,tt) {
                            gra=grup1(yk-1,tt)
                            grb=grup1(yk,tt)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp1
                            yk=oldyk
                            tt=oldtt
                        }
                    }
                }
                if (tt-1) >= 0 {
                    if sta(yk,tt-1) == 1 {
                        if grup1(yk,tt) < grup1(yk,tt-1) {
                            gra=grup1(yk,tt)
                            grb=grup1(yk,tt-1)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp1
                            yk=oldyk
                            tt=oldtt
                        }
                        if grup1(yk,tt) > grup1(yk,tt-1) {
                            gra=grup1(yk,tt-1)
                            grb=grup1(yk,tt)
                            oldyk=yk
                            oldtt=tt
                            gosub *anagrp1
                            yk=oldyk
                            tt=oldtt
                        }
                    }
                }
            }
        loop
    loop

    if cng == 1 {        ;囲んだ石を消す時の優先順位
        gosub *anachk0
        gosub *anachk1
    } else {
        gosub *anachk1
        gosub *anachk0
    }
    return

*anachk0                ;黒石が囲まれているかのチェック
                        ;上下左右に一つでも空きがあれば消さない
    repeat gp0            ;黒石のグループを一つずつ調べる
        grc0=cnt
        anaflg0=0
        repeat 19
              tt=cnt
            repeat 19
                yk=cnt
           
                if grup0(yk,tt) == grc0 {

                    if (yk-1) >= 0 {
                        if (sta(yk-1,tt) == 10) or (sta(yk-1,tt) == 2) : anaflg0=1
                    }
                    if (yk+1) <= 18 {
                        if (sta(yk+1,tt) == 10) or (sta(yk+1,tt) == 2) : anaflg0=2
                    }
                    if (tt-1) >= 0 {
                        if (sta(yk,tt-1) == 10) or (sta(yk,tt-1) == 2) : anaflg0=3
                    }
                    if (tt+1) <= 18 {
                        if (sta(yk,tt+1) == 10) or (sta(yk,tt+1) == 2) : anaflg0=4
                    }
                }
            loop
        loop
   
        if (anaflg0 == 0) {
            oldyk=yk
            oldtt=tt
            gosub *sakgrp0        ;空きがなければ削除へ
            yk=oldyk
            tt=oldtt
        }
    loop
   
    return

*anachk1                ;白石が囲まれているかのチェック
                  ;上下左右に一つでも空きがあれば消さない
    repeat gp1            ;白石のグループを一つずつ調べる
        grc1=cnt
        anaflg1=0
        repeat 19
              tt=cnt
            repeat 19
                yk=cnt
           
                if grup1(yk,tt) == grc1 {
           
                    if (yk-1) >= 0 {
                        if (sta(yk-1,tt) == 10) or (sta(yk-1,tt) == 2) : anaflg1=1
                    }
                    if (yk+1) <= 18 {
                        if (sta(yk+1,tt) == 10) or (sta(yk+1,tt) == 2) : anaflg1=2
                    }
                    if (tt-1) >= 0 {
                        if (sta(yk,tt-1) == 10) or (sta(yk,tt-1) == 2) : anaflg1=3
                    }
                    if (tt+1) <= 18 {
                        if (sta(yk,tt+1) == 10) or (sta(yk,tt+1) == 2) : anaflg1=4
                    }
                }
            loop
        loop
   
        if (anaflg1 == 0) {
            oldyk=yk
            oldtt=tt
            gosub *sakgrp1            ;空きがなければ削除へ
            yk=oldyk
            tt=oldtt
        }
    loop
   
    return

*anagrp0            ;黒石のグループ番号を統一する処理
   
    repeat 19
          tt=cnt
        repeat 19
        yk=cnt

        if grup0(yk,tt) == grb {
            grup0(yk,tt)=gra
            color 150,150,150
            circle ax(yk,tt)-15,ay(yk,tt)-15,ax(yk,tt)+15,ay(yk,tt)+15,1
            color 255,255,255
            if grup0(yk,tt) < 10 : pos ax(yk,tt)-5,ay(yk,tt)-9       

;グループ番号の表示位置を桁数で変えている
            if (grup0(yk,tt) > 9) and (grup0(yk,tt) < 100) : pos ax(yk,tt)-9,ay(yk,tt)-9
            if grup0(yk,tt) > 99 : pos ax(yk,tt)-12,ay(yk,tt)-9
            mes grup0(yk,tt)
        }

        loop
    loop

    return
   
*anagrp1            ;白石のグループ番号を統一する処理
   
    repeat 19
          tt=cnt
        repeat 19
        yk=cnt

        if grup1(yk,tt) == grb {
            grup1(yk,tt)=gra
            color 230,230,230
            circle ax(yk,tt)-15,ay(yk,tt)-15,ax(yk,tt)+15,ay(yk,tt)+15,1
            color 0,0,0
            circle ax(yk,tt)-15,ay(yk,tt)-15,ax(yk,tt)+15,ay(yk,tt)+15,0
            if grup1(yk,tt) < 10 : pos ax(yk,tt)-5,ay(yk,tt)-9       

;グループ番号の表示位置を桁数で変えている
            if (grup1(yk,tt) > 9) and (grup1(yk,tt) < 100) : pos ax(yk,tt)-9,ay(yk,tt)-9
            if grup1(yk,tt) > 99 : pos ax(yk,tt)-12,ay(yk,tt)-9
            mes grup1(yk,tt)
        }

        loop
    loop

    return

*sakgrp0            ;黒石の削除処理
   
    repeat 19
          tt=cnt
        repeat 19
        yk=cnt

        if grup0(yk,tt) == grc0 {
            sta(yk,tt)=10
            grup0(yk,tt)=0
            color 255,0,0
            circle ax(yk,tt)-15,ay(yk,tt)-15,ax(yk,tt)+15,ay(yk,tt)+15,1
        }

        loop
    loop

    return
   
*sakgrp1            ;白石の削除処理
   
    repeat 19
          tt=cnt
        repeat 19
        yk=cnt

        if grup1(yk,tt) == grc1 {
            sta(yk,tt)=10
            grup1(yk,tt)=0
            color 0,0,255
            circle ax(yk,tt)-15,ay(yk,tt)-15,ax(yk,tt)+15,ay(yk,tt)+15,1
        }

        loop
    loop

    return

*file_load                    ;SGFファイルのロード処理
    dialog "sgf",16,"テキストファイル"
    if stat=0 : goto *dlcan2
    notesel buf
    noteload refstr            ; テキストファイル読み込み
   
    screen 1,700,500,0
    objmode 2
    font msmincho, 18, 0
    mesbox buf,700,500,1,0    ; 最大サイズ編集許可
    objprm 0,buf
    gsel 0,1
    return
   
*dlcan2
    stop

*suhenkan            ;SGFファイル形式の石の位置の文字を数値にする
    strrep suhen,"a","1"
    strrep suhen,"b","2"
    strrep suhen,"c","3"
    strrep suhen,"d","4"
    strrep suhen,"e","5"
    strrep suhen,"f","6"
    strrep suhen,"g","7"
    strrep suhen,"h","8"
    strrep suhen,"i","9"
    strrep suhen,"j","10"
    strrep suhen,"k","11"
    strrep suhen,"l","12"
    strrep suhen,"m","13"
    strrep suhen,"n","14"
    strrep suhen,"o","15"
    strrep suhen,"p","16"
    strrep suhen,"q","17"
    strrep suhen,"r","18"
    strrep suhen,"s","19"
    return
   
*hanchk                ;ハンデキャップの黒石を置く数を追加する処理
    if handb == 2 {
        handbuf=";B[pd];B[dp]"
    }
    if handb == 3 {
        handbuf=";B[pd];B[dp];B[pp]"
    }
    if handb == 4 {
        handbuf=";B[pd];B[dp];B[pp];B[dd]"
    }
    if handb == 5 {
        handbuf=";B[pd];B[dp];B[pp];B[dd];B[jj]"
    }
    if handb == 6 {
        handbuf=";B[pd];B[dp];B[pp];B[dd];B[pj];B[dj]"
    }
    if handb == 7 {
        handbuf=";B[pd];B[dp];B[pp];B[dd];B[pj];B[dj];B[jj]"
    }
    if handb == 8 {
        handbuf=";B[pd];B[dp];B[pp];B[dd];B[pj];B[dj];B[jd];B[jp]"
    }
    if handb == 9 {
        handbuf=";B[pd];B[dp];B[pp];B[dd];B[pj];B[dj];B[jd];B[jp];B[jj]"
    }

    return

2014年5月12日月曜日

グループとして考えよう

九路盤にCOMがアトランダムに石を打つ様子
石を並べてできた線をグループと考えて
見てみると、どの場所にどんな線のグルー
プを作るのが有利になるかが分かってくる。
 それが、囲碁の定石というものなのだが、
超初心者が定石を覚えても、そのとおりの
展開にはならない。
 最初は、相手の置いていく石に合わせて、
柔軟に線が作れるように練習したほうがい
い。
  右の画像は、九路盤にコンピュータがアト
ランダムに石を打っていく様子で、石に表示
している番号はグループ番号だ。
 グループ番号は、同じ色の石が上下左右
にある時、小さい番号に統一される。
 なお、この画像は、囲碁の正式なルールと
は違い、一度囲って石を取り除いた場所に
は、どちらも石が置けず、石を置く場所がな
くなったら終了するようになっている。

2014年5月10日土曜日

囲碁はフィールドバトルだ

 囲碁はジャングルのように相手の見えないフィールドで戦うゲー
ムだと考えた方がいい。
 どちらも見えない状態では、戦いようがないので、お互いに少
しずつ姿を見せることにする。それが、石を交互に一つずつ置く
ということだ。
 まず、黒石から最初に置き、次に白石を置くというルールで始
める。
 石を置く場所は、碁盤にひかれた線と線が交わった場所(交点)
で、もちろんどこに置いてもいい。(隅や角の点にも置ける)
 この石が「守るべきもの」で、自分の石を守りつつ、相手の石
を攻撃することで勝敗が決まってくる。
 どうやって自分の石を守り、相手の石を攻撃するのか?
 自分の石を守るには、自分の石の上下左右に、別の自分の石を
置いていき「グループ」を作る。そのグループを塊のようにする
のではなく、線にして、その線が切れないようにできれば、勝つ
ことができる。
 相手の石を攻撃するということは、相手の石が線のようになっ
ていくことを邪魔して、分断することで、成功すれば相手を弱ら
せ、有利に戦うことができる。
 ここで問題なのが、自分が石を線にしていることが相手にばれ
ると、相手に邪魔されるので、色々な場所に石を分散して置いて
いき、相手をかく乱する。また、こうすることで広範囲に線がで
きるという効果もある。
 これは、神出鬼没なゲリラ戦をするのが上手な人が、囲碁の上
手な人ということになる。
 こう考えて囲碁を見ていけば、途中経過でも、どちらが有利に
展開しているかが分かるようになる。
 最終的に勝敗を決めるのは、自分の線ができた時の影響範囲が
大きい方が勝ちとなり、この時に陣地という考え方を利用する。
 最初は、どちらが勝ちか負けかは気にする必要はなく、知りた
ければ、囲碁対局ソフトを利用すれば、計算をしてくれるので勝
敗はすぐに分かる。

そもそも囲碁は陣取りゲームではない

 囲碁は陣取りゲームとして説明されることが一般的だが、これ
が超初心者には理解できない。
 碁盤の上には何もなく、どこに石を置いてもいい。だから、ど
こを守り、どこを攻めればいいのか分からない。
 自分で陣地と決めた場所が、相手も同じ場所を陣地にすること
もあり、守るべき場所が実は攻める場所になることもある。
 塀のように石で囲ったとしても、相手はその中に簡単に石を置
くことができるので、守っているという感覚になれない。
 やっている途中経過では、どちらが有利で、どちらが不利なの
かがさっぱり分からない。
 終了する時も、すべての場所に石を置いて終わるのではなく、
自分たちが石を置く場所がなくなったと判断して終わるのも超初
心者には理解しがたい。
 こうしたことは囲碁のルールが確立した過程を知らないと分か
らない。
 まず、19路盤に二人が交互に石を置いていくというルールだ
けにして、すべての場所に石を置いていくと、先に石を置いた方
が必ず勝ってしまう。(石を置ける交点が361あり、先に置く
方は、181個が置け、後に置く方は、180個しか置けない)
そこで、後から石を置く方も勝てるようにするにはどうしたらよ
いか?
 とりあえず、相手の石を上下左右から囲んだら、その石が取れ
るようにして、石を取った場所には、どちらも石を置けないとい
うルールにする。こうすると後から石を置く方も勝てるようにな
る。
 今度は、相手の石が沢山集まっている場所を取り囲んだら、そ
の石の集まりをすべて取れるようなルールを追加すると、さらに
面白くなる。
 ここまでのルールでも十分、ゲームとして楽しめ、陣取りゲー
ムという考え方はここに完成したと思われる。
 ところがこれに、石を取り除いた場所に再び石が置けるような
ルールを追加してしまった。
 こうするとなかなか終わりが見えてこないゲームとなり、これ
が超初心者を悩ませる原因となっている。
 まずは、「囲碁は陣取りゲーム」という考え方を忘れよう。