2013-03-26 60 views
1

我是Python编程的初学者,并且遇到了与我当前任务相关的问题。作业内容如下:Python大师游戏难题

  • 您的程序应该暗中生成一个4位数的数字(或只包含数字,4个字符长的字符串),其中没有数字重复。
  • 然后,程序应该要求用户输入代码猜测。用户的猜测应该是4个字符长,仅包含数字,不重复任何数字。评分前,您的程序应验证输入是否有效,并在必要时提示用户重新输入。无效输入不计入代码破解器的猜测次数。您的代码可能会忽略(剥离)输入中的前导空白或尾随空白,但应将内部空间计为不正确的输入。
  • 在每一回合中,打印转数并得到用户的猜测。如果输入有效,回合的输出应该是用户的猜测,然后是反馈。反馈是一个4个字符的字符串:'X'表示每个数字在正确的位置; 'O'表示代码中的每个数字,但不在正确的位置; ' - '为所有其他人。请注意,X和O应该在一起;反馈只是每种类型有多少钉,而不是哪些钉或哪些钉。
  • 保持所有猜测和反馈的历史记录,因此可以在每一回合中为用户打印。

现在我只关注作业的“反馈”部分。我的代码是目前:

import random 

def validateInput(): 
inputGuess = input("Enter your guess as 4 numbers:") 

while True: 
    if len(inputGuess) != 4: 
     inputGuess = input("Enter your guess as 4 numbers:") 
    else: 
     numberList = list(inputGuess) ## 

     invalidNumbers = False 
     for number in numberList: 
      if number not in ['1','2','3','4','5','6','7','8','9']: 
       invalidNumbers = True 

     if invalidNumbers == True: 
      print ("Possible numbers are 1, 2, 3, 4, 5, 6, 7, 8, 9.") 
      inputGuess = input("Enter your guess as 4 numbers:") 

     else: 
      return numberList 

guessesRemaining=10 

code=['1','2','3','4'] 



while guessesRemaining > 0: 
    report=[] 
    guess=validateInput() 
    guessesRemaining -= 1 
    if guess[0] == code[0]: 
     report.append("X") 
    if guess[1] == code[1]: 
     report.append("X") 
    if guess[2] == code[2]: 
     report.append("X") 
    if guess[3] == code[3]: 
     report.append("X") 

    tempCode=sorted(code) 
    tempGuess=sorted(guess) 

    if tempCode[0]==tempGuess[0]: 
     report.append("O") 
    if tempCode[1]==tempGuess[1]: 
     report.append("O") 
    if tempCode[2]==tempGuess[2]: 
     report.append("O") 
    if tempCode[3]==tempGuess[3]: 
     report.append("O") 

    report2=report[0:4] 
    dash=["-","-","-","-"] 
    report3=report2+dash 
    report4=report3[0:5] 



    print(report4) 

例如,如果用户想1879的代码是1234,我收到“×○ - ”但我想收到“X ---”。此外,任何关于精简我的代码的建议都会很棒。为了简单起见,我现在只是[1,2,3,4]制作了“随机代码”。

回答

3

你可以用Python函数map()非常优雅地解决你的问题。 (没有这么优雅,因为我原本以为,但还是蛮漂亮。)

guess = "1879" # or [ '1', '8', '7', '9' ] 
answer = "1234" 

地图()的工作原理是这样的:你给它一个函数作为第一个参数,并遵循一个或多个序列作为参数。然后它接受该函数并将其首先应用于第一个元素,然后应用于第二个元素,依此类推。例如:

>>> def f(a,b): 
>>> return a + b 
>>> map(f, [1,2,3,4], [ 10, 20, 30, 40 ]) 

[ 11, 22, 33, 44 ] 

现在,你有两个字符序列,“猜测”和“答案”。你可以写,如果他们是平等的,返回X的功能 - 否则像这样:

>>> def mastermind_hint(a, b): 
>>> return "X" if a == b else "-" 

这还远远不够,还需要放在“0'。为此,您需要同时使用整个“答案”序列:

>>> def mastermind_hint(a, b): 
>>> if a == b: return "X" 
>>> if a in answer: return "O" 
>>> return "-" 

使用地图,我们可以应用到你的序列:

>>> map(mastermind_hint, guess, answer) 
[ "X", "-", "-", "-" ] 

现在,现在我们正在给因为我们提示的位置与猜测字符的位置相对应,所以我们可以得到比我们预期更多的信息。隐藏这些信息的简单方法是对序列进行排序。Python有一个排序()函数做到这一点:

>>> sorted(map(mastermind_hint, guess, answer)) 
[ "-", "-", "-", "X" ] 

剩下的工作就是加入到这个单一的字符串:

>>> "".join(sorted(map(mastermind_hint, guess, answer))) 
"---X" 
+0

这不正确处理案件[1,2,3,4] [2,7,8,9]。 – Jerome 2013-03-26 22:33:33

+0

哦,对不起。自从我玩过Mastermind已经很久了。我会删除/审查/可能取消删除。 – svk 2013-03-26 22:36:04

+0

编辑,应该现在工作。作为lambda表达式将不再是非常漂亮的。 – svk 2013-03-26 22:44:24

2

非常有趣的功课,我必须说。我希望我能像这样做作业。

通常我不提供完整的答案作业,但我解决了这个一个有趣的和你试图解决这个你自己那么在这里你去:

import random 

def main(): 
    print '>> New game started.\n>> Good luck!\n' 
    answer = generateAnswer() 
    while True: 
     userGuess = getUserGuess() 
     if userGuess == answer: 
      print '>> Congratulations, you won!' 
      return 
     print '>> The answer you provided is incorrect.\n>> Perhaps this hint will help you: ' 
     giveFeedback(answer, userGuess) 

def generateAnswer(): 
    digits = [str(x) for x in range(10)] 
    answer = '' 
    for i in range(4): 
     digit = random.sample(digits, 1)[0] 
     digits.remove(digit) 
     answer += digit 
    return answer 

def getUserGuess(): 
    while True: 
     guess = raw_input('>> Please enter a 4-digit number: ').strip() 
     if len(guess) != 4: 
      continue 
     guessIsValid = True 
     for x in guess: 
      if guess.count(x) != 1 or ord(x) not in range(48, 58): 
       guessIsValid = False 
       break 
     if guessIsValid: 
      return guess 

def giveFeedback(answer, guess): 
    for i in range(4): 
     if guess[i] == answer[i]: 
      print 'X', 
      continue 
     if guess[i] in answer: 
      print 'O', 
      continue 
     print '-', 
    print '\n' 

if __name__ == '__main__': 
    try: 
     main() 
    except Exception, e: 
     print '>> Fatal error: %s' % e 

我希望你会发现你的在这段代码中回答。

+0

我在想'giveFeedback'是否处理重复项,如答案:'[1,2,3,4]'guess:'[1,1,1,1]''。这可能会返回'['X','O','O','O']'。根据维基百科:如果在猜测中有重复的颜色,他们不能被授予关键挂钩,除非它们对应于隐藏代码中相同数量的重复颜色。 – Bastian 2017-08-21 15:41:26

1

这是一个使用一些更高级的python习语来提高可读性和简洁性的例子。这也使得制作一个更通用的解决方案变得更容易,例如m base的n位数答案。

import random 
from itertools import permutations # for "lucky guess" Easter egg 

def main(base=10, size=4): 
    print 'New game started.\nGood luck!\n' 
    answer, turn = list(genAnswer(range(base), size)), 1 
    while True: 
     hint = ['X' if a == g 
      else '0' if g in answer 
      else '-' for a, g in zip(answer, guess(base, size))] 
     if set(hint) == set(['X']): 
      if turn == 1: 
       choices = len(list(permutations(range(base), size))) 
       print 'You won, lucky guess out of %d possible choices' % choices 
      else: 
       print 'Congratulations, you won in %d turns!' % turn 
      return 
     print ' Hint %d: %s' % (turn, ''.join(hint)) 
     turn += 1 

def genAnswer(digits, size): 
    '''Python generator function''' 
    for i in range(size): 
     choice = random.choice(digits) 
     yield str(choice) 
     digits.remove(choice) 

def guess(base, size): 
    '''Uses duck typing for error detection''' 
    while True: 
     guess = raw_input('>> Guess: ').strip() 
     try: 
      if int(guess, base) < base**size and len(set(guess)) == size: 
       return guess 
     except ValueError: 
      pass 
     print 'Enter %d unique digits from 0 to %d' % (size, base -1) 

>>> main(6, 4) 
New game started. 
Good luck! 

>> Guess: 1234 
    Hint 1: 0-X- 
>> Guess: 12345 
Enter 4 unique digits from 0 to 5 
>> Guess: 01227 
Enter 4 unique digits from 0 to 5 
>> Guess:
    Hint 2: XX-0 
>> Guess: 0135 
Congratulations, you won in 3 turns!