日期:2014-05-20  浏览次数:20746 次

猜数字问题
VS2010发布中文版后,迫不及待地学习一下F#,但这里好像还没开F#的版块,只好发到这里来。

这是一个猜数字的小游戏,用计算机求解。在网上看了一下规则,要在7步内完成,我这样算有几个数字需要8步才能完成,不知道哪种情况没有考虑到?

C# code

open System

//所有数字
let mutable numberList=[for a in 0..9 do for b in 0..9 do for c in 0..9 do for d in 0..9 ->[a;b;c;d]]
let contains (num:int list)=
    let mutable same=false
    for i in 0..2 do
        for j in i+1..3 do
            if num.[i]=num.[j] then
                same<-true
    same
numberList<-List.filter(fun num->not(contains num)) numberList


//随机取一个结果数字
let resultIndex=(new Random()).Next(numberList.Length)
let result=numberList.[resultIndex]

//计算a
let getA (number:int list, guessNumber:int list)=
    let mutable count=0
    for i in 0..3 do
        if number.[i]=guessNumber.[i] then
            count<-count+1
    count

//计算ab
let getAB (number:int list, guessNumber:int list)=
    let mutable count=0
    for i in 0..3 do
        for j in 0..3 do
            if number.[i]=guessNumber.[j]then
                count<-count+1
    count

//过滤不符合aA的情况
let removeA a guessNumber=
    numberList<-List.filter(
        fun num->
            getA (num,guessNumber)=a
        ) numberList
        
//过滤不符合bB的情况
let removeAB ab guessNumber=
    numberList<-List.filter(
        fun num->
            getAB(num,guessNumber)=ab
        ) numberList


let mutable a=0
let mutable b=0
let mutable step=0
while a<>4 do
    let currentNumber=numberList.[0]
    a<-getA(result,currentNumber)
    b<-getAB(result,currentNumber)-a
    removeA a currentNumber
    removeAB (a+b) currentNumber
    printfn "Current Guess: %A, Return: %dA%dB, The Result Is:%A" currentNumber a b result
    step<-step+1
printfn "Step:%d" step



------解决方案--------------------
F#还没去学!
不懂,帮顶一个!
------解决方案--------------------
不懂F#,
不过“猜数字”让我想起了“二分法”。。。

------解决方案--------------------
还没使用
------解决方案--------------------
探讨

还没使用

------解决方案--------------------
不懂,帮顶!~
------解决方案--------------------
学了一种新语法呀
------解决方案--------------------
学习!!!!!!!!!!!
------解决方案--------------------
LZ果然很先进!
------解决方案--------------------
F#是个嘛东西啊?
------解决方案--------------------
没用过呢
------解决方案--------------------
bu dong 

------解决方案--------------------
LZ的思路没问题,每一步把不符合条件的去掉,剩下的就是符合条件的了。
试着翻译为C#验证了一下,结果一样,对有些数据需要8步,比如[4; 3; 1; 9]。
顺便说一下,F#的程序比C#简单,因为F#的List.filter很强大。
C# code
using System;
using System.Collections.Generic;

class GuessDigit
{
  List<int[]> numberList;

  public GuessDigit()
  {
    InitNumberList();
    GuessIt(numberList[new Random().Next(numberList.Count)]);
  }

  void GuessIt(int[] result)
  {
    int a = 0;
    int b = 0;
    int step = 0;
    while (a != 4)
    {
      int[] currentNumber = numberList[0];
      a = GetA(result, currentNumber);
      b = GetAB(result, currentNumber) - a;
      RemoveA(a, currentNumber);
      RemoveAB(a + b, currentNumber);
      Console.WriteLine("Current Guess: {0}, Return: {1}A{2}B, The Result Is: {3}",
        Print(currentNumber), a, b, Print(result));
      step++;
    }
    Console.WriteLine("Step: {0}", step);
  }

  string Print(int[] c)
  {
    return string.Format("[{0}; {1}; {2}; {3}]", c[0], c[1], c[2], c[3]);
  }

  void InitNumberList()
  {
    numberList = new List<int[]>();
    for (int a = 0; a <= 9; a++)
      for (int b = 0; b <= 9; b++)
        for (int c = 0; c <= 9; c++)
          for (int d = 0; d <= 9; d++)
            numberList.Add(new int[]{a, b, c, d});
    for (int k = numberList.Count - 1; k >= 0; k--)
    {
      for (int i = 0; i < 3; i++)
        for (int j = i + 1; j < 4; j++)
          if (numberList[k][i] == numberList[k][j])
          {
            numberList.RemoveAt(k);
            goto next;
          }
      next:;
    }
  }

  int GetA(int[] number, int[] guessNumber)
  {
    int count = 0;
    for (int i = 0; i < 4; i++)
      if (number[i] == guessNumber[i]) count++;
    return count;
  }

  int GetAB(int[] number, int[] guessNumber)
  {
    int count = 0;
    for (int i = 0; i < 4; i++)
      for (int j = 0; j < 4; j++)
        if (number[i] == guessNumber[j]) count++;
    return count;
  }

  void RemoveA(int a, int[] guessNumber)
  {
    for (int k = numberList.Count - 1; k >= 0; k--)
    {
      if (GetA(numberList[k], guessNumber) != a)
        numberList.RemoveAt(k);
    }
  }

  void RemoveAB(int ab, int[] guessNumber)
  {
    for (int k = numberList.Count - 1; k >= 0; k--)
    {
      if (GetAB(numberList[k], guessNumber) != ab)
        numberList.RemoveAt(k);
    }
  }

  [STAThread]
  static void Main()
  {
    new GuessDigit();
  }
}