晚上闲着无聊,用C#写了类似文曲星上面的那个猜数字的小游戏。 (这款游戏还算经典,当年在它上面可玩了不少时间)
算法其实很简单,首先电脑随机生成一个数字,然后和输入的数字比较,返回比较结果即可。
class Numbers
{
public int[] Value { get; set; }
public Numbers()
{
var data = RandomShuffle(10);
Value = new int[] { data[0], data[1], data[2], data[3] };
}
public Numbers(params int[] value)
{
if (value.Length != 4)
throw new ArgumentException();
this.Value = value;
}
public int Guess(params int[] num)
{
int count_a = 0;
int count_b = 0;
for (int i = 0; i < Value.Length; i++)
{
if (num[i] == Value[i])
count_a++;
if (Value.Contains(num[i]))
count_b++;
}
count_b -= count_a;
return count_a * 10 + count_b;
}
static int[] RandomShuffle(int count)
{
var data = new List<int>();
for (int i = 0; i < count; i++)
{
data.Add(i);
}
var rand = new Random();
var result = new List<int>();
var alg = new Func<List<int>, int>(d =>
{
var index = rand.Next(d.Count);
var ret = d[index];
d.RemoveAt(index);
return ret;
});
while (data.Count > 0)
{
result.Add(alg(data));
}
return result.ToArray();
}
}
玩了一下后,便想让电脑来自动猜数字,网上搜了一下,好像算法还不少,不过大部分看得比较晕。好像效率高的只需要5.2步即可猜出来。我一向认为对于简单的东西没必要搞得那么复杂,用一个简洁而直观的实现更容易阅读和扩展。这里是我的实现算法,非常简单,大概就50行左右,好像最多的时候需要7步。对这个算法就没必要讨论了,有兴趣的可以参看这个网页:http://www.javaworld.com.tw/jute/post/page?bid=35&sty=1&age=0&tpg=1&s=105 。
class Guesser
{
List<int[]> dicList = new List<int[]>();
public Guesser()
{
for (int i = 123; i <= 9876; i++)
{
var a = (i / 1000) % 10;
var b = (i / 100) % 10;
var c = (i / 10) % 10;
var d = (i) % 10;
//目前的规则是没有重复数字,其实有重复数字也不影响这个算法
if (a == b || a == c || a == d || b == c || b == d || c == d)
continue;
dicList.Add(new int[] { a, b, c, d });
}
}
public void FiltWithResult(int[] input,int result)
{
if (result == 40)
return;
var n = new Numbers(input);
dicList.RemoveAll(dic => n.Guess(dic) != result);
}
public int[] GetGuessValue()
{
//return dicList[0];
return dicList[new Random().Next(dicList.Count)];
}
//这个函数用来自动猜数字
public int Guess(Func<int[],int> resultFunc)
{
int index = 0;
var PharseToNumber = new Func<int[], int>(n => n[0] * 1000 + n[1] * 100 + n[2] * 10 + n[3]);
while (true)
{
var guessValue = GetGuessValue();
var ret = resultFunc(guessValue);
Console.WriteLine("{0}: {1} -- {2}", ++index, PharseToNumber(guessValue), ret);
if (ret == 40)
{
Console.WriteLine("result is " + PharseToNumber(guessValue));
return PharseToNumber(guessValue);
}
FiltWithResult(guessValue, ret);
}
}
}
加上这个类后,便能实现电脑猜数字了,在网上找了几个猜数字的在线游戏,用它来猜了几把,都能很快的猜出来。然后我又把原来那个游戏程序改写了一下,让它自动生成待猜的数字后后自己右去猜,感觉还是挺有意思的。另外,网上查了一下,貌似有的网游里面就有猜数字的游戏,猜对了送礼物什么的。如果用这个玩意儿让它自动猜个一天的话,估计也能换不少小钱花。^_^