homework-08

1) 把程序编译通过, 跑起来 , 把正确的 playPrev(GoMove) 的方法给实现了.

解释一下playPrev里都要做什么

1 把gm的子去除

2 转移gm的mark 到它之前的棋子

3 并设置之前的棋子为待更新(重画)

4 如果当前棋子有吃掉什么的画,需要把吃掉的都画回去.

5 取吃掉的棋子数组, 生成一个迭代器

6 遍历数组,对每个棋子设置nokilled,setstorn(相反颜色)

7 重画

 1         public void playPrev(GoMove gm)
 2         {
 3             int i = gm.Point.X;
 4             int j = gm.Point.Y;
 5             Grid[i,j].removeStone();
 6             m_gmLastMove = gameTree.peekPrev();
 7             if (m_gmLastMove != null)
 8                 Grid[m_gmLastMove.Point.X,m_gmLastMove.Point.Y].setUpdated();
 9             if (gm.DeadGroup != null)
10             {
11                 System.Collections.IEnumerator myEnumerator = gm.DeadGroup.GetEnumerator();
12                 while (myEnumerator.MoveNext())
13                 {
14                     Point p;    
15                     p = (Point)myEnumerator.Current;
16                     Grid[p.X,p.Y].setNoKilled();
17                     Grid[p.X,p.Y].setStone(nextTurn(gm.Color));
18                 }
19             }
20             optRepaint();
22             return; 
23         }

2)根据你选择的教材 (三本之一或更多),点评一下这个程序设计方面的不足,例如:编码风格,程序架构,程序的错误处理,文件处理,UI 等等.

首先我们得明确一下,代码的作者是出于什么目的去写这么一个程序的,从博客上可以看到:

“在很久以前为了学习Java, 就写了一个 Java 的围棋下棋程序 (不是人工智能,只是在屏幕上展现下棋的过程),  后来C# 出现之后,他又随意地把程序改写为C#,  经过简单测试之后,他就把程序放在一边了。”

所以,代码是入门时出于“学习java”的目的去写的,又“随意”改成C#。

这么说来,当时的软件需求就是:“写这个程序首先是为了学习java,后来更改是为了学C#。” 是一个纯粹是学习性质的代码,风格会更偏向于草稿。

所以,代码出现了这么几个衍生的毛病:

1 游戏无目的,对围棋无“算目”模块,无法完成一次完整的对弈。

2 很多类,函数,函数中的变量,都只出现在程序中一次,其他地方没使用过,造成代码冗余不说,毫无意义的代码看起来简直恶心。

3 几乎 没有错误处理

4 函数之间分层不明确

5 程序还有架构吗? 就是堆叠类罢了。类没有经过设计,没有任何继承重用。

6 到底软件是作为一个:下棋游戏,还是:看谱软件。很遗憾,两方面都没实现好。

7 label和mark的意义模糊。

代码问题很多,但我觉得这都是由于“需求”而导致的问题,因为这样的需求,而产生了这样的代码。你再去批评软件架构如何差,错误如何没处理,UI如何烂。。是毫无意义的, 因为作为一个“学习用”的代码, 压根就不需要考虑这些。

让我们去阅读一个“本身就没什么价值”的程序有意义吗?我觉得意义不大,甚至只能说是浪费时间,如果我想练习我的阅读代码能力,我会去读那些开源库,读Linux源码,因为那些是经过精心设计的代码,读完是能对自己能力有提升的。

当然咯,以后如果步入社会还是可能会遇到读“烂代码”这样的差事,我想,我们能做的只能是:

    学好知识,以后尼玛去屌一点的水平高一点的公司,别特么读这么随意的代码了。

3) 程序的注释, 请把这个程序中被标成 “zzzz” 的注释都恢复过来。

代码注释已经签入https://github.com/Forwil/homework-06/blob/master/Goboard.cs

 由于没什么时间去了解cgf(机智游戏格式smartgameformat)格式,所以最后的文件处理没写注释,不过这也不影响对于程序结构的理解。

   1 /**
   2  *  Go Applet
   3  *  1996.11        xinz    written in Java
   4  *  2001.3        xinz    port to C#
   5  *  2001.5.10    xinz    file parsing, back/forward
   6  */
   7 
   8 using System;
   9 using System.Drawing;
  10 using System.Collections;
  11 using System.ComponentModel;
  12 using System.Windows.Forms;
  13 using System.Data;
  14 using System.IO;
  15 using System.Diagnostics; 
  16 
  17 namespace Go_WinApp
  18 {
  19 
  20     public enum StoneColor : byte
  21     {
  22         black = 0, white = 1
  23     }
  24 
  25 
  26     public class GoBoard : System.Windows.Forms.Form
  27     {
  28         string [] strLabels; // {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t"};
  29 
  30         int nSize;                        //棋盘大小(像素)
  31         const int nBoardMargin = 10;    //边界大小
  32         int nCoodStart = 4;
  33         const int    nBoardOffset = 20;
  34         int nEdgeLen = nBoardOffset + nBoardMargin;
  35         int nTotalGridWidth = 360 + 36;    //总大小
  36         int nUnitGridWidth = 22;        //单个格大小
  37         int nSeq = 0;
  38         Rectangle rGrid;            //棋盘
  39         StoneColor m_colorToPlay;   //当前颜色. 
  40         GoMove m_gmLastMove;        //最近一次下的子, 
  41         Boolean bDrawMark;            //渲染锁. 
  42         Boolean m_fAnyKill;            //标记是否有被kill的棋子
  43         Spot [,] Grid;                //格子二维度数组
  44         Pen penGrid, penStoneW, penStoneB,penMarkW, penMarkB;
  45         Brush brStar, brBoard, brBlack, brWhite, m_brMark;
  46     
  47 
  48         int nFFMove = 10;   //一次恢复10个棋子. 
  49         int nRewindMove = 10;  // 没用过; 
  50 
  51         GoTree    gameTree;
  52 
  53         // 各种显示控件
  54         private System.ComponentModel.Container components;
  55         private System.Windows.Forms.TextBox textBox1;
  56         private System.Windows.Forms.Button Rewind;
  57         private System.Windows.Forms.Button FForward;
  58         private System.Windows.Forms.Button Save;
  59         private System.Windows.Forms.Button Open;
  60         private System.Windows.Forms.Button Back;
  61         private System.Windows.Forms.Button Forward;
  62 
  63         public GoBoard(int nSize)
  64         {
  65             InitializeComponent();
  66 
  67             this.nSize = nSize;  //当前棋盘大小
  68 
  69             m_colorToPlay = StoneColor.black;
  70 
  71             Grid = new Spot[nSize,nSize];
  72             for (int i=0; i<nSize; i++)
  73                 for (int j=0; j<nSize; j++)
  74                     Grid[i,j] = new Spot();
  75             penGrid = new Pen(Color.Brown, (float)0.5);
  76             penStoneW = new Pen(Color.WhiteSmoke, (float)1);
  77             penStoneB = new Pen(Color.Black,(float)1);
  78             penMarkW = new Pen(Color.Blue, (float) 1);
  79             penMarkB = new Pen(Color.Beige, (float) 1);
  80 
  81             brStar = new SolidBrush(Color.Black);
  82             brBoard = new SolidBrush(Color.Orange);
  83             brBlack = new SolidBrush(Color.Black);
  84             brWhite = new SolidBrush(Color.White);
  85             m_brMark = new SolidBrush(Color.Red);
  86 
  87             rGrid = new Rectangle(nEdgeLen, nEdgeLen,nTotalGridWidth, nTotalGridWidth);
  88             strLabels = new string [] {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t"};
  89             gameTree = new GoTree();
  90         }
  91 
  92         /// 初始化啊
  93         private void InitializeComponent()
  94         {
  95             this.Open = new System.Windows.Forms.Button();
  96             this.Save = new System.Windows.Forms.Button();
  97             this.Rewind = new System.Windows.Forms.Button();
  98             this.Forward = new System.Windows.Forms.Button();
  99             this.Back = new System.Windows.Forms.Button();
 100             this.FForward = new System.Windows.Forms.Button();
 101             this.textBox1 = new System.Windows.Forms.TextBox();
 102             this.SuspendLayout();
 103             // 
 104             // open
 105             // 
 106             this.Open.Location = new System.Drawing.Point(445, 88);
 107             this.Open.Name = "Open";
 108             this.Open.Size = new System.Drawing.Size(56, 23);
 109             this.Open.TabIndex = 2;
 110             this.Open.Text = "open";
 111             this.Open.Click += new System.EventHandler(this.Open_Click);
 112             // 
 113             // save
 114             // 
 115             this.Save.Location = new System.Drawing.Point(509, 88);
 116             this.Save.Name = "Save";
 117             this.Save.Size = new System.Drawing.Size(56, 23);
 118             this.Save.TabIndex = 3;
 119             this.Save.Text = "save";
 120             this.Save.Click += new System.EventHandler(this.Save_Click);
 121             // 
 122             // rewind
 123             // 
 124             this.Rewind.Location = new System.Drawing.Point(509, 56);
 125             this.Rewind.Name = "Rewind";
 126             this.Rewind.Size = new System.Drawing.Size(56, 23);
 127             this.Rewind.TabIndex = 5;
 128             this.Rewind.Text = "<<";
 129             this.Rewind.Click += new System.EventHandler(this.Rewind_Click);
 130             // 
 131             // forward
 132             // 
 133             this.Forward.Location = new System.Drawing.Point(445, 24);
 134             this.Forward.Name = "Forward";
 135             this.Forward.Size = new System.Drawing.Size(56, 23);
 136             this.Forward.TabIndex = 0;
 137             this.Forward.Text = ">";
 138             this.Forward.Click += new System.EventHandler(this.Forward_Click);
 139             // 
 140             // back
 141             // 
 142             this.Back.Location = new System.Drawing.Point(509, 24);
 143             this.Back.Name = "Back";
 144             this.Back.Size = new System.Drawing.Size(56, 23);
 145             this.Back.TabIndex = 1;
 146             this.Back.Text = "<";
 147             this.Back.Click += new System.EventHandler(this.Back_Click);
 148             // 
 149             // fforward
 150             // 
 151             this.FForward.Location = new System.Drawing.Point(445, 56);
 152             this.FForward.Name = "FForward";
 153             this.FForward.Size = new System.Drawing.Size(56, 23);
 154             this.FForward.TabIndex = 4;
 155             this.FForward.Text = ">>";
 156             this.FForward.Click += new System.EventHandler(this.FForward_Click);
 157             // 
 158             // textbox1
 159             // 
 160             this.textBox1.Location = new System.Drawing.Point(447, 128);
 161             this.textBox1.Multiline = true;
 162             this.textBox1.Name = "textBox1";
 163             this.textBox1.Size = new System.Drawing.Size(120, 311);
 164             this.textBox1.TabIndex = 6;
 165             this.textBox1.Text = "please oepn a .sgf file to view, or just play on the board";
 166             this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
 167             // 
 168             // add to  controls and others
 169            // 
 170             this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
 171             this.AutoScroll = true;
 172             this.ClientSize = new System.Drawing.Size(581, 478);
 173             this.Controls.Add(this.textBox1);
 174             this.Controls.Add(this.Rewind);
 175             this.Controls.Add(this.FForward);
 176             this.Controls.Add(this.Save);
 177             this.Controls.Add(this.Open);
 178             this.Controls.Add(this.Back);
 179             this.Controls.Add(this.Forward);
 180             this.Name = "GoBoard";
 181             this.Text = "Go_WinForm";
 182             this.Paint += new System.Windows.Forms.PaintEventHandler(this.PaintHandler);
 183             this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MouseUpHandler);
 184             this.Click += new System.EventHandler(this.GoBoard_Click);
 185             this.ResumeLayout(false);
 186             this.PerformLayout();
 187 
 188         }
 189 
 190         protected void textBox1_TextChanged (object sender, System.EventArgs e)
 191         {
 192             return;
 193         }
 194 
 195         private void PaintHandler(Object sender, PaintEventArgs e)
 196         {
 197             UpdateGoBoard(e);
 198         }
 199 
 200         protected void Save_Click (object sender, System.EventArgs e)
 201         {
 202             return;
 203         }
 204 
 205         protected void Open_Click (object sender, System.EventArgs e)
 206         {
 207             OpenFile();
 208             showGameInfo();
 209         }
 210 
 211         protected void Rewind_Click (object sender, System.EventArgs e)
 212         {
 213             gameTree.reset();
 214             resetBoard();
 215             showGameInfo();
 216         }
 217 
 218         protected void FForward_Click (object sender, System.EventArgs e)
 219         {
 220             if (gameTree != null)
 221             {
 222                 int i = 0; 
 223                 GoMove gm = null;
 224                 for (gm = gameTree.doNext(); gm != null; gm = gameTree.doNext()) 
 225                 {
 226                     playNext(ref gm);
 227                     if (i++ > nFFMove)
 228                         break; 
 229                 }
 230             }
 231         }
 232 
 233         protected void Forward_Click (object sender, System.EventArgs e)
 234         {
 235             GoMove gm = gameTree.doNext();
 236             if (null != gm)
 237             {
 238                 playNext(ref gm);
 239             }
 240         }
 241 
 242         private void showGameInfo()
 243         {
 244             //清空textbox1并且更新为新的info
 245             textBox1.Clear();
 246             textBox1.AppendText(gameTree.Info);
 247         }
 248 
 249         protected void Back_Click (object sender, System.EventArgs e)
 250         {
 251             GoMove gm = gameTree.doPrev();    //令gm为历史记录中刚下过的那个棋子
 252             if (null != gm)
 253             {
 254                 playPrev(gm);
 255                 showGameInfo();
 256             }
 257             else
 258             {
 259                 resetBoard();
 260                 showGameInfo(); 
 261             }
 262         }
 263 
 264         Boolean onBoard(int x, int y) 
 265         {
 266             return (x>=0 && x<nSize && y>=0 && y<nSize);
 267         }
 268 
 269         protected void GoBoard_Click (object sender, System.EventArgs e)
 270         {
 271             return;
 272         }
 273 
 274         private Point PointToGrid(int x, int y)
 275         {
 276             Point p= new Point(0,0);
 277             p.X = (x - rGrid.X + nUnitGridWidth/2) / nUnitGridWidth;
 278             p.Y = (y - rGrid.Y + nUnitGridWidth/2) / nUnitGridWidth;
 279             return p;
 280         }
 281 
 282         //判断到达一定区域内才能下子
 283         private Boolean closeEnough(Point p, int x, int y)
 284         {
 285             if (x < rGrid.X+nUnitGridWidth*p.X-nUnitGridWidth/3 ||
 286                 x > rGrid.X+nUnitGridWidth*p.X+nUnitGridWidth/3 ||
 287                 y < rGrid.Y+nUnitGridWidth*p.Y-nUnitGridWidth/3 ||
 288                 y > rGrid.Y+nUnitGridWidth*p.Y+nUnitGridWidth/3)
 289             {
 290                 return false;
 291             }
 292             else 
 293                 return true;
 294         }
 295         /// 下子的处理函数
 296         private void MouseUpHandler(Object sender,MouseEventArgs e)
 297         {
 298             Point p;
 299             GoMove    gmThisMove;
 300 
 301             p = PointToGrid(e.X,e.Y);
 302             if (!onBoard(p.X, p.Y) || !closeEnough(p,e.X, e.Y)|| Grid[p.X,p.Y].hasStone())
 303                 return; //判断是否当前点击点可下子.
 304 
 305             //如果可以,新建新的一个move,play它.
 306             gmThisMove = new GoMove(p.X, p.Y, m_colorToPlay, 0);
 307             playNext(ref gmThisMove);
 308             gameTree.addMove(gmThisMove);
 309         }
 310 
 311         public void playNext(ref GoMove gm) 
 312         {
 313             Point p = gm.Point;
 314             m_colorToPlay = gm.Color;    //当前颜色为当前棋子的颜色
 315 
 316             //先清除屌所有的label和mark
 317             clearLabelsAndMarksOnBoard(); 
 318             
 319             if (m_gmLastMove != null)
 320                 repaintOneSpotNow(m_gmLastMove.Point);
 321 
 322             bDrawMark = true;
 323             Grid[p.X,p.Y].setStone(gm.Color);
 324             m_gmLastMove = new GoMove(p.X, p.Y, gm.Color, nSeq++);
 325             //重新画出marks和labels
 326             setLabelsOnBoard(gm);
 327             setMarksOnBoard(gm);
 328             
 329             doDeadGroup(nextTurn(m_colorToPlay));
 330             //处理无气的对方棋子,如果存在,则下面进行处理. 
 331             if (m_fAnyKill)
 332                 appendDeadGroup(ref gm, nextTurn(m_colorToPlay));
 333             else //处理无气的己方棋子.
 334             {
 335                 doDeadGroup(m_colorToPlay);
 336                 if (m_fAnyKill)
 337                     appendDeadGroup(ref gm, m_colorToPlay);
 338             }
 339             m_fAnyKill = false;
 340             
 341             optRepaint();
 342 
 343             //转换下棋子颜色
 344             m_colorToPlay = nextTurn(m_colorToPlay);
 345             
 346             //更新注释
 347             textBox1.Clear();
 348             textBox1.AppendText(gm.Comment);
 349         }
 350 
 351         private void appendDeadGroup(ref GoMove gm, StoneColor c)
 352         {
 353             ArrayList a = new ArrayList();
 354             for (int i=0; i<nSize; i++)
 355                 for (int j=0; j<nSize; j++)
 356                     if (Grid[i,j].isKilled())
 357                     {
 358                         Point pt = new Point(i,j);
 359                         a.Add(pt);
 360                         Grid[i,j].setNoKilled();
 361                     }
 362             gm.DeadGroup = a;
 363             gm.DeadGroupColor = c;
 364         }
 365 
 366         public void resetBoard()
 367         {
 368             int i,j;
 369             for (i=0; i<nSize; i++)
 370                 for (j=0; j<nSize; j++) 
 371                     Grid[i,j].removeStone();
 372             m_gmLastMove = null;
 373             Invalidate(null);
 374         }
 375 
 376         /*
 377          * 撤销操作
 378          */
 379         public void playPrev(GoMove gm)
 380         {
 381             int i = gm.Point.X;
 382             int j = gm.Point.Y;
 383             Grid[i,j].removeStone();
 384             m_gmLastMove = gameTree.peekPrev();
 385             if (m_gmLastMove != null)
 386                 Grid[m_gmLastMove.Point.X,m_gmLastMove.Point.Y].setUpdated();
 387             if (gm.DeadGroup != null)
 388             {
 389                 System.Collections.IEnumerator myEnumerator = gm.DeadGroup.GetEnumerator();
 390                 while (myEnumerator.MoveNext())
 391                 {
 392                     Point p;    
 393                     p = (Point)myEnumerator.Current;
 394                     Grid[p.X,p.Y].setNoKilled();
 395                     Grid[p.X,p.Y].setStone(nextTurn(gm.Color));
 396                 }
 397             }
 398             optRepaint();
 399             //Console.WriteLine("i={0},j={1} c={2}",m_gmLastMove.Point.X,m_gmLastMove.Point.Y,m_gmLastMove.Color);
 400             return; 
 401         }
 402 
 403                 
 404         
 405         Rectangle getUpdatedArea(int i, int j) 
 406         {
 407             int x = rGrid.X + i * nUnitGridWidth - nUnitGridWidth/2;
 408             int y = rGrid.Y + j * nUnitGridWidth - nUnitGridWidth/2;
 409             return new Rectangle(x,y, nUnitGridWidth, nUnitGridWidth);
 410         }
 411 
 412         /**
 413          * 全更新画
 414          */
 415         private void optRepaint()
 416         {
 417             Rectangle r = new Rectangle(0,0,0,0);
 418             Region    re;
 419 
 420             for (int i=0; i<nSize; i++)
 421                 for (int j=0; j<nSize; j++)
 422                     if (Grid[i,j].isUpdated()) 
 423                     {
 424                         r = getUpdatedArea(i,j);
 425                         re = new Region(r);
 426                         Invalidate(re);
 427                     }
 428         }
 429 
 430         /*
 431          * 重画一个格子
 432          */
 433         void repaintOneSpotNow(Point p)
 434         {
 435             Grid[p.X, p.Y].setUpdated();
 436             bDrawMark = false;
 437             Rectangle r = getUpdatedArea(p.X, p.Y);
 438             Invalidate( new Region(r));
 439             Grid[p.X, p.Y].resetUpdated();
 440             bDrawMark = true;
 441         }
 442 
 443         //这个函数没有被用到  
 444         void recordMove(Point p, StoneColor colorToPlay) 
 445         {
 446             Grid[p.X,p.Y].setStone(colorToPlay);
 447             // 呵呵.
 448             m_gmLastMove = new GoMove(p.X, p.Y, colorToPlay, nSeq++);
 449         }
 450 
 451         StoneColor nextTurn(StoneColor c) 
 452         {
 453             if (c == StoneColor.black)
 454                 return StoneColor.white;
 455             else 
 456                 return StoneColor.black;
 457         }
 458 
 459         /**
 460          *    bury the dead stones in a group (same color). 
 461          *    if a stone in one group is dead, the whole group is dead.
 462         */
 463         void buryTheDead(int i, int j, StoneColor c) 
 464         {
 465             if (onBoard(i,j) && Grid[i,j].hasStone() && 
 466                 Grid[i,j].color() == c) 
 467             {
 468                 Grid[i,j].die();
 469                 buryTheDead(i-1, j, c);
 470                 buryTheDead(i+1, j, c);
 471                 buryTheDead(i, j-1, c);
 472                 buryTheDead(i, j+1, c);
 473             }
 474         }
 475 
 476         void cleanScanStatus()
 477         {
 478             int i,j;
 479             for (i=0; i<nSize; i++)
 480                 for (j=0; j<nSize; j++) 
 481                     Grid[i,j].clearScanned();
 482         }
 483 
 484         /**
 485          * 死掉的收集起来,以后有用
 486          */
 487         void doDeadGroup(StoneColor c) 
 488         {
 489             int i,j;
 490             for (i=0; i<nSize; i++)
 491                 for (j=0; j<nSize; j++) 
 492                     if (Grid[i,j].hasStone() &&
 493                         Grid[i,j].color() == c) 
 494                     {
 495                         if (calcLiberty(i,j,c) == 0)
 496                         {
 497                             buryTheDead(i,j,c);
 498                             m_fAnyKill = true;
 499                         }
 500                         cleanScanStatus();
 501                     }
 502         }
 503 
 504 
 505         /**
 506          * 递归计算气
 507          */
 508         int calcLiberty(int x, int y, StoneColor c) 
 509         {
 510             int lib = 0; // 初始气0    
 511             
 512             if (!onBoard(x,y))
 513                 return 0;
 514             if (Grid[x,y].isScanned())
 515                 return 0;
 516 
 517             if (Grid[x,y].hasStone()) 
 518             {
 519                 if (Grid[x,y].color() == c) 
 520                 {
 521                     //递归计算剩余气.
 522                     Grid[x,y].setScanned();
 523                     lib += calcLiberty(x-1, y, c);
 524                     lib += calcLiberty(x+1, y, c);
 525                     lib += calcLiberty(x, y-1, c);
 526                     lib += calcLiberty(x, y+1, c);
 527                 } 
 528                 else 
 529                     return 0;
 530             } 
 531             else 
 532             {// 如果无石,则找到一个气. 
 533                 lib ++;
 534                 Grid[x,y].setScanned();
 535             }
 536 
 537             return lib;
 538         }
 539 
 540 
 541         /**
 542          * 给上一次下的棋子反色标记
 543          */
 544         void markLastMove(Graphics g) 
 545         {
 546             Brush brMark;
 547             if (m_gmLastMove.Color == StoneColor.white)
 548                 brMark = brBlack;
 549             else 
 550                 brMark = brWhite;
 551             Point p = m_gmLastMove.Point;
 552             //Console.Out.WriteLine ("{0} {1} {2} {3}",p.X,p.Y,m_gmLastMove.Color,brMark);
 553             g.FillRectangle( brMark,
 554                 rGrid.X + (p.X) * nUnitGridWidth - (nUnitGridWidth-1)/8, 
 555                 rGrid.Y + (p.Y) * nUnitGridWidth - (nUnitGridWidth-1)/8,
 556                 3, 3);
 557         }
 558 
 559         private void clearLabelsAndMarksOnBoard()
 560         {
 561             for (int i=0; i<nSize; i++)
 562                 for (int j=0; j<nSize; j++)
 563                 {
 564                     if (Grid[i,j].hasLabel())
 565                         Grid[i,j].resetLabel();
 566                     if (Grid[i,j].hasMark())
 567                         Grid[i,j].resetMark();
 568                 }
 569 
 570         }
 571 
 572         private void setLabelsOnBoard(GoMove gm)
 573         {
 574             short    nLabel = 0;
 575             Point p;
 576             if (null != gm.Labels)
 577             {
 578                 int i = gm.Labels.Count;
 579                 i = gm.Labels.Capacity;
 580 
 581                 System.Collections.IEnumerator myEnumerator = gm.Labels.GetEnumerator();
 582                 while (myEnumerator.MoveNext())
 583                 {
 584                     p = (Point)myEnumerator.Current;
 585                     Grid[p.X,p.Y].setLabel(++nLabel);
 586                 }
 587             }
 588         }
 589 
 590         private void setMarksOnBoard(GoMove gm)
 591         {
 592             Point p;
 593             if (null != gm.Labels)
 594             {
 595                 System.Collections.IEnumerator myEnumerator = gm.Marks.GetEnumerator();
 596                 while ( myEnumerator.MoveNext() )
 597                 {
 598                     p = (Point)myEnumerator.Current;
 599                     Grid[p.X,p.Y].setMark();
 600                 }
 601             }
 602         }
 603 
 604         private Point SwapXY(Point p)
 605         {
 606             Point pNew = new Point(p.Y,p.X);
 607             return pNew;
 608         }
 609 
 610         private void DrawBoard(Graphics g)
 611         {
 612             //画棋盘的标格
 613             string[] strV= {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19"};
 614             string[] strH= {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T"};
 615 
 616             Point p1 = new Point(nEdgeLen,nEdgeLen);
 617             Point p2 = new Point(nTotalGridWidth+nEdgeLen,nEdgeLen);
 618             g.FillRectangle(brBoard,nBoardOffset,nBoardOffset,nTotalGridWidth+nBoardOffset,nTotalGridWidth+nBoardOffset);
 619             for (int i=0;i<nSize; i++)
 620             {
 621                 g.DrawString(strV[i],this.Font, brBlack, 0, nCoodStart+ nBoardOffset + nUnitGridWidth*i);
 622                 g.DrawString(strH[i],this.Font, brBlack, nBoardOffset + nCoodStart + nUnitGridWidth*i, 0);
 623                 g.DrawLine(penGrid, p1, p2);
 624                 g.DrawLine(penGrid, SwapXY(p1), SwapXY(p2));
 625 
 626                 p1.Y += nUnitGridWidth;
 627                 p2.Y += nUnitGridWidth;
 628             }
 629             //立体效果
 630             Pen penHi = new Pen(Color.WhiteSmoke, (float)0.5);
 631             Pen penLow = new Pen(Color.Gray, (float)0.5);
 632 
 633             g.DrawLine(penHi, nBoardOffset, nBoardOffset, nTotalGridWidth+2*nBoardOffset, nBoardOffset);
 634             g.DrawLine(penHi, nBoardOffset, nBoardOffset, nBoardOffset, nTotalGridWidth+2*nBoardOffset);
 635             g.DrawLine(penLow, nTotalGridWidth+2*nBoardOffset,nTotalGridWidth+2*nBoardOffset, nBoardOffset+1, nTotalGridWidth+2*nBoardOffset);
 636             g.DrawLine(penLow, nTotalGridWidth+2*nBoardOffset,nTotalGridWidth+2*nBoardOffset, nTotalGridWidth+2*nBoardOffset, nBoardOffset+1);
 637         }
 638 
 639         void UpdateGoBoard(PaintEventArgs e)
 640         {
 641             DrawBoard(e.Graphics);
 642             
 643             //画9个星. 
 644             drawStars(e.Graphics);
 645 
 646             //画棋子
 647             drawEverySpot(e.Graphics);
 648         }
 649 
 650         //画棋盘上的9个星星啊
 651         void drawStar(Graphics g, int row, int col) 
 652         {
 653             g.FillRectangle(brStar,
 654                 rGrid.X + (row-1) * nUnitGridWidth - 1, 
 655                 rGrid.Y + (col-1) * nUnitGridWidth - 1, 
 656                 3, 
 657                 3);
 658         }
 659 
 660         //同上啊. 
 661         void  drawStars(Graphics g)
 662         {
 663             drawStar(g, 4, 4);
 664             drawStar(g, 4, 10);
 665             drawStar(g, 4, 16);
 666             drawStar(g, 10, 4);
 667             drawStar(g, 10, 10);
 668             drawStar(g, 10, 16);
 669             drawStar(g, 16, 4);
 670             drawStar(g, 16, 10);
 671             drawStar(g, 16, 16);
 672         }
 673 
 674         /**
 675          * 画棋子
 676          */
 677         void drawStone(Graphics g, int row, int col, StoneColor c) 
 678         {
 679             Brush br;
 680             if (c == StoneColor.white)
 681                 br = brWhite;
 682             else 
 683                 br = brBlack;
 684             
 685             Rectangle r = new Rectangle(rGrid.X+ (row) * nUnitGridWidth - (nUnitGridWidth-1)/2, 
 686                 rGrid.Y + (col) * nUnitGridWidth - (nUnitGridWidth-1)/2,
 687                 nUnitGridWidth-1,
 688                 nUnitGridWidth-1);
 689 
 690             g.FillEllipse(br, r);
 691         }
 692 
 693         void drawLabel(Graphics g, int x, int y, short nLabel) 
 694         {
 695             if (nLabel ==0)
 696                 return;
 697             nLabel --;
 698             nLabel %= 18;            //除18取余数.
 699 
 700             //画标签
 701             Rectangle r = new Rectangle(rGrid.X+ x * nUnitGridWidth - (nUnitGridWidth-1)/2, 
 702                 rGrid.Y + y * nUnitGridWidth - (nUnitGridWidth-1)/2,
 703                 nUnitGridWidth-1,
 704                 nUnitGridWidth-1);
 705 
 706             g.FillEllipse(brBoard, r);
 707 
 708             g.DrawString(strLabels[nLabel],    //标记出来,用某个字母.
 709                 this.Font, 
 710                 brBlack, 
 711                 rGrid.X+ (x) * nUnitGridWidth - (nUnitGridWidth-1)/4, 
 712                 rGrid.Y + (y) * nUnitGridWidth - (nUnitGridWidth-1)/2);
 713         }
 714 
 715         void drawMark(Graphics g, int x, int y)
 716         {
 717             g.FillRectangle( m_brMark,
 718                 rGrid.X + x* nUnitGridWidth - (nUnitGridWidth-1)/8, 
 719                 rGrid.Y + y * nUnitGridWidth - (nUnitGridWidth-1)/8,
 720                 5, 5);
 721         }
 722 
 723         void drawEverySpot(Graphics g) 
 724         {
 725             for (int i=0; i<nSize; i++)
 726                 for (int j=0; j<nSize; j++)
 727                 {
 728                     if (Grid[i,j].hasStone())
 729                         drawStone(g, i, j, Grid[i,j].color());
 730                     if (Grid[i,j].hasLabel())
 731                         drawLabel(g, i, j, Grid[i,j].getLabel());
 732                     if (Grid[i,j].hasMark())
 733                         drawMark(g, i, j);
 734                 }
 735             //如果可以画最近下子的标签,则画出来. 
 736             if (bDrawMark && m_gmLastMove != null)
 737                 {
 738                 markLastMove(g);
 739                 }
 740         }
 741 
 742         //打开棋谱
 743         private void OpenFile()
 744         {
 745             OpenFileDialog openDlg = new OpenFileDialog();
 746             openDlg.Filter  = "sgf files (*.sgf)|*.sgf|All Files (*.*)|*.*";
 747             openDlg.FileName = "" ;
 748             openDlg.DefaultExt = ".sgf";
 749             openDlg.CheckFileExists = true;
 750             openDlg.CheckPathExists = true;
 751             
 752             DialogResult res = openDlg.ShowDialog ();
 753             
 754             if(res == DialogResult.OK)
 755             {
 756                 if( !(openDlg.FileName).EndsWith(".sgf") && !(openDlg.FileName).EndsWith(".SGF")) 
 757                     MessageBox.Show("Unexpected file format","Super Go Format",MessageBoxButtons.OK);
 758                 else
 759                 {
 760                     FileStream f = new FileStream(openDlg.FileName, FileMode.Open); 
 761                     StreamReader r = new StreamReader(f);
 762                     string s = r.ReadToEnd();
 763                     gameTree = new GoTree(s);
 764                     gameTree.reset();
 765                     resetBoard();
 766                     r.Close(); 
 767                     f.Close();
 768                 }
 769             }        
 770         }    
 771     }
 772 
 773     public class GoTest
 774     {
 775         ///测试游戏?
 776         [STAThread]
 777         public static void Main(string[] args) 
 778         {
 779             Application.Run(new GoBoard(19));
 780         }
 781     }
 782 
 783     
 784     //每个棋盘点
 785     public class Spot 
 786     {
 787         private Boolean bEmpty;
 788         private Boolean bKilled;
 789         private Stone s;
 790         private short    m_nLabel;
 791         private Boolean m_bMark;
 792         private Boolean bScanned;
 793         private Boolean bUpdated; //标记是否应该重画
 794         /**
 795          * ZZZZZZZZZZZ.
 796          */
 797         public Spot() 
 798         {
 799             bEmpty = true;
 800             bScanned = false;
 801             bUpdated = false;
 802             bKilled = false;
 803         }
 804         
 805         public Boolean hasStone() { return !bEmpty;    }
 806         public Boolean isEmpty() {    return bEmpty;    }
 807         public Stone thisStone() {    return s;}
 808         public StoneColor color() {    return s.color;}
 809 
 810         public Boolean hasLabel() {return m_nLabel>0;}
 811         public Boolean hasMark() {return m_bMark;}
 812         public void setLabel(short l) {m_nLabel = l; bUpdated = true; }
 813         public void setMark() {m_bMark = true; bUpdated = true;}
 814         public void resetLabel() {m_nLabel = 0; bUpdated = true;}
 815         public void resetMark() {m_bMark = false; bUpdated = true;}
 816         public short    getLabel() {return m_nLabel;}
 817 
 818         public Boolean isScanned() { return bScanned;}
 819         public void setScanned() {    bScanned = true;}
 820         public void clearScanned() { bScanned = false; }
 821 
 822         public void setStone(StoneColor c) 
 823         {
 824             if (bEmpty) 
 825             {
 826                 bEmpty = false;
 827                 s.color = c;
 828                 bUpdated = true;
 829             } // 设置当前棋盘点颜色为c,标记其非空且已更新. 
 830         }
 831 
 832         /*
 833          * 移除棋子
 834         */
 835         public void removeStone()
 836         {    //移除棋子
 837             bEmpty = true;
 838             bUpdated = true;
 839         }
 840                 
 841         //设定棋子已死.
 842         public void die() 
 843         {
 844             bKilled = true;
 845             bEmpty = true;
 846             bUpdated = true;
 847         } 
 848 
 849         public Boolean isKilled() { return bKilled;}
 850         public void setNoKilled() { bKilled = false;}
 851 
 852         public void resetUpdated() { bUpdated = false; bKilled = false;}
 853 
 854         //判断棋子是否需要更新
 855         public Boolean isUpdated() 
 856         { 
 857             if (bUpdated)
 858             {    //如果需要更新
 859                 bUpdated = false;
 860                 return true;
 861             } 
 862             else 
 863                 return false;
 864         }
 865 
 866         // 设置需要更新
 867         public void setUpdated() { bUpdated = true; }
 868     }
 869 
 870     /**
 871      * 每一步的类
 872      */
 873     public class GoMove 
 874     {
 875         StoneColor m_c;    //颜色
 876         Point m_pos;        //位置
 877         int m_n;            //标记第几步.
 878         String m_comment;    //注释.
 879         MoveResult m_mr;    //标记这步下完之后上下左右是否有被杀的棋子. 
 880 
 881         ArrayList        m_alLabel; //该步的标签. 
 882         ArrayList        m_alMark; //该步的标记
 883 
 884         //这两个压根没用过,别闹!. 
 885         ArrayList        m_alDead;
 886         StoneColor    m_cDead;
 887         /**
 888          * 构造类.
 889          */
 890         public GoMove(int x, int y, StoneColor sc, int seq) 
 891         {
 892             m_pos = new Point(x,y);
 893             m_c = sc;
 894             m_n = seq;
 895             m_mr = new MoveResult();
 896             m_alLabel = new ArrayList();
 897             m_alMark = new ArrayList();
 898         }
 899 
 900         public GoMove(String str, StoneColor c) 
 901         {
 902             char cx = str[0];
 903             char cy = str[1];
 904             m_pos = new Point(0,0);
 905             //字符串构造类
 906             m_pos.X = (int) ( (int)cx - (int)(char)'a');
 907             m_pos.Y = (int) ( (int)cy - (int)(char)'a');
 908             this.m_c = c;
 909             m_alLabel = new ArrayList();
 910             m_alMark = new ArrayList();
 911         }
 912 
 913 
 914         private Point    StrToPoint(String str)
 915         {
 916             Point p = new Point(0,0);
 917             char cx = str[0];
 918             char cy = str[1];
 919             //转换函数,字符串to Point 
 920             p.X = (int) ( (int)cx - (int)(char)'a');
 921             p.Y = (int) ( (int)cy - (int)(char)'a');
 922             return p;
 923         }
 924 
 925 
 926         public StoneColor Color
 927         { 
 928             get { return m_c; } 
 929         }
 930 
 931         public String Comment 
 932         {
 933             get
 934             {
 935                 if (m_comment == null)
 936                     return string.Empty;
 937                 else
 938                     return m_comment;
 939             }
 940             set
 941             {
 942                 m_comment = value; 
 943             }
 944         }
 945 
 946         public int Seq
 947         {
 948             get { return m_n; }
 949             set {    m_n = value;}
 950         }
 951 
 952         public Point Point
 953         {
 954            get  { return m_pos; }
 955         }
 956 
 957         public MoveResult Result
 958         {
 959             get { return m_mr; }
 960             set { m_mr = value; }
 961         }
 962         
 963         public ArrayList DeadGroup
 964         {
 965             get { return m_alDead;}
 966             set {m_alDead = value;}
 967         }
 968 
 969         public StoneColor DeadGroupColor
 970         {
 971             get { return m_cDead; }
 972             set { m_cDead = value; }
 973         }
 974         
 975         public void addLabel(String str) {m_alLabel.Add(StrToPoint(str));}
 976         
 977         public void addMark(String str) {    m_alMark.Add(StrToPoint(str));}
 978 
 979         public ArrayList Labels
 980         {
 981             get { return m_alLabel; }
 982         }
 983 
 984         public ArrayList Marks
 985         {
 986             get { return m_alMark; }
 987         }
 988     }
 989     
 990 
 991     /**
 992      * 这个类基本没用过,别闹了!
 993      * 
 994      */
 995     public class MoveResult 
 996     {
 997         public StoneColor color; 
 998         // 4个方向. 
 999         public Boolean bUpKilled;
1000         public Boolean bDownKilled;
1001         public Boolean bLeftKilled;
1002         public Boolean bRightKilled;
1003         public Boolean bSuicide;    //你在程序中就出现一次,从此就没人问津
1004         public MoveResult() 
1005         {
1006             bUpKilled = false;
1007             bDownKilled = false;
1008             bLeftKilled = false;
1009             bRightKilled = false;
1010             bSuicide = false;
1011         }
1012     }
1013 
1014     /**
1015      * 棋子类. 
1016      */
1017     public struct Stone 
1018     {
1019         public StoneColor color; 
1020     }
1021 
1022     /**
1023      * 历史记录类 
1024      */
1025     public class GoVariation 
1026     {
1027         int m_id;            //初始化id. 
1028         string m_name;    //你没被用过.
1029     
1030         ArrayList m_moves; 
1031         int m_seq;            //当前棋面进行到哪. 
1032         int m_total;        //最长历史记录
1033 
1034 
1035         public GoVariation(int id)
1036         {
1037             m_id = id;
1038             m_moves = new ArrayList(10);
1039             m_seq = 0;
1040             m_total = 0;
1041         }
1042 
1043         public void addAMove(GoMove gm) 
1044         {
1045             gm.Seq = m_total ++;
1046             m_seq++;
1047             m_moves.Add(gm);
1048         }
1049 
1050         public void updateResult(GoMove gm) 
1051         {
1052         }
1053 
1054         public GoMove doNext()
1055         {
1056             if (m_seq < m_total) 
1057             {
1058                 return (GoMove)m_moves[m_seq++];
1059             } 
1060             else 
1061                 return null;
1062         }
1063 
1064         public GoMove doPrev()
1065         {
1066             if (m_seq > 0)
1067                 return (GoMove)(m_moves[--m_seq]);
1068             else 
1069                 return null;
1070         }
1071 
1072         /*
1073          *  返回最近下过的那一步
1074          */
1075         public GoMove peekPrev()
1076         {
1077             if (m_seq > 0)
1078                 return (GoMove)(m_moves[m_seq-1]);
1079             else 
1080                 return null;
1081         }
1082 
1083         public void reset() {m_seq = 0;}
1084     }
1085 
1086 
1087     /**
1088     * 你压根就没被用过
1089     */
1090     struct VarStartPoint
1091     {
1092         int m_id; 
1093         int m_seq;
1094     }
1095 
1096     struct GameInfo 
1097     {
1098         public string gameName;
1099         public string playerBlack;
1100         public string playerWhite;
1101         public string rankBlack;
1102         public string rankWhite;
1103         public string result;
1104         public string date;
1105         public string km;
1106         public string size;
1107         public string comment;
1108         public string handicap;
1109         public string gameEvent;
1110         public string location;
1111         public string time;             // 游戏时间. 
1112         public string unknown_ff;           . 
1113         public string unknown_gm;
1114         public string unknown_vw; 
1115     }
1116 
1117     public class KeyValuePair 
1118     {
1119         public string k; public ArrayList alV;
1120 
1121         private string    removeBackSlash(string strIn)
1122         {
1123             string strOut; 
1124             int        iSlash;
1125 
1126             strOut = string.Copy(strIn);
1127             if (strOut.Length < 2)
1128                 return strOut;
1129             for (iSlash = strOut.Length-2; iSlash>=0; iSlash--)
1130             {
1131                 if (strOut[iSlash] == '\\')        // && strOut[iSlash+1] == ']')
1132                 {
1133                     strOut = strOut.Remove(iSlash,1);
1134                     if (iSlash>0)
1135                         iSlash --;    //处理转义字符
1136                 }
1137             }
1138             return strOut;
1139         }
1140 
1141         public KeyValuePair(string k, string v)
1142         {
1143             this.k = string.Copy(k);
1144             string strOneVal;
1145             int        iBegin, iEnd;
1146         
1147             //新建一个arraylist,存所有的value
1148             alV = new ArrayList(1);
1149 
1150             //如果遇到评论C的话
1151             if (k.Equals("C"))
1152             {
1153                 strOneVal = removeBackSlash(string.Copy(v));
1154                 //处理'\'
1155                 alV.Add(strOneVal);
1156                 return;
1157             }
1158 
1159             iBegin = v.IndexOf("[");
1160             if (iBegin == -1)    //如果没有[
1161             {
1162                 alV.Add(v);
1163                 return; 
1164             }
1165             
1166             iBegin = 0;
1167             while (iBegin < v.Length && iBegin>=0)
1168             {
1169                 iEnd = v.IndexOf("]", iBegin);
1170                 if (iEnd > 0)
1171                     strOneVal = v.Substring(iBegin, iEnd-iBegin);
1172                 else 
1173                     strOneVal = v.Substring(iBegin);    //如果没有]结尾,则全部赋值进值数组
1174                 alV.Add(strOneVal);
1175                 iBegin = v.IndexOf("[", iBegin+1);
1176                 if (iBegin > 0)
1177                     iBegin ++;    //如果还有左括号,继续
1178             }
1179         }
1180     }
1181 
1182     /**
1183      * 历史信息数
1184      */
1185 
1186     public class GoTree 
1187     {
1188         GameInfo _gi;        //游戏信息
1189         ArrayList _vars;        //没用过
1190         int _currVarId;        //没用过
1191         int _currVarNum;
1192         GoVariation _currVar;        //历史信息
1193         string    _stGameComment;
1194 
1195         // 构造类啊
1196         public GoTree(string s)
1197         {
1198             _vars = new ArrayList(10);
1199             _currVarNum = 0;
1200             _currVarId = 0; 
1201             _currVar = new GoVariation(_currVarId);
1202             _vars.Add(_currVar);
1203             parseFile(s);
1204         }
1205 
1206         //    默认构造类
1207         public GoTree()
1208         {
1209             _vars = new ArrayList(10);
1210             _currVarNum = 0;
1211             _currVarId = 0; 
1212             _currVar = new GoVariation(_currVarId);
1213             _vars.Add(_currVar);
1214         }
1215 
1216         public    string Info
1217         {
1218             get
1219             {
1220                 return _gi.comment == null? string.Empty : _gi.comment;
1221             }
1222         }
1223 
1224         public void addMove(GoMove gm) 
1225         {
1226             _currVar.addAMove(gm);
1227         }
1228 
1229         /**
1230          * 分析文件
1231          */
1232         Boolean parseFile(String goStr) 
1233         {
1234             int iBeg, iEnd=0; 
1235             while (iEnd < goStr.Length) 
1236             {
1237                 if (iEnd > 0)
1238                     iBeg = iEnd;
1239                 else 
1240                     iBeg = goStr.IndexOf(";", iEnd);
1241                 iEnd = goStr.IndexOf(";", iBeg+1);
1242                 if (iEnd < 0) //找不到 ";"
1243                     iEnd = goStr.LastIndexOf(")", goStr.Length);        //找 ")"
1244                 if (iBeg >= 0 && iEnd > iBeg) 
1245                 {
1246                     string section = goStr.Substring(iBeg+1, iEnd-iBeg-1);
1247                     parseASection(section);
1248                 } 
1249                 else 
1250                     break;
1251             }
1252             return true;
1253         }
1254         // 往下都是在解析SmartGameFormat(sgf)格式的期谱,和功能关系不大 不注释了
1255         /// <ZZZZZZZ>
1256         /// ZZZZ ZZZ ZZZZZ ZZ ZZZ ZZ ZZZZZ ZZZZZZ,
1257         /// ZZZZZZZ ZZ'Z ZZZ "]" ZZZZ,  
1258         /// ZZ ZZZ ZZ ZZZZ "\]",  ZZ ZZZZ ZZZZZZZZ, ZZZ ZZZZZZ ZZZ ZZZ ZZZZ "]", ZZ ZZZ ZZ ZZZZZZ. 
1259         /// </ZZZZZZZ>
1260         /// <ZZZZZ ZZZZ="ZZZ"></ZZZZZ>
1261         /// <ZZZZZZZ></ZZZZZZZ>
1262         int findEndofValueStr(String sec)
1263         {
1264             int i = 0;
1265             //ZZ ZZZZZZ ZZ'ZZ ZZZZZZZZ ZZZZ ZZZZZZZ ZZZ ZZZZZ ZZZZZZ.
1266             while (i >= 0)
1267             {
1268                 i = sec.IndexOf(']', i+1);
1269                 if (i > 0 && sec[i - 1] != '\\')
1270                     return i;    //ZZZZZZ ZZZ ZZZZZ ZZ "]". 
1271             }
1272 
1273             //ZZ ZZ ZZZZ ZZ ZZZ ']', ZZZ'Z ZZZZ ZZZ ZZZ ZZZ ZZ ZZZZZZ. 
1274             return sec.Length - 1;        //ZZZZ ZZ ZZZ ZZZZZ ZZ ZZZ ZZZZ ZZZZ ZZ ZZZ ZZZZZZ
1275         }
1276         
1277         int findEndofValueStrOld(String sec)
1278         {
1279             int i = 0;
1280             //ZZ ZZZZZZ ZZ'ZZ ZZZZZZZZ ZZZZ ZZZZZZZ ZZZ ZZZZZ ZZZZZZ. 
1281             bool fOutside = false;
1282             
1283             for (i=0; i<sec.Length;i++)
1284             {
1285                 if (sec[i] == ']')
1286                 {
1287                     if (i>1 && sec[i-1] != '\\') //ZZ ZZ
1288                         fOutside = true;
1289                 }
1290                 else if (char.IsLetter(sec[i]) && fOutside && i>0)
1291                     return i-1;
1292                 else if (fOutside && sec[i] == '[')
1293                     fOutside = false;
1294             }
1295             return sec.Length-1;        //ZZZZ ZZ ZZZ ZZZZZ ZZ ZZZ ZZZZ ZZZZ ZZ ZZZ ZZZZZZ
1296         }
1297 
1298         private string purgeCRLFSuffix(string inStr)
1299         {
1300             int iLast = inStr.Length - 1; //ZZZZZ ZZ ZZZ ZZ ZZZZZZ. 
1301 
1302             if (iLast <= 0)
1303                 return inStr; 
1304 
1305             while ((inStr[iLast] == '\r' || inStr[iLast] == '\n' || inStr[iLast] == ' '))
1306             {
1307                 iLast--; 
1308             }
1309             if ((iLast+1) != inStr.Length)
1310                 return inStr.Substring(0, iLast+1);  //ZZZ 2ZZ ZZZZZZZZZ ZZ ZZZ ZZZZZZ
1311             else
1312                 return inStr; 
1313         }
1314  
1315 
1316         /**
1317          * ZZZZZ Z ZZZZZZZ ZZ ZZZ ZZZZZZ ZZZZZZ. 
1318          * Z ZZZZZZZ ZZZ ZZZ ZZZZZZ "ZZ {ZZ}"
1319          * Z ZZ (ZZZ ZZZZZ ZZZZ) ZZZ ZZZ ZZZZZZ "ZZZ ZZZZZ {ZZZZZ}"
1320          * ZZZZ: Z ZZZ ZZZ ZZZZZZZZZ ZZZZ ZZZZZZZZ ZZZZZZ, Z.Z. ZZZZZZ, ZZZZZ:  Z[ZZ][ZZ]. 
1321          * Z ZZZ ZZ ZZZZZZ 
1322          * Z ZZZZZ ZZ Z ZZZZZZ ZZZZZZZZ ZZ [ ZZZ ].
1323          * ZZZZ: ZZZZZZZZ ( Z[ZZZZZZZZ]) ZZZ ZZZZ ZZZ ']' ZZZZZZZZZ ZZZZZZ ZZZ ZZZZZZZZ, ZZZZZ ZZ ZZZZZZZ ZZ "\]"
1324          * Z.Z.  Z[ZZZZZ ZZZZZ ZZ [4,Z\] ZZ ZZZZZ ZZZZZZ]
1325          * 
1326          */
1327         Boolean parseASection(String sec) 
1328         {
1329             int iKey = 0;
1330             int iValue = 0;
1331             int iLastValue = 0;
1332             KeyValuePair kv;
1333             ArrayList Section = new ArrayList(10);
1334             
1335             try 
1336             {
1337                 iKey = sec.IndexOf("[");
1338                 if (iKey < 0)
1339                 {
1340                     return false;
1341                 }
1342                 sec = purgeCRLFSuffix(sec);
1343  
1344                 iValue = findEndofValueStr(sec); //ZZZ.ZZZZZZZ("]", ZZZZ);
1345                 iLastValue = sec.LastIndexOf("]");
1346                 if (iValue <= 0 || iLastValue <= 1)
1347                 {
1348                     return false;
1349                 }
1350                 sec = sec.Substring(0,iLastValue+1);
1351                 while (iKey > 0 && iValue > iKey)//ZZ ZZZZ ZZZZZ ZZ ZZZZZZZ
1352                 {
1353                     string key = sec.Substring(0,iKey);
1354                     int iNonLetter = 0;
1355                     while (!char.IsLetter(key[iNonLetter]) && iNonLetter < key.Length)
1356                         iNonLetter ++;
1357                     key = key.Substring(iNonLetter);
1358                     //ZZZZ ZZ ZZZZ ZZZ ZZZZ ZZZZZZ ZZZZZZZ ZZ Z [] ZZZZ
1359                     //ZZZZZZ = ZZZZZZZZZZZZZZZZZ(ZZZ);
1360                     string strValue = sec.Substring(iKey+1, iValue-iKey-1);
1361                     //ZZZ ZZ ZZZZ Z ZZZ/ZZZZZ ZZZZ
1362                     kv = new KeyValuePair(key, strValue);
1363                     Section.Add(kv);
1364                     if (iValue >= sec.Length)
1365                         break;
1366                     sec = sec.Substring(iValue+1);
1367                     iKey = sec.IndexOf("[");
1368                     if (iKey > 0)
1369                     {
1370                         iValue = findEndofValueStr(sec); //ZZZ.ZZZZZZZ("]",ZZZZ);
1371                     }
1372                 }
1373             }
1374             catch
1375             {
1376                 return false;
1377             }
1378 
1379             processASection(Section);
1380             return true;
1381         }
1382 
1383 
1384         /** 
1385          * ZZZZZZZ Z ZZZ ZZZ ZZZ ZZZZZZZZZZZZZ ZZZZZ
1386          * ZZ ZZZZZ ZZ Z ZZZZ, ZZ ZZZZZZ ZZZZZZZZZZZ.
1387          * ZZZZZZZZZZ, ZZZ ZZZZZZZ ZZZ ZZZZ ZZZZ ZZZ ZZZZ ZZ ZZZZ. 
1388          * 
1389          * ZZZZ: ZZ/ZZ ZZZ ZZZZZZZZZ ZZZ ZZZZ ZZZZZZZZ ZZZZZ ZZZZZZ, ZZZ Z ZZZZZ'Z ZZZZ ZZZ ZZZZZZZ ZZZ 
1390          */
1391         Boolean processASection(ArrayList arrKV) 
1392         {
1393             Boolean fMultipleMoves = false;   //ZZZZZZZ ZZZZ ZZZZZZZ ZZZ ZZZZZZZZ ZZZZZ. 
1394             GoMove gm = null; 
1395             
1396             string key, strValue;
1397 
1398             for (int i = 0;i<arrKV.Count;i++)
1399             {
1400                 key = ((KeyValuePair)(arrKV[i])).k;
1401                 for (int j=0; j<((KeyValuePair)(arrKV[i])).alV.Count; j++)
1402                 {
1403                     strValue = (string)(((KeyValuePair)(arrKV[i])).alV[j]);
1404 
1405                     if (key.Equals("B"))   //ZZZZZ ZZZZZ
1406                     {
1407                         Debug.Assert(gm == null);
1408                         gm = new GoMove(strValue, StoneColor.black);
1409                     }
1410                     else if (key.Equals("W"))  //ZZZZZ ZZZZZ
1411                     {
1412                         Debug.Assert(gm == null);
1413                         gm = new GoMove(strValue, StoneColor.white);
1414                     }
1415                     else if (key.Equals("C"))  //ZZZZZZZ
1416                     {
1417                         //ZZZZZ.ZZZZZZ(Z>0);
1418                         if (gm != null)
1419                             gm.Comment = strValue;
1420                         else    //ZZZ ZZ ZZ ZZZ ZZZZ ZZZZZZZ 
1421                             _gi.comment += strValue;
1422                     }
1423                     else if (key.Equals("L"))  //ZZZZZ
1424                     {
1425                         if (gm != null)
1426                             gm.addLabel(strValue);
1427                         else    //ZZZ ZZ ZZ ZZZ ZZZZ ZZZZZZZ 
1428                             _stGameComment += strValue;
1429                     }
1430 
1431                     else if (key.Equals("M"))  //ZZZZ
1432                     {
1433                         if (gm != null)
1434                             gm.addMark(strValue);
1435                         else    //ZZZ ZZ ZZ ZZZ ZZZZ ZZZZZZZ 
1436                             _gi.comment += strValue;
1437                     }
1438                     else if (key.Equals("AW"))        //ZZZ ZZZZZ ZZZZZ
1439                     {
1440                         fMultipleMoves = true;
1441                         gm = new GoMove(strValue, StoneColor.white);
1442                     }
1443                     else if (key.Equals("AB"))        //ZZZ ZZZZZ ZZZZZ
1444                     {
1445                         fMultipleMoves = true;
1446                         gm = new GoMove(strValue, StoneColor.black);
1447                     }
1448                     else if (key.Equals("HA"))
1449                         _gi.handicap = (strValue);
1450                     else if (key.Equals("BR"))
1451                         _gi.rankBlack = (strValue);
1452                     else if (key.Equals("PB"))
1453                         _gi.playerBlack = (strValue);
1454                     else if (key.Equals("PW"))
1455                         _gi.playerWhite = (strValue);
1456                     else if (key.Equals("WR"))
1457                         _gi.rankWhite = (strValue);
1458                     else if (key.Equals("DT"))
1459                         _gi.date = (strValue);
1460                     else if (key.Equals("KM"))
1461                         _gi.km = (strValue);
1462                     else if (key.Equals("RE"))
1463                         _gi.result = (strValue);
1464                     else if (key.Equals("SZ"))
1465                         _gi.size = (strValue);
1466                     else if (key.Equals("EV"))
1467                         _gi.gameEvent = (strValue);
1468                     else if (key.Equals("PC"))
1469                         _gi.location = (strValue);
1470                     else if (key.Equals("TM"))
1471                         _gi.time = (strValue);
1472                     else if (key.Equals("GN"))
1473                         _gi.gameName = strValue;
1474 
1475                     else if (key.Equals("FF"))
1476                         _gi.unknown_ff = (strValue);
1477                     else if (key.Equals("GM"))
1478                         _gi.unknown_gm = (strValue);
1479                     else if (key.Equals("VW"))
1480                         _gi.unknown_vw = (strValue);
1481                     else if (key.Equals("US"))
1482                         _gi.unknown_vw = (strValue);
1483 
1484                     else if (key.Equals("BS"))
1485                         _gi.unknown_vw = (strValue);
1486                     else if (key.Equals("WS"))
1487                         _gi.unknown_vw = (strValue);
1488                     else if (key.Equals("ID"))
1489                         _gi.unknown_vw = (strValue);
1490                     else if (key.Equals("KI"))
1491                         _gi.unknown_vw = (strValue);
1492                     else if (key.Equals("SO"))
1493                         _gi.unknown_vw = (strValue);
1494                     else if (key.Equals("TR"))
1495                         _gi.unknown_vw = (strValue);
1496                     else if (key.Equals("LB"))
1497                         _gi.unknown_vw = (strValue);
1498                     else if (key.Equals("RO"))
1499                         _gi.unknown_vw = (strValue);
1500 
1501 
1502                     //ZZZZ ZZZZZ
1503                     else
1504                         System.Diagnostics.Debug.Assert(false, "unhandle key: " + key + " "+ strValue);
1505 
1506                     //ZZZZZZZZZ ZZZ ZZZZ ZZZZZZ ZZZ ZZZZ ZZ ZZZZ ZZZZ (ZZ, ZZ) ZZZZ ZZZZZZZZ ZZZZZ. 
1507                     if (fMultipleMoves)
1508                     {
1509                         _currVar.addAMove(gm);
1510                     }
1511                 }
1512             }
1513 
1514             //ZZZ ZZZ ZZZZ ZZ ZZZZZZZ ZZZZZZZZZ. 
1515             if (!fMultipleMoves && gm != null)
1516             {
1517                 _currVar.addAMove(gm);
1518             }
1519             return true;
1520         } 
1521 
1522         public GoMove doPrev() 
1523         {
1524             return _currVar.doPrev();
1525         }
1526 
1527         public GoMove peekPrev() 
1528         {
1529             return _currVar.peekPrev();
1530         }
1531 
1532         public GoMove doNext() 
1533         {
1534             return _currVar.doNext();
1535         }
1536 
1537         public void updateResult(GoMove gm) 
1538         {
1539             _currVar.updateResult(gm);
1540         }
1541         
1542         public void reset()
1543         {
1544             _currVarNum = 0;
1545             _currVarId = 0; 
1546             _currVar.reset();
1547         }
1548         public void rewindToStart()
1549         {
1550 
1551         }
1552     } //ZZZ ZZ ZZZZZZ
1553 }
View Code

1. 了解Lambda的用法

计算“Hello World!”中
字母‘e’的个数
字母‘l’的个数

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 string s;
 5 int count(char c)
 6 {
 7         int n = 0;
 8         for_each (s.begin(),s.end(),[&n,c](char x)
 9         {
10                 if (x == c) n += 1;
11         });
12         return n ;
13 }
14 int main(void)
15 {
16         cin >> s;
17         cout<< count('l')<<endl;
18         cout<< count('e')<<endl;
19         return 0;
20 }

 我猜这种东西能用更“函数式风格”来实现,比如在find函数里传入一个lambda表达式,但实在是不懂C++的常用风格,所以这里只用了一种简单的方式来实现这个功能。

2. 练习使用智能指针

打印“Hello World!”循环右移n位的结果
Example:
n = 1, output = “!Hello World”
n = 3, output = “ld!Hello Wor"

 1 #include<stdio.h>
 2 #include<string.h>
 3 int main(void)
 4 {
 5         int i,r,l;
 6         char s[255];
 7         scanf("%d\n",&r);
 8         fgets(s,255,stdin);
 9         l = strlen(s)-1;
10         for (i = 0;i<l;i++)
11                 putchar(s[(i - r + l)%l]);
12         return 0;
13 }

 一开始搞不懂为什么这个功能需要用智能指针,稍微想了一下发现老师说的使用智能指针可能是为了操作原字符串而不至于引入新的空间(unique_ptr),由于对C++字符串处理或指针根本就不会,所以尝试了一下放弃了。课上就写了C语言版的,用的是取模运算。主要思想也就一行 putchar(s[(i - r + l)%l])。

 

posted @ 2013-11-25 00:26  Forwil  阅读(399)  评论(2编辑  收藏  举报