Опубликован: 12.02.2014 | Доступ: свободный | Студентов: 819 / 236 | Длительность: 11:22:00
Специальности: Программист
Лекция 14:

Игры

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

14.3. Игра "Отгадай числа"

"Отгадай числа" — это игра для двух участников, которая состоит в следующем. Игроки загадывают по n целых чисел в пределах от 0 до 9 включительно, числа не повторяются. Цель игры — найти набор чисел, который загадал противник. Порядок чисел в наборе значения не имеет. Участник называет n чисел. Если среди них более половины совпадают с числами, загаданными противником, то право хода остается за ним. В противном случае ход переходит к другому игроку. Побеждает игрок, который первым правильно назовет весь набор чисел, загаданный противником. Данная игра является одним из вариантов игры "Быки и коровы" [9], в котором имеются только "коровы".

Приведенная ниже программа — это реализация игры человека с компьютером. Значение n запрашивается у пользователя. Компьютер загадывает набор n попарно-различных случайных чисел. Пользователь вводит числа через пробел. Первым ходит компьютер.

    open core, console, list

constants
    diglist : unsigned* = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0].

class facts
    num: (unsigned, unsigned*, positive).
    digs : unsigned* := [].
    n : positive := 0.
class predicates
    readDigits: (positive) -> unsigned*.
    add: (unsigned, unsigned*, unsigned* [out], positive, 
        positive [out]).
    gen: (positive, unsigned) -> unsigned*.
    gen: (positive, unsigned, unsigned*) -> unsigned*.
    count: (unsigned*, unsigned*) -> positive.
    f: (positive) -> string.
clauses
    readDigits(N) = reverse(digs):-
        writef("Введите % % от 0 до 9 через пробел: > ", N, f(N)),
        digs := [], n := N,
        std::repeat(),
            try hasDomain(unsigned, X), X = read()
            catch _ do
                clearInput(), write("\nПовторите попытку: > "), fail
            end try,
            add(X, digs, L, n, N1),
            digs := L, n := N1,
        n = 0,
        clearInput(),
        !.
    readDigits(_) = [].

    f(N) = "чисел":-
        N > 4,
        !.
    f(_) = "числа".

    gen(N, R) = reverse(gen(N, R, [])).

    gen(N, R, L) = gen(N1, R, L1):-
        N > 0,
        !,
        add(math::random(R), L, L1, N, N1).
    gen(_, _, L) = L.

    add(X, L, [X | L], N, N - 1):-
        X < 10,
        not(isMember(X, L)),
        !.
    add(_, L, L, N, N).

    count(L, L1) = length(filter(L, {(X):- isMember(X, L1)})).

class predicates
    game: (positive).
    game: (positive, unsigned, unsigned*, unsigned*).
    game: (positive, unsigned, unsigned*, unsigned*, positive).
    move: (unsigned, positive) -> unsigned*.
    writeMessage: (unsigned, unsigned*, unsigned*).
    writeVariants: (unsigned).
    subset: (positive, unsigned*) -> unsigned* nondeterm.
    candidate: (positive) -> unsigned* nondeterm.
    isBad: (unsigned*) determ.
    toStr: (unsigned) -> string.
clauses
    subset(0, _) = []:- !.
    subset(N, [X | L]) = [X | subset(N - 1, L)].
    subset(N, [_ | L]) = subset(N, L).

    candidate(N) = L:-
        L = subset(N, diglist),
        not(isBad(L)).

    isBad(L):-
        num(0, L1, N),
        N <> count(L, L1),
        !.

    writeVariants(X):-
        num(X, L, N),
            write(L, " - ", N), nl,
        fail;
        succeed().

    game(N):-
        writef("Загадайте % различных чисел от 0 до 9\n", N),
        L = readDigits(N),
        write("\nНачинается игра\n"),
        game(N, 0, gen(N, length(diglist) + 0), L).

    game(N, X, L, L1):-
        L2 = move(X, N),
        K = count(L1, L2),
        write(L2, " - ", K), nl,
        assert(num(X, L2, K)),
        game(N, X, L, L1, K).

    game(N, X, L, L1, N):- !,
        writeMessage(X, L, L1).
    game(N, X, L, L1, K):-
        K > N div 2,
        !,
        game(N, X, L, L1).
    game(N, X, L, L1, _):-
        game(N, 1 - X, L1, L).

    move(0, N) = L:-
        write("\nХод компьютера\n"),
        L = candidate(N),
        !.
    move(_, N) = readDigits(N):-
        write("\nВаш ход\n"),
        writeVariants(1).

    toStr(0) = "компьютер":- !.
    toStr(_) = "человек".

    writeMessage(X, L, L1):-
        Player1 = toStr(X),
        Player2 = toStr(1 - X),
        writef("Выиграл %!\n% задумал %, % задумал %.\n",
            Player1, Player1, L, Player2, L1).

    run():-
        write("Количество угадываемых чисел: "),
        N = read(), clearInput(),
        game(N),
        _ = readLine().
Пример 14.3. Игра "Отгадай все числа"

Упражнения

  1. Реализуйте вариант топологической игры "Ползунок", в котором игрок, замкнувший траекторию, проигрывает, а не выигрывает.
  2. Реализуйте игру "Поле чудес" в режиме "пользователь загадывает, компьютер отгадывает".
  3. Реализуйте игру "Быки о коровы" в режимах

    • пользователь загадывает, компьютер отгадывает;
    • компьютер загадывает, пользователь отгадывает;
    • загадывают оба, выигрывает тот, кто отгадает первым.
  4. Реализуйте игру "Крестики-нолики" пользователя с компьютером.
  5. Реализуйте игру в камни пользователя с компьютером. Имеется груда камней. За один ход можно взять от одного до трех камней. Игроки ходят по очереди. Проигрывает тот, кто берет последний камень.
  6. Игра "Ним" заключается в следующем. Имеется n кучек, в которых лежат камни. Игроки ходят по очереди. За один ход игрок может взять любое ненулевое число камней из произвольной кучки. Напишите программу для игры пользователя с компьютером, в которой игрок, взявший последний камень

    • выигрывает;
    • проигрывает.
  7. Реализуйте игру в баллы пользователя с компьютером. Компьютер запрашивает число n баллов, которые нужно набрать (например 20), а также несколько чисел, которые можно называть (например 2, 5, 6) и имя игрока, который ходит первым. Игроки по очереди называют одно из разрешенных чисел. Названные числа суммируются. Выигрывает участник, после хода которого сумма становится равной n или вынудивший противника превысить это число.
  8. Реализуйте игру в 37 пользователя с компьютером. Игроки по очереди называют одно из чисел от 1 до 5, названные числа суммируются. Нельзя повторять число, которое назвал противник на предыдущем ходе. Выигрывает участник, получивший ровно 37 очков или вынудивший противника превысить это число.
< Лекция 13 || Лекция 14: 123 || Лекция 15 >
Жаныл Айкын
Жаныл Айкын
Rustam Inatov
Rustam Inatov

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

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

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