Опубликован: 12.02.2014 | Уровень: для всех | Доступ: платный
Лекция 15:

Экспертная система. Логическая задача. Фейерверк

< Лекция 14 || Лекция 15: 123 || Лекция 16 >

15.3. Новогодний фейерверк

В следующей программе моделируется фейерверк. Она представляет собой анимационную поздравительную открытку (рис. 15.1).

 Новогодний фейерверк

Рис. 15.1. Новогодний фейерверк

На фоне праздничного фейерверка появляются поздравительные надписи, выбранные случайным образом. Цвет надписей и цвет каждого элемента фейерверка также выбирается случайным образом. На каждую надпись приходится три залпа. Местоположение фейерверка и надписи выбирается случайным образом перед каждым залпом. Перед появлением или исчезновением каждого элемента фейерверка делается небольшая пауза. Поток залпов и поздравлений прекращается после щелчка левой кнопкой мыши в окне консоли.

open core, console, console_native, math, list, programControl

constants
    % Congratulation-phrases for random choice
    phraseList : string* =
        [
            "Счастливого Нового Года и Рождества!",
            "From Russia with love!",
            "Vivat Visual Prolog!",
            "We wish you a Merry Christmas and a happy New Year!",
            "Joyeux Noёl et bonne Annee!",
            "Frohe Weihnachten und ein gutes neues Jahr!",
            "Buon Natale e felice Anno Nuovo!",
            "Feliz Navidad y Prospero Ano Nuevo!",
            "Glaedelig Jul og Godt Nytar!",
            "Kurisumasu Omedeto!",
            "Natale hilareet Annum Faustum!"
         ].
    % Symbols that will be randomly used for building a firework
    symbolList : string* = ["*", "+", "x"].

class facts
    xp : unsigned16 := 28.
    yp : unsigned16 := 37.
    phrase : string := "".
    n : positive := 3.

class predicates
    ellipse: (integer Rx, integer Ry, integer XCent, integer YCent,
        string Symbol, positive Sleep).
    arc: (integer Rx, integer Ry, integer XCent, integer YCent,
        real PercentBeg, real PercentEnd, string Symb, positive Sleep).
    line: (coord P1, coord P2, string, positive Sleep).
    print: (string Symbol).
    stop: () determ.
clauses
    print(Symbol):-
        setTextAttribute(math::random(7) + 9),
        write(Symbol).

    % drawing an ellipse with the center in (XCent; YCent)
    ellipse(Rx, Ry, XCent, YCent, Symbol, Sleep):-
        arc(Rx, Ry, XCent, YCent, 0, 1, Symbol, Sleep).

    % drawing an arc with the center in (XCent; YCent)
    arc(Rx, Ry, XCent, YCent, PercentBeg, PercEnd, Symb, Sleep):-
        X = std::downTo(round(PercEnd *31), round(PercentBeg *31)),
            Angle = (2 * pi) * (X / 32),
            XCur = round(XCent + Rx * cos(Angle)),
            YCur = round(YCent - Ry * sin(Angle)),
            setLocation(coord(XCur + 0, YCur + 0)),
            print(Symb),
            sleep(Sleep),
        fail;
        succeed().

    % Drawing a vertical line
    line(coord(X, Y1), coord(X, Y2), Symbol, Sleep):- !,
        (Y = std::fromTo(Y1, Y2),
            setLocation(coord(X, Y)),
            print(Symbol),
            sleep(Sleep),
        fail;
        succeed()).
    % Drawing a non-vertical line
    line(coord(X1, Y1), coord(X2, Y2), Symbol, Sleep):-
        X = std::between(X1, X2),
            Y = round(Y1 + (X - X1) * (Y2 - Y1) / (X2 - X1)),
            setLocation(coord(X, Y + 0)),
            print(Symbol),
            sleep(Sleep),
        fail;
        succeed().

    stop():-
        L = getEventQueue(),
        mouse(_, _, 1, _, 0) = getMember_nd(L),
        !.

% Drawing a firework using random symbols from the list
% and replacing the firework by that of blank spaces
constants
% Parametres for 7 branches of the firework
    startx : integer* = [42, 38, 42, 38, 41, 39, 39].
    starty : integer* = [20, 20, 18, 18, 21, 21, 18].
    vx : integer* = [7, -6, 4, -3, 5, -5, -2].
    vy : integer* = [7, 7, 9, 9, 5, 5, 11].
class facts
    parametres : tuple{integer, integer, integer, integer}* :=
        zip(startx, starty, vx, vy).

class predicates
    printPoint: (real X0, real Xspeed, real T, real Y0, real Yspeed, 
        real G, string Symbol).
    firework: (boolean IsDrawing, real X0, real Y0, real G,
        positive Sleep, string Symbol, positive SymbolListLength).
    getSymbol: (boolean IsDrawing, string Symbol, positive) -> string.
clauses
    /* Calculation of the trajectory of a thrown object (symbol) for
        forming a firework line. The object is thrown at certain angle
        and falls with free-fall acceleration G */
    printPoint(X0, Xspeed, T, Y0, Yspeed, G, Symbol):-
        X = round(X0 + XSpeed * T),
        Y = round(Y0 - (YSpeed * T - G * T ^ 2/2)),
        setLocation(coord(X + 0, Y + 0)),
        print(Symbol).

    firework(IsDrawing, Xc, Yc, G, Sleep, Symbol, N):-
        I = std::fromTo(0, 29),
            forAll(parametres, {(tuple(Cx, Cy, Vx, Vy)):-
                printPoint(Cx - Xc, Vx, I * 0.1, Cy + Yc, Vy, G,
                                getSymbol(IsDrawing, Symbol, N))}),
            sleep(Sleep),
        fail;
        succeed().

    getSymbol(true, _, N) = nth(random(N), symbolList):- !.
    getSymbol(_, Symbol, _) = Symbol.

    run():-
        FSleep = 15,
        setConsoleTitle("Happy New Year"),
        %A circle that will contain the characters
        ellipse(22, 11, 40, 12, "*", 0),
        vpi::alarm(2),
        % Three
         arc(7, 4, 40, 7, -0.25, 0.40, "$", FSleep),
         arc(9, 5, 40, 16, -0.43, 0.25, "$", FSleep),
         sleep(750),
        % Erasing 'three'
        % To erase something we replace it by the same figure
        % formed by blank spaces
        arc(7, 4, 40, 7, -0.25, 0.40, " ", FSleep),
        arc(9, 5, 40, 16, -0.43, 0.25, " ", FSleep),
        vpi::alarm(2),
        % Two
        arc(7, 4, 40, 7, -0.1, 0.50, "$", FSleep),
        line(coord(46, 9), coord(34, 18), "$", FSleep),
        line(coord(33, 19), coord(48, 19), "$", FSleep),
        sleep(750),
        % Erasing 'two'
        arc(7, 4, 40, 7, -0.1, 0.50, " ", FSleep),
        line(coord(46, 9), coord(34, 18), " ", FSleep),
        line(coord(33, 19), coord(48, 19), " ", FSleep),
        vpi::alarm(2),
        % One
        line(coord(33, 11), coord(43, 5), "$", FSleep),
        line(coord(43, 6), coord(43, 19), "$$", FSleep),
        sleep(750),
        % Erasing 'one'
        line(coord(33, 11), coord(43, 5), " ", FSleep),
        line(coord(43, 6), coord(43, 19), "  ", FSleep),
        vpi::alarm(2),
        % Zero
        ellipse(11, 7, 40, 12, "$$", FSleep),
        sleep(200),
        % Erasing 'zero'
        ellipse(11, 7, 40, 12, "  ", 0),
        % Erasing the initial circle
        ellipse(22, 11, 40, 12, " ", 0),

        LengthOfPhraseList = length(phraseList),
        LengthOfSymbolList = length(symbolList),
        vpi::alarm(3),
        I = varM::new(0),
        /* The cycle that draws fireworks and writes random
            congratulation-phrases in a random place */
        std::repeat(),
            Xc = random(11),
            Yc = random(5),
            G = 4 + random(3),
            /* The first time a congratulation-phrase appears
                (all in all one phrase exists during three fireworks) */
            if I:value = 0 then
                setLocation(coord(xp, yp)),
                phrase := nth(n, phraseList)
            end if,
             /* The last time the current phrase appears; it is replaced
                  by a string of blank spaces. Then new random location is
                  chosen and a new congratulation-phrase is written */
            if I:value mod 3 = 0, I:value > 0 then
                setLocation(coord(xp, yp)),
                write(string::create(55, " ")),
                phrase := nth(n, phraseList),
                xp :=random(getConsoleWidth() - string::length(phrase)),
                yp := random(30),
                setLocation(coord(xp, yp)),
                write(phrase)
            % Not the first or the last time the current phrase appears
            else
                setLocation(coord(xp, yp)),
                write(phrase)
            end if,
            I:value := I:value + 1,
            n := random(LengthOfPhraseList),
            % Drawing a firework
            firework(true, Xc, Yc, G, 30, "", LengthOfSymbolList),
            % Erasing the firework
            firework(false, Xc, Yc, G, 3, " ", 0),
        stop(),
        !,
        _ = readLine();
        succeed().
Пример 15.4. Поздравительная открытка

В упражнениях 6 – 9 требуется написать программу, которая решает логическую задачу.

Упражнения

  1. Реализуйте такой вывод в экспертной системе, чтобы система начинала с опроса сведений о признаках животного, и при наличии необходимого набора признаков у какого-либо животного, сразу выдавала бы заключение.
  2. Создайте экспертную систему по определению видов растений.
  3. Создайте экспертную систему по выбору места летнего отдыха.
  4. Создайте экспертную систему по выбору книг для отпуска.
  5. Создайте экспертную систему по выбору направления обучения для абитуриента.
  6. Мартовский Заяц заявил, что муку украл Болванщик. Что сказали Болванщик и Соня, записано не было. Однако выяснилось, что муку украл лишь один из этих троих и что только он сказал правду. Кто украл муку?
  7. Мартовский Заяц сообщил, что масло украл Болванщик. Болванщик сказал, что яйца украла Соня. Соня сказала, что она украла молоко. Каждый из них украл что-то одно. Выяснилось, что тот, кто украл масло, говорил правду, а тот, кто украл яйца, лгал. Кто что украл?
  8. Тройка думает, что Туз не в своем уме. Четверка думает, что Тройка и Двойка обе не могут быть не в своем уме. Пятерка думает, что Туз и Четверка либо оба не в своем уме, либо оба в здравом рассудке. Шестерка думает, что Туз и Двойка оба в здравом уме. Семерка думает, что Пятерка не в своем уме. Валет Червей думает, что Шестерка и Семерка не обе не в своем уме. В своем ли уме Валет Червей?
  9. На одном международном конгрессе встретились четыре делегата из разных стран. Каждый из них владел двумя языками из четырех — английским, французским, немецким и итальянским. Оказалось, что не было такого языка, на котором они могли говорить вчетвером, и был только один язык, на котором могли говорить трое из них. Никто из делегатов не владеет французским и немецким языками одновременно. Хотя физик не говорит по-английски, он может служить переводчиком, если математик и биолог захотят поговорить друг с другом. Биолог говорит по-немецки и может говорить с химиком, хотя тот не знает ни одного немецкого слова. Физик, математик и химик не могут беседовать втроем на одном языке. Какими двумя языками владеет каждый из этих делегатов ?
  10. Измените программу "Фейерверк" (листинг 15.4) так, чтобы почти одновременно производилось по 2-3 залпа с разным числом "ветвей".
< Лекция 14 || Лекция 15: 123 || Лекция 16 >
Жаныл Айкын
Жаныл Айкын
Rustam Inatov
Rustam Inatov

Доброго времени суток, подскажите пожалуйста, visual prolog examples, pie, vip7.5 - это все, где я могу скачать? (в смысле) может быть на сайте есть какой-то архив? Увы я не нашел его.

Подскажите, пожалуйста.

С уважением, Рустам.

Айдана Ахметова
Айдана Ахметова
Россия
Дмитрий Куянов
Дмитрий Куянов
Россия, Омск, ОмГТУ