2012-05-25 106 views
1

可能重複:
Hangman Game in SWI Prolog劊子手遊戲在SWI序言(Enchance)

我想enchance一個簡單的劊子手遊戲在SWI Prolog的有以下幾點:

1)通過跟上錯誤迄今爲止猜到的字母。如果用戶猜到一封已經被猜測錯誤的信件,程序應該說'你猜對了!'只要繼續遊戲而不增加櫃檯。

2)最後,添加計數不正確猜測的數量,達到一定數量時退出比賽的計數器。該程序應告訴用戶他們輸了,顯示該短語的真實含義,並終止。重複的猜測不應該算作錯誤。

我怎樣才能把這些謂詞放在一起,讓我的程序運行上述增強?
1)

alreadyGuessed(Guess, AnsCodes) :- 
    memberchk(Guess, AnsCodes). 

2)

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) 
). 

什麼我試圖做的是:
擴展謂詞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. 
+0

人誰可以幫助我解決問題1? – Kostas

回答

1

插入之前processGuess(AnsList, BlankList, _, CountFailed) :-

processGuess(AnsList, BlankList, Guess, CountFailed):- 
    memberchk(Guess, BlankList), 
    write('You guessed that!'), nl, 
    !, getGuess(AnsList, BlankList, CountFailed). 

這個規則,我把內嵌從alreadyGuessed唯一的呼叫

編輯要改變CountFailed到FailedList:

processGuess(AnsList, BlankList, Guess, FailedList):- 
    ( length(FailedList, 5) 
    -> ... signal game failure and stop ... 
    ; getGuess(AnsList, BlankList, [Guess|FailedList]) 
    ) 
+0

仍然'memberchk'不起作用。該程序只是繞過「memberchk」列出的謂詞。 我真正想要做的是,如果例如在單詞中沒有字母「n」,並且用戶之前已經按下了該字母「n」,我想要打印他那條消息而不增加計數器。我試圖做的事: :-dynamic(store/1) store([])。 (Guess,L), assert(store(L))。 alreadyGuessed(猜測): - 退(店(L)), 不是(會員(猜,L)), 斷言(店([猜猜| L]) – Kostas

+0

對不起,我不知道。爲什麼它沒有格式化上面的評論 – Kostas

+0

主要想法是製作一個列表,我會把所有錯誤的信件給用戶,然後每次他給出一個錯誤的信件我會首先用錯誤的字母檢查上面的列表,然後所有其他的檢查,對所有這些問題抱歉,但這很麻煩我現在有一段時間 – Kostas