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 }
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])。