背景
早上看了,觉得有趣,实现一个Windows Mobile版本。很多年前我也有一台文曲星,也常常玩这个猜数字游戏,所以尝试在Windows Mobile下实现。
方案
强调需要TDD,所以我的实现方案也是TDD。
实现
使用NUintLite
测试代码需要使用NUintLite,NUintLite具体可以参考 。修改Main函数如下,把结果写到SD卡上。
static void Main(string[] args) { System.IO.TextWriter writer = new System.IO.StreamWriter("\\Storage Card\\TestResult.txt"); new NUnitLite.Runner.TextUI(writer).Execute(args); writer.Close(); Application.Run(new MainForm()); }
编写测试代码
TDD,先写测试代码。测试代码的逻辑是按照写的,在实际使用中根据功能需求编写。
[TestFixture] class BingleTest { private Bingle bingle; [SetUp] public void SetUp() { bingle = new Bingle(); } [TearDown] public void TearDown() { } [Test] public void BuildAnswersTest() { bingle.BuildAnswers(); Assert.True(bingle.Answers[0] != bingle.Answers[1] && bingle.Answers[0] != bingle.Answers[2] && bingle.Answers[0] != bingle.Answers[3] && bingle.Answers[1] != bingle.Answers[2] && bingle.Answers[1] != bingle.Answers[3] && bingle.Answers[2] != bingle.Answers[3]); } [Test] public void MatchTest() { bingle.Answers = new int[] { 1, 2, 3, 4 }; int a; int b; int[] num; //1 5 6 7 1A0B num = new int[] { 1, 5, 6, 7 }; bingle.Match(num, out a, out b); Assert.That(a, Is.EqualTo(1)); Assert.That(b, Is.EqualTo(0)); //2 4 7 8 0A2B num = new int[] { 2, 4, 7, 8 }; bingle.Match(num, out a, out b); Assert.That(a, Is.EqualTo(0)); Assert.That(b, Is.EqualTo(2)); //0 3 2 4 1A2B num = new int[] { 0, 3, 2, 4 }; bingle.Match(num, out a, out b); Assert.That(a, Is.EqualTo(1)); Assert.That(b, Is.EqualTo(2)); //5 6 7 8 0A0B num = new int[] { 5, 6, 7, 8 }; bingle.Match(num, out a, out b); Assert.That(a, Is.EqualTo(0)); Assert.That(b, Is.EqualTo(0)); //4 3 2 1 0A4B num = new int[] { 4, 3, 2, 1 }; bingle.Match(num, out a, out b); Assert.That(a, Is.EqualTo(0)); Assert.That(b, Is.EqualTo(4)); //1 2 3 4 4A0B num = new int[] { 1, 2, 3, 4 }; bingle.Match(num, out a, out b); Assert.That(a, Is.EqualTo(4)); Assert.That(b, Is.EqualTo(0)); } [Test] [ExpectedException(typeof(ArgumentException))] public void MatchTest2() { int a; int b; int[] num; //1 1 2 3 num = new int[] { 1, 1, 2, 3 }; bingle.Match(num, out a, out b); //1 2 num = new int[] { 1, 2 }; bingle.Match(num, out a, out b); } }
我把对Match测试的代码写在一起,我喜欢一个Test函数对应一个功能函数。而把异常处理分开出来写了,怕前面的测试抛出异常,导致测试通过了。
功能代码
功能代码的目的就是通过所以单元测试。
public class Bingle { public int[] Answers { set; get; } private int attemptTimes; public int AttemptTimes { get { return attemptTimes; } } public Bingle() { Answers = new int[4]; } public void BuildAnswers() { Random r = new Random(); while(true) { int i = r.Next(9999); Answers[0] = i / 1000; Answers[1] = i % 1000 / 100; Answers[2] = i % 100 / 10; Answers[3] = i % 10; if (Answers[0] != Answers[1] && Answers[0] != Answers[2] && Answers[0] != Answers[3] && Answers[1] != Answers[2] && Answers[1] != Answers[3] && Answers[2] != Answers[3]) { return; } } } public bool Match(int[] attemptNum, out int bingle, out int match) { bingle = 0; match = 0; if (attemptNum.Length != 4) { throw new ArgumentException("Should be 4 digits."); } if(!(attemptNum[0] != attemptNum[1] && attemptNum[0] != attemptNum[2] && attemptNum[0] != attemptNum[3] && attemptNum[1] != attemptNum[2] && attemptNum[1] != attemptNum[3] && attemptNum[2] != attemptNum[3])) { throw new ArgumentException("Should be non repeating 4 digits."); } ++attemptTimes; for(int i=0; i<4; ++i) { if (attemptNum[i] == Answers[i]) { ++bingle; } else { for (int j = 0; j < 4; ++j) { if (attemptNum[i] == Answers[j]) { ++match; } } } } return (bingle == 4); } }
单元测试结果
如果通过所有单元测试,说明功能代码编写完毕,每次修改都有run单元测试。
NUnitLite version 0.2.0 Copyright 2007, Charlie Poole Runtime Environment - OS Version: Microsoft Windows CE 5.2.21234 .NET Version: 2.0.7045.0 3 Tests : 0 Errors, 0 Failures, 0 Not Run
UI 处理
功能代码写完以后,可以写UI了,具体UI代码见源代码,下面是执行效果。
源代码:
环境: VS 2008 + WM 6 professional SDK + NUnitLite