Учебный Проект. Релиз 3: различия между версиями
м |
м |
||
Строка 686: | Строка 686: | ||
end implement humanInterface | end implement humanInterface | ||
</vip> | </vip> | ||
|enver= | |enver= | ||
[[en:Game Polyline. release 3]] | [[en:Game Polyline. release 3]] | ||
}} | }} |
Версия 13:44, 28 марта 2011
Автор: Виктор Юхтенко. Email victor@pdc.spb.su
Очередная версия Учебного проекта, функциональной идеей которого является простая игра.
Цель
Демонстрация свойств языка Visual Prolog и простейших приемов программирования, в том числе:
- принципы обмена информацией между классами и объектами;
- продвинутая система обработки исключений.
Функции
- Размер поля 6х6 точек.
- Игроков может быть более двух;
- Тип каждого игрока (компьютер, человек) выбирается;
- Ход может быть крайне неудачным, если компьютер не находит выигрышный ход.
Код
- Проверено на версии Visual Prolog 7.3 build 7302.
- Каждый класс несет определенную ролевую нагрузку, например,
- game - главный координатор приложения;
- human - модель игрока-человека;
- computer - модель игрока-компьютера;
- seniourJudge - старший судья, предоставляет право хода следующему игроку, ожидает информацию о завершении игры, объявляет победителя;
- juniourJudge - младший судья, принимает ход от игрока, проверяет соблюдение правил игры, определяет момент победы одного из игроков;
- humanInterface - представление хода игры человеку-пользователю и интерпретация его действий;
- В силу неэффективного алгоритма игры компьютера размер поля более 36 клеток (6x6, например) устанавливать не рекомендуется;
Установка
Если Вам нужен полный набор проектов серии Polyline (персональная версия), сгрузите и разархивируйте файлы архивов, пользуясь ссылками на форуме PDC ЗДЕСЬ
- VipSpbSDK_PE_73_Examples_Polyline_1_14.zip
- VipSpbSDK_PE_73_Tools_Polyline_1_14.zip]
в удобную для Вас директорию.
Коммерческая версия представлена в виде одного архива и может быть получена Здесь.
Оплата в любой из указанных валют. При оплате с рублевой кредитной карты валюта оплаты конвертируется в рубли по курсу банка-эмитента карты.
Директория с именем VipSpbSDK будет создана автоматически.
Если у Вас установлен VipSpbSDK, то следует открыть проект Examples\Polyline\Polyline1\Polyline3.prj
Если у Вас нет полного набора примеров из VipSpbSDK, то для помещения игры в проект необходимо:
- Создать проект с пользовательским интерфейсом типа console
- Построить проект
- В построенном проекте заменить полностью код файла "main.pro" кодом, предложенным ниже.
- Запустить вновь построение проекта. При построении проекта ответить на предложение о включении дополнительных пакетов в проект "Add All".
Запуск
Запуск приложения из среды по E или запустить исполняемое приложение из директории EXE.
/***************************************************************************** Copyright (c) Victor Yukhtenko SpbSolutions/Examples/Polyline Predicates, which represent the strategy neighbour_nd, neighbourOutOfPolyLine_nd, resolveStep, successfulStep, stepCandidate based on solutions proposed by Elena Efimova ********************************************/ goal mainExe::run(main::run). /************ Class Main ************/ implement main open core constants className = "main". classVersion = "1.0". clauses classInfo(className, classVersion). clauses run():- console::init(), game::run(). end implement main class game open core predicates classInfo : core::classInfo. predicates run:(). end class game implement game open core constants className = "game". classVersion = "1.0". clauses classInfo(className, classVersion). class facts playerNo_V:positive:=1. clauses run():- humanInterface::announceStartUp(), PlayerType=humanInterface::getInput(humanInterface::playerType_S,toString(playerNo_V)), not(PlayerType=""), try Player=createPlayerObject(toTerm(PlayerType)), seniourJudge::addPlayer(Player), playerNo_V:=playerNo_V+1 catch _TraceID do humanInterface::announceManagerError(humanInterface::errorPlayerType_S) end try, !, run(). run():- startingPlayer(). class predicates playListMember:()->string nondeterm. clauses playListMember()=PlayersListMember:- I = std::fromTo(1, list::length(seniourJudge::players_V)), Player=list::nth(I-1,seniourJudge::players_V), PlayersListMember=string::format("\n% - %",I,Player:name). class predicates startingPlayer:(). clauses startingPlayer():- not(seniourJudge::players_V=[]) and not(seniourJudge::players_V=[_SiglePlayer]), findAll(PlayListMember,PlayListMember=playListMember(),PlayList), PlayListStr=string::concatList(PlayList), StartingPlayerStr=humanInterface::getInput(humanInterface::startingPlayer_S,PlayListStr), not(StartingPlayerStr=""), try StartingPlayer=toTerm(StartingPlayerStr), !, startGame(StartingPlayer) catch _TraceID1 do humanInterface::announceManagerError(humanInterface::errorMustBeNumber_S), !, startingPlayer() end try. startingPlayer(). class predicates startGame:(positive). clauses startGame(StartingPlayer):- try Player=list::nth(StartingPlayer-1,seniourJudge::players_V), % list::nth(...) needs unsigned !, seniourJudge::play(Player) catch _Trace_D do humanInterface::announceManagerError(humanInterface::errorStartingPlayer_S), ! end try, !, startingPlayer(). class predicates createPlayerObject:(positive)->player. clauses createPlayerObject(1)=Player:- !, Player=human::new(). createPlayerObject(2)=Player:- !, Player=computer::new(). createPlayerObject(_)=_Player:- exception::raise(classInfo,wrongInputException,[]). class predicates wrongInputException:exception. clauses wrongInputException ( classInfo, predicate_Name(), "" ). end implement game /************************ Class seniorJudge ************************/ class seniourJudge open core properties players_V:player*. inProgress_V:boolean. predicates play:(player CurrentPlayer). addPlayer:(player NextPlayer). end class seniourJudge implement seniourJudge open core, humanInterface class facts players_V:player*:=[]. inProgress_V:boolean:=false. clauses play(Player):- inProgress_V=false, humanInterface::showStage(), inProgress_V:=true, Player:move(), humanInterface::announceStarter(Player:name), play(Player), !. play(Player):- juniourJudge::isGameOver(), !, Player:announceWin(), foreach (Participant=list::getMember_nd(players_V) and not(Participant=Player)) do Participant:announceLoss() end foreach, inProgress_V:=false, juniourJudge::reset(). play(Player):- NextPlayer=nextPlayer(Player), NextPlayer:move(), !, play(NextPlayer). clauses addPlayer(NextPlayer):- players_V:=list::append(players_V,[NextPlayer]). class predicates nextPlayer:(player CurrentPlayer)->player NextPlayer. clauses nextPlayer(Player)=NextPlayer:- Index=list::tryGetIndex(Player,players_V), NextPlayer=list::tryGetNth(Index+1,players_V), !. nextPlayer(_Player)=list::nth(0,players_V). end implement seniourJudge /************************ Class juniourJudge ************************/ class juniourJudge open core predicates classInfo : core::classInfo. domains cell = c(positive,positive). stepType_D= ordinary_S; winner_S. properties maxRow_P:positive. maxColumn_P:positive. polyline_P:cell*. predicates neighbour_nd: (cell,cell) nondeterm (i,o) (i,i). neighbourOutOfPolyLine_nd:(cell,cell)->cell nondeterm. set: (string ). isGameOver:() determ. reset:(). end class juniourJudge implement juniourJudge open core, humanInterface constants className = "JuniourJudge". classVersion = "1.0". clauses classInfo(className, classVersion). class facts maxRow_P:positive:=6. maxColumn_P:positive:=6. polyline_P:cell*:=[]. endOfGame_V:boolean:=false. clauses isGameOver():- endOfGame_V=true. clauses set(InputString):- Cell=toTerm(InputString), handleInput (Cell). clauses reset():- juniourJudge:: polyline_P:=[], juniourJudge::endOfGame_V:=false. class predicates handleInput:(juniourJudge::cell). clauses handleInput(Cell):- list::isMember(Cell,polyline_P), try _=makePolyLine(Cell,polyline_P) % it will be an exception if wrong Cell, but we ignore it by failing catch _TraceID do fail end try, !, endOfGame_V:=true, humanInterface::showStep(Cell,winner_S). handleInput (Cell):- polyline_P:=makePolyLine(Cell,polyline_P), !, humanInterface::showStep(Cell,ordinary_S). class predicates makePolyLine: (cell,cell*)-> cell* multi. clauses makePolyLine(c(X,Y),[])=[c(X,Y)]:- X>0,X<=maxColumn_P, Y>0,Y<=maxRow_P, !. makePolyLine(NewCell,[SingleCell])=[NewCell,SingleCell]:- neighbour_nd(SingleCell, NewCell), !. makePolyLine(NewCell,[Left, RestrictingCell | PolyLineTail])=[NewCell, Left, RestrictingCell | PolyLineTail]:- NewCell=neighbourOutOfPolyLine_nd(Left,RestrictingCell). makePolyLine(NewCell,PolyLine)=list::reverse([NewCell,Left, RestrictingCell | PolyLineTail]):- [Left, RestrictingCell | PolyLineTail]= list::reverse(PolyLine), NewCell=neighbourOutOfPolyLine_nd(Left,RestrictingCell). makePolyLine(NewCell,_PolyLine)= _PolyLine1:- exception::raise(classInfo,wrongStepException,[namedValue("data",string(toString(NewCell)))]). class predicates wrongStepException:exception. clauses wrongStepException ( classInfo, predicate_Name(), "the point % can not prolong the polyline!" ). clauses neighbourOutOfPolyLine_nd(Cell,RestrictingCell)=NewCell:- neighbour_nd(Cell,NewCell), not(NewCell = RestrictingCell). clauses neighbour_nd(c(X, Y), c(X + 1, Y)):- X < maxColumn_P. neighbour_nd(c(X, Y), c(X, Y + 1)):- Y < maxrow_P. neighbour_nd(c(X, Y), c(X - 1, Y)):- X > 1. neighbour_nd(c(X, Y), c(X, Y - 1)):- Y > 1. end implement juniourJudge /****************************************** Interface Player ******************************************/ interface player predicates move:(). announceWin:(). announceLoss:(). properties name:string. end interface player /****************************************** Class human ******************************************/ class human:player open core end class human implement human open core facts name:string:=string::format("Hum_%",toString(This)). clauses new():- Name=humanInterface::getInput(humanInterface::playerName_S,name), if not(Name="") then name:=Name end if. clauses move():- InputString=humanInterface::getInput(humanInterface::playerStep_S), try juniourJudge::set(InputString) catch TraceID do handleException(TraceID), fail end try, !. move():- move(). clauses announceWin():- humanInterface::announceWin(name). announceLoss():- humanInterface::announceLoss(name). class predicates handleException:(exception::traceId TraceID). clauses handleException(TraceID):- foreach Descriptor=exception::getDescriptor_nd(TraceID) do Descriptor = exception::descriptor( _ClassInfo1, exception::exceptionDescriptor(_ClassInfo2,_PredicateName,Description), _Kind, ExtraInfo, _GMTTime, _ExceptionDescription, _ThreadId), if ExtraInfo=[namedValue("data",string(CellPointer))] then ErrorMsg=string::format(Description,CellPointer), humanInterface::announceError(ErrorMsg) else humanInterface::announceError("") end if end foreach. end implement human /****************************************** Class computer ******************************************/ class computer:player open core end class computer implement computer open core facts name:string:=string::format("Cmp_%",toString(This)). clauses new():- Name=humanInterface::getInput(humanInterface::playerName_S,name), if not(Name="") then name:=Name end if. clauses move():- humanInterface::announceThinker(name), Cell=resolveStep(), juniourJudge::set(toString(Cell)). predicates resolveStep:()->juniourJudge::cell. clauses resolveStep()=Cell:- Cell=successfulStep(juniourJudge::polyline_P), !. resolveStep()=Cell:- stepCandidate(juniourJudge::polyline_P,_PolyLine,Cell), !. resolveStep()=juniourJudge::c(X+1,Y+1):- X=math::random(juniourJudge::maxColumn_P-1), Y=math::random(juniourJudge::maxRow_P-1). class predicates successfulStep: (juniourJudge::cell*)->juniourJudge::cell nondeterm. clauses successfulStep(PolyLine)=Cell:- stepCandidate(PolyLine,_PolyLine1,Cell), list::isMember(Cell, PolyLine), !. successfulStep(PolyLine)=Cell:- stepCandidate(PolyLine, PolyLine1, Cell), not(_=successfulStep(PolyLine1)). class predicates stepCandidate: (juniourJudge::cell*,juniourJudge::cell* [out],juniourJudge::cell [out]) nondeterm. clauses stepCandidate([Cell],[Cell,NewCell], NewCell):- juniourJudge::neighbour_nd(Cell, NewCell). stepCandidate([Left, RestrictingCell | PolyLine],[NewCell,Left, RestrictingCell| PolyLine], NewCell):- NewCell=juniourJudge::neighbourOutOfPolyLine_nd(Left,RestrictingCell). stepCandidate(PolyLine,list::reverse([NewCell,Left, RestrictingCell |PolyLineTail]),NewCell):- [Left, RestrictingCell |PolyLineTail] = list::reverse(PolyLine), NewCell=juniourJudge::neighbourOutOfPolyLine_nd(Left,RestrictingCell). clauses announceWin():- humanInterface::announceWin(name). clauses announceLoss():- humanInterface::announceLoss(name). end implement computer /****************************************** Class HumanInterface ******************************************/ class humanInterface open core predicates announceStartUp:(). predicates showStage:(). showStep:(juniourJudge::cell,juniourJudge::stepType_D). getInput:(inputType_D,string StringParameter)->string InputString. getInput:(inputType_D)->string InputString. predicates announceManagerError:(choiceError_D). predicates announceStarter:(string Name). announceThinker:(string Name). announceWin:(string Name). announceLoss:(string Name). announceError:(string Description). announceError:(). domains choiceError_D= errorPlayerType_S; errorMustBeNumber_S; errorstartingPlayer_S. domains inputType_D= playerStep_S; playerType_S; playerName_S; startingPlayer_S. end class humanInterface implement humanInterface open core constants cellMarkedOrdinary_C="*". cellMarkedWinner_C="O". constants % messages thinker_C="% is thinking ...". beginner_C="First move done by: %". error_C="Error, % ". congratulation_C="Player % won!". sorryLoss_C="%, Sorry, you loss :-(". playerStep_C="Please enter your move as c(X,Y): ". playerType_C="\nPlayer #%s. Please enter the player type (1-human, 2-computer, Enter - end of choice):". playerName_C="\nPlease assign the name to the player (% proposed):". startingPlayer_C="\nWho moves the first (PlayerNo or Enter - end of the game)?:". errorPlayerType_C="\nNo such player type exists! Enter - repeat input:". errorMustBeNumber_C="\nMust be number! Please repeat input:". errorstartingPlayer_C="\nNo such Player exiasts! Please repeat input:". constants verticalSpace_C=2. horizontalSpace_C=3. emptyLineLenght_C=80. constants % Position of Line starterLine_C=1. announceLine_C=starterLine_C+1. actionLine_C=announceLine_C+1. polylineLine_C=actionLine_C+1. clauses getInput(InputType)=Input:- Input=getInput(InputType,""). getInput(InputType,StringParameter)=Input:- inputInvitation(InputType,StringParameter), Input = console::readLine(), console::clearInput(). class predicates inputInvitation:(inputType_D,string StringParameter). clauses inputInvitation(playerStep_S,_StringParameter):- clearMessageArea(actionLine_C), writeMessage(actionLine_C,"%",playerStep_C). inputInvitation(playerName_S,StringParameter):- console::writef(playerName_C,StringParameter). inputInvitation(playerType_S,StringParameter):- console::writef(playerType_C,StringParameter). inputInvitation(startingPlayer_S,StringParameter):- console::write(StringParameter,startingPlayer_C). clauses showStage():- console::clearOutput(), foreach I = std::fromTo(1, juniourJudge::maxColumn_P) do console::setLocation(console_native::coord(horizontalSpace_C*I, 0)), console::write(I) end foreach, foreach J = std::fromTo(1, juniourJudge::maxRow_P) do console::setLocation(console_native::coord(0, verticalSpace_C*J)), console::write(J) end foreach. clauses showStep(juniourJudge::c(X,Y),_Type):- console::setLocation(console_native::coord(horizontalSpace_C*X, verticalSpace_C*Y)), fail. showStep(_Cell,juniourJudge::ordinary_S):- console::write(cellMarkedOrdinary_C). showStep(_Cell,juniourJudge::winner_S):- console::write(cellMarkedWinner_C). clauses announceStartUp():- console::clearOutput(). clauses announceStarter(Name):- clearMessageArea(starterLine_C), writeMessage(starterLine_C,beginner_C,Name). clauses announceManagerError(errorPlayerType_S):- console::write(errorPlayerType_C), _=console::readLine(). announceManagerError(errorMustBeNumber_S):- console::write(errorMustBeNumber_C). announceManagerError(errorstartingPlayer_S):- console::write(errorstartingPlayer_C). clauses announceError():- announceError(""). announceError(ErrorText):- clearMessageArea(announceLine_C), writeMessage(announceLine_C,error_C,ErrorText). clauses announceWin(Name):- clearMessageArea(announceLine_C), writeMessage(announceLine_C,congratulation_C,Name), showPolyLine(), _ = console::readLine(). announceLoss(Name):- clearMessageArea(announceLine_C), writeMessage(announceLine_C,sorryLoss_C,Name), showPolyLine(), _ = console::readLine(). clauses announceThinker(Name):- clearMessageArea(announceLine_C), clearMessageArea(actionLine_C), writeMessage(actionLine_C,thinker_C,Name). class predicates showPolyLine:(). clauses showPolyLine():- clearMessageArea(actionLine_C), writeMessage(polylineLine_C,"%",toString(juniourJudge::polyline_P)). class predicates clearMessageArea:(positive AreaID). clauses clearMessageArea(AreaID):- console::setLocation(console_native::coord(0,juniourJudge::maxRow_P*verticalSpace_C+AreaID)), console::write(string::create(emptyLineLenght_C," ")). class predicates writeMessage:(positive AreaID,string FormatString,string ParameterString). clauses writeMessage(AreaID,FormatString,ParameterString):- console::setLocation(console_native::coord(0, juniourJudge::maxRow_P*verticalSpace_C+AreaID)), console::writef(FormatString,ParameterString). end implement humanInterface