公牛和奶牛游戏 - 编程算法(python)

时间:2013-06-26 09:42:45

标签: python algorithm

这是模拟游戏Cows and Bulls的三位数字

我试图获得两个数字之间的牛和公牛数量。其中一个是由计算机生成的,另一个是由用户猜测的。我已经解析了我拥有的两个数字,现在我有两个列表,每个列表包含三个元素,每个元素都是数字中的一个数字。所以:

237将列出[2,3,7]列表。我确保保持相对指数。一般模式是:(hundreds, tens, units)

这两个列表存储在两个列表中:machineperson

ALGORITHM 1

所以,我编写了以下代码,最直观的算法:

在此循环开始之前,

cowsbulls被初始化为0.

for x in person:
    if x in machine:
        if machine.index(x) == person.index(x):
            bulls += 1
            print x,' in correct place'
        else:
            print x,' in wrong place'
            cows += 1

我开始使用计算机猜测的不同类型的数字来测试它。

很随机,我决定277.我猜到了447.这里,我得到了第一个线索,这个算法可能不起作用。我有1头牛和0头公牛。虽然我应该有1头牛和1头牛。

这是第一个算法的输出表:

Guess        Output            Expected Output

447     0 bull, 1 cow          1 bull, 0 cow 
477     2 bulls, 0 cows        2 bulls, 0 cows
777     0 bulls, 3 cows        2 bulls, 0 cows

很明显,当计算机随机选择的数字中有重复数字时,此算法无效。

我试图理解为什么会发生这些错误,但我不能。我已经尝试了很多,但我在算法中看不到任何错误(可能是因为我写了它!)

ALGORITHM 2

在考虑这几天后,我尝试了这个:

在此循环开始之前,

cowsbulls被初始化为0.

for x in range(3):
    for y in range(3):
            if x == y and machine[x] == person[y]:
                bulls += 1
            if not (x == y) and machine[x] == person[y]:                   
                cows += 1

我对这个更有希望。但是当我测试这个时,这就是我得到的:

Guess        Output            Expected Output

447     1 bull, 1 cow          1 bull, 0 cow 
477     2 bulls, 2 cows        2 bulls, 0 cows
777     2 bulls, 4 cows        2 bulls, 0 cows

我所犯的错误在这里很清楚,我明白这些数字一次又一次被计算在内。

即:277对477

当你计算公牛时,那么2只公牛就会出现,那就好了。但是当你算上奶牛时:

  1. 单位所在的277中的7与477中的7位相匹配,因而产生了一头牛。
  2. 277中的7位数在10位与477位单位相匹配,因而产生了一头牛。'
  3. 这里的匹配完全正确,因为我按照这个编写了代码。但这不是我想要的。而且我不知道在此之后要做什么。

    此外...

    我想强调的是,如果计算机选择的数字中没有重复数字,两种算法都能正常工作。

6 个答案:

答案 0 :(得分:5)

def digits(number):
    return [int(d) for d in str(number)]

def bulls_and_cows(guess, target):
    guess, target = digits(guess), digits(target)
    bulls = [d1 == d2 for d1, d2 in zip(guess, target)].count(True)
    bovine = 0
    for digit in set(guess):
      bovine += min(guess.count(digit), target.count(digit))
    return bulls, bovine - bulls

请注意bulls_and_cows(277, 447)将返回1头牛和0头奶牛。这就是我个人所期望的:为什么277中的前7个算作牛,因为已经有447的7牛?

答案 1 :(得分:1)

.index()返回给定输入的第一次出现的索引:

>>> [1, 5, 5].index(5)
1

您应该使用enumerate()来获取所有可能的索引:

>>> for i, j in enumerate([1, 5, 5]):
...     if j == 5:
...             print i
... 
1
2

但是,似乎可以使用zip()来完成,除非我弄错了:

for x, y in enumerate(zip(player,computer)):
    if y[0] in computer and not y[0] == y[1]:
        print y[0], "is in the number"
        cows += 1
    elif y[0] == y[1]:
        print y[0], "in the correct place"
        bulls += 1
    else:
        print y[0], "is not in the number"

使用player = [4, 4, 7]

4 is not in the number
4 is not in the number
7 in the correct place
>>> cows
0
>>> bulls
1

使用player = [4, 7, 7]

4 is not in the number
7 in the correct place
7 in the correct place
>>> cows
0
>>> bulls
2

答案 2 :(得分:1)

Here is an algorithm which compares digits and positions.
I use it in a program for finding the target in a 4-digit 
version of the game when the target can begin with "0". 
It works with or without repeating digits equally well.
In the table below are shown all 9 results/values of variable 
ED (Equal Digits) when comparing digits in each position of  
the guess 447 with each digit of the target 447, for the 
special case when the guess G$(3) equals the target T$(3)*.
For any other case the table is different and the values for 
B and C will change accordingly. 
It's a fact that for us, humans it's easier to count 
Bulls and Cows without repeating digits. 
With repeating digits I need to see the table below.
        !!!Important!!! 
Do not judge the values for B and C. Just use them. 

    4  4  7       3 Bulls      3 Cows
   --------        (I=J)       (I<>J)
 4| 1  1  0       1  .  .      .  1  .   
  |                    
 4| 1  1  1       .  1  .      1  .  1
  |                      
 7| 0  0  1       .  .  1      .  .  .



Here is the algorithm in Liberty BASIC:
'-------------------------------------
[calculate_Bulls_and_Cows]
B = 0: C = 0
        FOR I=1 TO 3
            FOR J=1 TO 3
                ED=(T$(I)=G$(J)) 'finding Equal Digits makes ED=1
                B = B+ED*(I=J)   'Bulls increment when ED*(I=J)=1
                C = C+ED*(I<>J)  'Cows increment when ED*(I<>J)=1
            NEXT J
        NEXT I
return
'------------------------------------
_________

*In this case I decided Digits to be considered 
text variables because of some benefits when 
it wasn't restricted the target to begin with "0".

答案 3 :(得分:0)

def game(a,b,c,d):
    from random import randint
    m=randint(0,9)
    n=randint(0,9)
    o=randint(0,9)
    p=randint(0,9)
    cow=bull=0
    A={a:m,b:n,c:o,d:p}
    k=A.keys()
    v=A.values()
    bull=cow=0
    for i in k:
        if i==A[i]:
            bull+=1
        elif i in v:
            cow+=1
    if (cow>0 or bull>0):
        print(bull,"Bull and ",cow,"Cow")
    print("Correct No. :       ",m,n,o,p)
    print("You've Entered : ",a,b,c,d)

答案 4 :(得分:-1)

嘿,制作牛牛计划的最佳方法是使用字符和字符串而不是数字。那么你就不必费心去打扰一百或十几个地方了。您可以在python:http://funpythonprojects.blogspot.in/2013/07/cow-bull-game-aka-guess-number-in-python.html

中按照我的4位牛牛游戏教程进行操作

答案 5 :(得分:-1)

公牛和奶牛(代码有点乞求,刚开始向youtube学习)

import random

def num_checker(guess_num,answer):
    guess_num=list(str(guess_num))
    ans=list(str(answer))
    cow=0
    bull=0
    for a in range(0,4):
        if guess_num[a]==ans[a]:
            bull+=1
            ans[a]=10#changed values to counter reccuring digits
            guess_num[a]=20#changed values to counter reccuring digits

    for a in range(0,4):
        for b in range (0,4):
            if guess_num[a]==ans[b]:
                cow+=1
                ans[b]=30#changed values to counter reccuring digits
                break

    final=[bull,cow]
    return final

#..................................................
ans=random.randrange(1000,10000)
print("this is the program to gues a four digit number")

#......................................................#continue asking until you get it right
while True:
    print("just for reference answer is:",ans)
    num_typed=int(input("please guess a four digit the number?\n "))
    reply=num_checker(num_typed,ans)
    if reply==[4,0]:
        print("correct")
        print(reply[0],"bull",reply[1],"cows and the ans is",ans)
        break
    else:
        print(reply[0],"bulls",reply[1],"cows")