Possible Duplicate:
Hangman Game in SWI Prolog
我试图在 SWI Prolog 中用下面的 :
来安抚一个简单的玩家游戏:
< pronger@ em>1 > em/ strong >, 跟上迄今为止所猜到的“ 坚挺 " Whong < / strong > 字母。 如果用户猜到一个已经猜错的信, 程序应该说您猜到了! 并且继续游戏而不增加计数器 。
How can i put these predicates together so that my progam runs for the above enchancements?
1)
alreadyGuessed(Guess, AnsCodes) :-
memberchk(Guess, AnsCodes).
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)
).
What i tried to do is:
Extend the predicate getGuess(AnsList, BlankList, CountFailed)
<%% em> 在我修改前, 我提供代码和注释, 以及运行版本 。 em/ enge{% br/ >
Edit: Program now runs until you do 5 mistakes. Run it like ?- hangman(0).
Now i only need to NOT count the letters that have been used so far as wrong answers and display the appropriate message as listed above. Am i gonna do it by writting one more predicate 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.