我正在尝试在SWI Prolog中制作一个简单的子手游戏。 既然我们使该程序运行了,那么您可以通过以下方法帮助我增强该程序:
1) 跟上到目前为止已经猜到的字母。如果用户猜到了已经猜到的字母,程序应说“您猜到了!”。然后继续游戏。
2) 最后,添加一个计数器,用于计算错误猜想的数量,并在达到一定数量时退出游戏。该程序应告知用户他们输了,显示该短语的真正含义并终止。重复的猜测不应被认为是错误的。
我要感谢到目前为止帮助过我的每个人。 这对我来说意义非凡。
我为您提供代码和注释。
% This top-level predicate runs the game. It prints a % welcome message, picks a phrase, and calls getGuess. % Ans = Answer % AnsList = AnswerList hangman:- getPhrase(Ans), !, write('Welcome to hangman.'), nl, name(Ans,AnsList), makeBlanks(AnsList, BlankList), getGuess(AnsList,BlankList). % Randomly returns a phrase from the list of possibilities. getPhrase(Ans):- phrases(L), length(L, X), R is random(X), N is R+1, getNth(L, N, Ans). % Possible phrases to guess. phrases(['a_picture_is_worth_a_thousand_words','one_for_the_money','dead_or_alive','computer_science']). % Asks the user for a letter guess. Starts by writing the % current "display phrase" with blanks, then asks for a guess and % calls process on the guess. getGuess(AnsList, BlankList):- name(BlankName, BlankList), write(BlankName), nl, write('Enter your guess, followed by a period and return.'), nl, read(Guess), !, name(Guess, [GuessName]), processGuess(AnsList,BlankList,GuessName). % Process guess takes a list of codes representing the answer, a list of codes representing the current % "display phrase" with blanks in it, and the code of the letter that was just guessed. If the guess % was right, call substitute to put the letter in the display phrase and check for a win. Otherwise, just % get another guess from the user. processGuess(AnsList,BlankList,GuessName):- member(GuessName,AnsList), !, write('Correct!'), nl, substitute(AnsList, BlankList, GuessName, NewBlanks), checkWin(AnsList,NewBlanks). processGuess(AnsList, BlankList,_):- write('Nope!'), nl, getGuess(AnsList, BlankList). % Check to see if the phrase is guessed. If so, write 'You win' and if not, go back and get another guess. checkWin(AnsList, BlankList):- name(Ans, AnsList), name(BlankName, BlankList), BlankName = Ans, !, write('You win!'). checkWin(AnsList, BlankList):- !, getGuess(AnsList, BlankList). % getNth(L,N,E) should be true when E is the Nth element of the list L. N will always % be at least 1. getNth([H|T],1,H). getNth([H|T],N,E):- N1 is N-1, getNth(T,N1,E1), E=E1. % makeBlanks(AnsList, BlankList) should take an answer phrase, which is a list % of character codes that represent the answer phrase, and return a list % where all codes but the '_' turn into the code for '*'. The underscores % need to remain to show where the words start and end. Please note that % both input and output lists for this predicate are lists of character codes. % You can test your code with a query like this: % testMakeBlanks:- name('csc_is_awesome', List), makeBlanks(List, BlankList), name(Towrite, BlankList), write(Towrite). makeBlanks(AnsCodes, BlankCodes) :- maplist(answer_blank, AnsCodes, BlankCodes). answer_blank(Ans, Blank) :- Ans == 0'_ -> Blank = Ans ; Blank = 0'* . % substitute(AnsList, BlankList, GuessName, NewBlanks) Takes character code lists AnsList and BlankList, % and GuessName, which is the character code for the guessed letter. The NewBlanks should again be a % character code list, which puts all the guesses into the display word and keeps the *'s and _'s otherwise. % For example, if the answer is 'csc_is_awesome' and the display is 'c*c_**_*******' and the guess is 's', the % new display should be 'csc_*s_***s***'. % You can test your predicate with a query like this: % testSubstitute:- name('csc_is_awesome', AnsList), name('c*c_**_*******', BlankList), name('s',[GuessName]), substitute(AnsList, BlankList, GuessName, NewBlanks), % name(Towrite, NewBlanks), write(Towrite). % Also, since the predicate doesn't deal directly with character codes, this should also work: % substitute(['c','s','c'],['c','*','c'],'s',L). L should be ['c','s','c']. substitute(AnsCodes, BlankCodes, GuessName, NewBlanks) :- maplist(place_guess(GuessName), AnsCodes, BlankCodes, NewBlanks). place_guess(Guess, Ans, Blank, Display) :- Guess == Ans -> Display = Ans ; Display = Blank.
maplist / 3&maplist / 4将其第一个参数(适当Arity的谓词)应用于其他参数列表的所有元素,那么您的makeBlanks可能是:
makeBlanks(AnsCodes, BlankCodes) :- maplist(answer_blank, AnsCodes, BlankCodes). answer_blank(Ans, Blank) :- Ans == 0'_ -> Blank = Ans ; Blank = 0'* .
并替换为:
substitute(AnsCodes, BlankCodes, GuessName, NewBlanks) :- maplist(place_guess(GuessName), AnsCodes, BlankCodes, NewBlanks). place_guess(Guess, Ans, Blank, Display) :- Guess == Ans -> Display = Ans ; Display = Blank.
编辑 :
根据其他要求:1)可以使用其他谓词解决:
alreadyGuessed(Guess, AnsCodes) :- memberchk(Guess, AnsCodes).
而问候2)getGuess并processGuess一起构成一个循环,当没有更多呼叫发生时,循环将终止。删除checkWin的最后一条规则,添加一个参数作为计数器来跟踪失败的猜测,并扩展processGuess来指示失败:
getGuess
processGuess
processGuess(AnsList, BlankList, _, CountFailed) :- ( CountFailed == 5 -> format('Sorry, game over. You didn\'t guess (~s)~n', [AnsList]) ; write('Nope!'), CountFailed1 is CountFailed + 1, getGuess(AnsList, BlankList, CountFailed1) ).