Algorithm SWI序言中的刽子手游戏(Enchance)
可能重复:Algorithm SWI序言中的刽子手游戏(Enchance),algorithm,prolog,Algorithm,Prolog,可能重复: 我试图通过以下内容来增强SWI Prolog中一个简单的刽子手游戏: 1)跟踪到目前为止猜到的错误的字母。如果用户猜到一个已经猜错的字母,程序应该说“你猜到了!”继续游戏,不要增加计数器 2)最后,添加一个计数器,计算错误猜测的次数,并在达到某个数字时退出游戏。程序应该告诉用户他们输了,显示短语的真实内容,然后终止。重复猜测不应被视为错误。 我如何将这些谓词放在一起,以便我的程序能够针对上述增强运行? 1) 2) 我想做的是: 扩展谓词getGuess(AnsList、BlankL
我试图通过以下内容来增强SWI Prolog中一个简单的刽子手游戏:
1)跟踪到目前为止猜到的错误的字母。如果用户猜到一个已经猜错的字母,程序应该说“你猜到了!”继续游戏,不要增加计数器 2)最后,添加一个计数器,计算错误猜测的次数,并在达到某个数字时退出游戏。程序应该告诉用户他们输了,显示短语的真实内容,然后终止。重复猜测不应被视为错误。
我如何将这些谓词放在一起,以便我的程序能够针对上述增强运行?
1) 2) 我想做的是:
扩展谓词getGuess(AnsList、BlankList、CountFailed)
在更改之前,我会向您提供运行版本的代码和注释。
编辑:程序现在运行,直到您出现5个错误。像
?-hangman(0)一样运行它。
现在,我只需要不计算到目前为止已被用作错误答案的字母,并显示上面列出的相应消息。我是否要再写一个谓词
processGuess
% This top-level predicate runs the game. It prints a
% welcome message, picks a phrase, and calls getGuess.
% Ans = Answer
% AnsList = AnswerList
hangman(CountFailed):-
getPhrase(Ans),
!,
write('Welcome to hangman.'),
nl,
name(Ans,AnsList),
makeBlanks(AnsList, BlankList),
getGuess(AnsList,BlankList, CountFailed).
% 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, CountFailed):-
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, CountFailed).
% 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, CountFailed):-
member(GuessName,AnsList),
!,
write('Correct!'),
nl,
substitute(AnsList, BlankList, GuessName, NewBlanks),
checkWin(AnsList,NewBlanks, CountFailed).
processGuess(AnsList, BlankList, _, CountFailed) :-
( CountFailed == 5
-> format('Sorry, game over. You didn\'t guess (~s)~n', [AnsList])
; write('Nope!'),
nl,
CountFailed1 is CountFailed + 1,
getGuess(AnsList, BlankList, CountFailed1)
).
% 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, CountFailed):-
name(Ans, AnsList),
name(BlankName, BlankList),
BlankName = Ans,
!,
write('You win!').
checkWin(AnsList, BlankList, CountFailed):-
getGuess(AnsList, BlankList, CountFailed).
% 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.
在
processGuess(AnsList、BlankList、\uu、CountFailed)之前插入此规则:-
processGuess(AnsList, BlankList, Guess, CountFailed):-
memberchk(Guess, BlankList),
write('You guessed that!'), nl,
!, getGuess(AnsList, BlankList, CountFailed).
我将alreadyguesed
编辑将失败计数更改为失败列表:
processGuess(AnsList, BlankList, Guess, FailedList):-
( length(FailedList, 5)
-> ... signal game failure and stop ...
; getGuess(AnsList, BlankList, [Guess|FailedList])
)
在
processGuess(AnsList、BlankList、\uu、CountFailed)之前插入此规则:-
processGuess(AnsList, BlankList, Guess, CountFailed):-
memberchk(Guess, BlankList),
write('You guessed that!'), nl,
!, getGuess(AnsList, BlankList, CountFailed).
我将alreadyguesed
编辑将失败计数更改为失败列表:
processGuess(AnsList, BlankList, Guess, FailedList):-
( length(FailedList, 5)
-> ... signal game failure and stop ...
; getGuess(AnsList, BlankList, [Guess|FailedList])
)
谁能帮我解决问题1?谁能帮我解决问题1?仍然
memberchk
不起作用。程序只是绕过列出memberchk
的谓词。实际上,我想做的是,例如,如果单词中没有字母“n”,并且用户之前已经按下了该字母“n”,我想向他打印该消息,而不是增加计数器。我尝试执行的操作:-动态(存储/1)存储([])。alreadyguesed(Guess):-retract(store(L)),member(Guess,L),assert(store(L))。已准备好(猜测):-retract(store(L)),not(member(Guess,L)),assert(store([Guess | L]))。很抱歉,我不知道为什么上面的评论没有格式化。主要的想法是列出一个列表,我会把用户给的所有错误的字母都放在其中,然后每次他给了一个错误的字母,我都会先用错误的字母检查上面的列表,然后再检查所有其他的检查。对于所有这些问题,很抱歉,但这让我很困扰。我认为你应该将CountFailed
更改为一个列表:然后,不要添加,cons
失败的GuessName
,并使用length/2检查游戏失败。尝试根据这些提示编写代码。如果你仍然需要帮助,我将尝试给出建议…仍然memberchk
不起作用ing。该程序只是绕过列出memberchk
的谓词。我实际上想做的是,例如,如果单词中没有字母“n”,并且用户之前已经按下了该字母“n”,我想打印该消息,而不是增加计数器。我试图做的是:-动态(存储/1)存储区([])。已准备就绪的(猜测):-retract(存储区(L)),member(猜测,L),assert(存储区(L))。已准备就绪的(猜测):-retract(存储区(L)),not(成员(猜测,L)),assert(存储区([Guess | L]))。很抱歉,我不知道为什么上面的评论没有格式化。主要的想法是列出一个列表,我会把用户给的所有错误的字母都放在其中,然后每次他给了一个错误的字母,我都会先用错误的字母检查上面的列表,然后再检查所有其他的检查。对于所有这些问题,很抱歉,但这让我很困扰。我认为你应该将CountFailed
更改为一个列表:然后,不要添加,cons
失败的GuessName
,并使用length/2检查游戏失败。试着根据这些提示编写代码。如果你仍然需要帮助,我会尝试给出建议。。。