SGF ファイルを入力

SGF ファイルを入力して、出題図を表示します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. 今回は、詰碁を記録した SGF ファイルを入力して初期局面(出題図)を表示します。
    詰碁を記録するファイル形式は様々ですが、最も広く使われていて汎用性がある SGF 形式を用いることにします。
    SGF 形式の説明は SGF SGFファイル形式 を参照して下さい。
  2. SGF ファイルの出題図は、例えば次のようになっています。
    今回処理するのは[cf]までの初期画面(出題図)です。
    また局面を表示するのに最低限必要なプロパティ(AB, AW)だけを処理することにします。
    ;B[ca]以降には、棋譜(手順)が記録されています。
    (
    ;FF[3]GM[1]AP[PocketGoban Ver 0.999]
    SZ[19]DT[2014-02-13]
    KM[5.5]
    AB[bc][cc][db]AW[cd][dc][ec][eb][de][cf]
    ;B[ca];W[ab];B[bb];W[ea];B[aa];W[ba];B[ac];W[da];B[cb]
    )
    
  3. 座標 [xy] は、左上を [aa] として次のように定義されています。
    碁盤の左上端から縦軸、横軸へそれぞれa、b、c・・・とします。
      a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s
      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
    
  4. SGF FILE(FF[3]) は Shift-JIS でタイプされています。
    m_SGF は SGF FILE を内部コードに変換して入力する領域です。
    m_P は m_SGF の Index です。
        string      m_SGF;          // SGF FILE Source
        int         m_P;            // m_SGF Position
        short       m_Ishi = 0;     // 黒&白
        Point       m_Pos;
        string      wk;
    
  5. LoadSGF() 関数で SGF ファイルを入力します。
        private void Form_Load(object sender, EventArgs e)
        {
            m_Width = this.Width; 
            m_Height = this.Height;
            m_Ban.Initialize();
            LoadSGF("C:\\DATA\\Pocket囲碁\\test1.sgf");
        }
    
  6. SGF ファイルを入力する LoadSGF() 関数です。
    Console.WriteLine() でデバッグ情報を表示します。
    テキストファイルの入力は TEXT File の入力 を参照して下さい。
        private void LoadSGF(string file_name)
        {
            if (!File.Exists(file_name)) return;
            StreamReader reader = new StreamReader(file_name,Encoding.GetEncoding("Shift_JIS"));
            m_SGF= reader.ReadToEnd();
            Console.WriteLine(m_SGF);
            reader.Close();
    
            m_P = 0;
            m_Ishi = 0;
            Token();        // (
            m_P++;
            Token();        // ;
            m_P++;
            while(true)
            {
                wk = "*";
                switch(Token())
                {
                    case '(':
                    case ')':
                    case ';':
                        return;
                    case '*':       // プロパティ
                        if (wk=="AW")   m_Ishi= -1;
                        else if (wk=="AB")  m_Ishi= 1;
                        else m_Ishi = 0;
                        break;
                    case '[':
                        Console.WriteLine("[" + wk + "]  黒白" + m_Ishi);
                        if (m_Ishi!=0 && Convt())
                            m_Ban[m_Pos.X, m_Pos.Y] = m_Ishi;
                        break;
                }
            }
        }
    
  7. トークンを切り出す Token() 関数です。
    改行コード(\r\n)や空白は、区切り文字とみなしません。
    SGF ファイルは改行コードや空白を使って見やすいように整えて下さい。
        private char Token()
        {   int i;
    
            while(true)
            {   switch(m_SGF[m_P])
                {   case '(':
                    case ')':
                    case ';':
                        return m_SGF[m_P];
                    case '[':
                        m_P++;
                        for(i=m_P; m_SGF[i]!=']'; i++);
                        wk = m_SGF.Substring(m_P, i-m_P);
                        m_P = i+1;
                        return '[';
                    default:
                        if (m_SGF[m_P]>='A' && m_SGF[m_P]<='Z')
                        {
                            GetKey();
                            return '*';
                        }
                        m_P++;
                        break; 
                }
            }
        }
    
  8. プロパティを切り出して wk に格納する GetKey() 関数です。
        private void GetKey()
        {   int i;
    
            for(; m_SGF[m_P]<'A' || m_SGF[m_P]>'Z'; m_P++);
            for(i=m_P; m_SGF[i]>='A' && m_SGF[i]<='Z'; i++);
            wk = m_SGF.Substring(m_P, i-m_P);
            m_P = i;
        }
    
  9. wk の文字座標を Point に変換する Convt() 関数です。
        string      alph = "abcdefghijklmnopqrs";
    
        private bool Convt()
        {
            m_Pos.X = alph.IndexOf(wk[0]);
            m_Pos.Y = alph.IndexOf(wk[1]);
            if (m_Pos.X==-1 || m_Pos.Y==-1) return false;
            return true;
        }
    

[Next Chapter ↓] 棋譜ツリー
[Previous Chapter ↑] 打ち上げと禁じ手

超初心者のプログラム入門(C# Frame Work)