В настоящей главе в консоли реализуются игры "Ползунок", "Поле чудес" и "Отгадай числа". В топологической игре "Ползунок" пользователь играет с компьютером. Поле для игры невелико, поэтому выигрышные ходы, в случаях, когда они существуют, находятся с помощью перебора возможных продолжений игры. В игре "Поле чудес" пользователь отгадывает слово, загаданное компьютером. "Отгадай числа" — это игра пользователя с компьютером, в которой участники отгадывают наборы чисел, загаданные противниками. Стратегия компьютера реализуется с помощью генерации варианта хода и отбрасывания вариантов, которые не согласуются с релультатами предыдущих ходов компьютера.
Топологическая игра "Ползунок" заключается в следующем. Игра ведется на решетке размером 5 на 6 клеток (рис. 14.1).
(рис 14.1) Партия топологической игры "Ползунок"
Участники ходят по очереди. Игрок проводит отрезок прямой длиной в одну клетку, достраивая ломаную с одного из концов. Получающаяся траектория (ломаная) должна быть непрерывной, причем ход можно делать с любого ее конца. Игрок, который замыкает траекторию, т. е. ходит так, что попадает одним из концов отрезка на ломаную, выигрывает. На рис 14.1 показана позиция, выигрышная для первого игрока (он проводит отрезки светлым карандашом). Ходом в клетку (1; 3) этот игрок замыкает траекторию.
Приведенная ниже программа — это реализация игры человека с компьютером. Для поиска выигрышной стратегии компьютера используется метод ван Эмдена (в [5, 14] он применяется в игре "Ним"): игрок делает выигрышный ход (замыкает траекторию) или ходит так, чтобы его противник не выиграл. Если противник (человек) не знает, каким образом нужно ходить, чтобы выиграть, то компьютер в результате обязательно выигрывает. Если же компьютер находится в проигрышной позиции и не может найти такой ход, то он пытается сходить так, чтобы его противник не выиграл на следующем же шаге. Если противник ошибется хотя бы один раз и не сделает правильный ход, то компьютер выиграет.
open core, console, console_native
class facts
humanCell: (coord).
class predicates
winMove: (positive, positive, coord*, coord*) nondeterm (i,i,i,o).
step: (coord*, coord*, coord) nondeterm (i,o,o) (i,o,i).
next: (coord, coord) nondeterm (i,o) (i,i).
move: (positive, coord*).
show: (coord*).
loseMove: (coord*) determ.
clauses
loseMove(Polyline):-
step(Polyline, _, Cell),
list::isMember(Cell, Polyline),
!.
winMove(_Player1, _Player2, Polyline, Polyline1):-
step(Polyline, Polyline1, Cell),
list::isMember(Cell, Polyline).
winMove(Player1, Player2, Polyline, Polyline1):-
step(Polyline, Polyline1, _),
not(winMove(Player2, Player1, Polyline1, _)).
move(2, Polyline):-
step(Polyline, Polyline1, Cell),
list::isMember(Cell, Polyline),
!,
show(Polyline1),
setLocation(coord(0, 14)),
write("Компьютер выиграл!\n\n", Polyline1).
move(2, Polyline):-
winMove(2, 1, Polyline, Polyline1),
!,
move(1, Polyline1).
move(2, Polyline):-
step(Polyline, Polyline1, _),
not(loseMove(Polyline1)),
!,
move(1, Polyline1).
move(2, Polyline):-
step(Polyline, Polyline1, _),
!,
move(1, Polyline1).
move(1, Polyline):-
show(Polyline),
setLocation(coord(0, 14)),
write(Polyline),
std::repeat(),
write("\n\nВаш ход.\nВведите новую клетку в виде"
" coord(2,3): "),
hasDomain(coord, Cell),
Cell = read(), clearInput(),
step(Polyline, Polyline1, Cell),
assert(humanCell(Cell)),
!,
if list::isMember(Cell, Polyline) then
write("\nПоздравляю! Вы выиграли!")
else
move(2, Polyline1)
end if.
move(_, _).
step([A, B | Polyline], [X, A, B | Polyline], X):-
next(A, X),
not(X = B).
step(Polyline, list::append(Polyline, [X]), X):-
[A, B | _] = list::reverse(Polyline),
next(A, X),
not(X = B).
next(coord(X, Y), coord(X - 1, Y)):- X > 1.
next(coord(X, Y), coord(X + 1, Y)):- X < 6.
next(coord(X, Y), coord(X, Y - 1)):- Y > 1.
next(coord(X, Y), coord(X, Y + 1)):- Y < 5.
show(Polyline):-
clearOutput(),
foreach I = std::fromTo(1, 6) do
setLocation(coord(3 * I, 0)), write(I)
end foreach,
foreach J = std::fromTo(1, 5) do
setLocation(coord(0, 2 * J)), write(J)
end foreach,
Attr0 = getTextAttribute(),
foreach coord(X, Y) = list::getMember_nd(Polyline) do
Attr = if humanCell(coord(X, Y)), ! then 13 else 11 end if,
setTextAttribute(Attr),
setLocation(coord(3 * X, 2 * Y)), write("*")
end foreach,
setTextAttribute(Attr0).
run():-
write("Кто ходит первым? (1 - человек, 2 - компьютер): "),
Player = read(), clearInput(),
if Player = 1 then
write("Введите начало отрезка в виде coord(3,3): "),
hasDomain(coord, Cell1),
Cell1 = read(), clearInput(),
write("Введите конец отрезка: "),
hasDomain(coord, Cell2),
Cell2 = read(), clearInput(),
next(Cell1, Cell2),
assert(humanCell(Cell1)),
assert(humanCell(Cell2)),
move(2, [Cell1, Cell2])
else
move(1, [coord(3, 3), coord(4, 3)])
end if,
!,
_ = readLine();
write("Ошибка ввода"),
_ = readLine().
Предикат hasDomain/2 связывает переменную с именем домена. Предикат getTextAttribute возвращает текущие атрибуты текста окна консоли.
Метод ван Эмдена может быть использован только для полей небольших размеров, так как перебор во время поиска выигрышного хода делается довольно большой. Подробный разбор, демонстрирующий этапы проектирования и компьютерной реализации топологической игры "Ползунок", как в консольных, так и в GUI-приложениях на языке Visual Prolog, проделал В. А. Юхтенко (PDC SPb) [12].
Игра "Поле чудес" заключается в следующем. Компьютер случайным образом выбирает слово из словаря и загадывает его пользователю. Пользователь должен угадать это слово. Он может ввести либо букву, либо сразу все слово. Если слово окажется неверным, то игра прекращается, пользователь проигрывает. В противном случае она продолжается до тех пор, пока слово не будет отгадано.
open core, console
class facts
word: (positive, string).
clauses
word(1, "пароход").
word(2, "паровоз").
word(3, "самолет").
word(4, "аэроплан").
word(5, "корабль").
word(6, "поезд").
word(7, "дирижабль").
word(8, "зонд").
word(9, "аэростат").
word(10, "стратостат").
word(11, "ракета").
word(12, "электровоз").
class facts
number : positive := 0.
currentWord : string := "".
secretWord : string := "".
attempt : positive := 0.
class predicates
human_machine: ().
replace : (string, string) -> string.
clauses
human_machine():-
No = math::random(number) + 1,
word(No, Word),
NormWord = string::toUpperCase(Word),
currentWord := NormWord,
Len = string::length(NormWord),
secretWord := string::create(Len, "_"),
std::repeat(),
nl, write(string::replaceAll(secretWord, "_", " _ ")),
write("\n\nНазовите слово или букву: "),
String = string::toUpperCase(readLine()),
attempt := attempt + 1,
LenOfStr = string::length(String),
if LenOfStr = 1, not(_ = string::search(secretWord, String))
then if not(_ = string::search(currentWord, String)) then
write("\nНет такой буквы в этом слове.\n")
else secretWord := replace(secretWord, String) end if
end if,
((string::isWhiteSpace(currentWord); String = NormWord),
writef("\n\nСлово: %!\nКоличество попыток: %!", NormWord,
attempt);
LenOfStr > 1,
writef("\n\nСлово: %\nВы назвали % и проиграли!",
NormWord, String)),
!.
human_machine().
replace(SecretWord, Letter) = replace(SecretWord1, Letter):-
Pos = string::search(currentWord, Letter),
!,
currentWord := string::replacePart(currentWord, Pos, 1, " "),
SecretWord1 = string::replacePart(SecretWord, Pos, 1, Letter).
replace(SecretWord, _) = SecretWord.
run():-
write("Машина загадывает, человек угадывает!\n\n"),
number := list::length([X || word(X, _)]),
human_machine(),
_ = readLine().
Предикат toUpperCase/2 переводит все символы строки в верхний регистр. Предикат search/2 возвращает позицию подстроки в строке. Предикат replaceAll/3 заменяет в строке все вхождения одной подстроки другой подстрокой. Предикат replacePart/4 заменяет подстрокой заданное количество элементов с указанной позиции.
"Отгадай числа" — это игра для двух участников, которая состоит в следующем. Игроки загадывают по 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().
Реализуйте игру "Быки о коровы" в режимах
Игра "Ним" заключается в следующем. Имеется n кучек, в которых лежат камни. Игроки ходят по очереди. За один ход игрок может взять любое ненулевое число камней из произвольной кучки. Напишите программу для игры пользователя с компьютером, в которой игрок, взявший последний камень
В настоящей главе в консоли реализуются игры "Ползунок", "Поле чудес" и "Отгадай числа". В топологической игре "Ползунок" пользователь играет с компьютером. Поле для игры невелико, поэтому выигрышные ходы, в случаях, когда они существуют, находятся с помощью перебора возможных продолжений игры. В игре "Поле чудес" пользователь отгадывает слово, загаданное компьютером. "Отгадай числа" — это игра пользователя с компьютером, в которой участники отгадывают наборы чисел, загаданные противниками. Стратегия компьютера реализуется с помощью генерации варианта хода и отбрасывания вариантов, которые не согласуются с релультатами предыдущих ходов компьютера.
Топологическая игра "Ползунок" заключается в следующем. Игра ведется на решетке размером 5 на 6 клеток (рис. 14.1).
(рис 14.1) Партия топологической игры "Ползунок"
Участники ходят по очереди. Игрок проводит отрезок прямой длиной в одну клетку, достраивая ломаную с одного из концов. Получающаяся траектория (ломаная) должна быть непрерывной, причем ход можно делать с любого ее конца. Игрок, который замыкает траекторию, т. е. ходит так, что попадает одним из концов отрезка на ломаную, выигрывает. На рис 14.1 показана позиция, выигрышная для первого игрока (он проводит отрезки светлым карандашом). Ходом в клетку (1; 3) этот игрок замыкает траекторию.
Приведенная ниже программа — это реализация игры человека с компьютером. Для поиска выигрышной стратегии компьютера используется метод ван Эмдена (в [5, 14] он применяется в игре "Ним"): игрок делает выигрышный ход (замыкает траекторию) или ходит так, чтобы его противник не выиграл. Если противник (человек) не знает, каким образом нужно ходить, чтобы выиграть, то компьютер в результате обязательно выигрывает. Если же компьютер находится в проигрышной позиции и не может найти такой ход, то он пытается сходить так, чтобы его противник не выиграл на следующем же шаге. Если противник ошибется хотя бы один раз и не сделает правильный ход, то компьютер выиграет.
open core, console, console_native
class facts
humanCell: (coord).
class predicates
winMove: (positive, positive, coord*, coord*) nondeterm (i,i,i,o).
step: (coord*, coord*, coord) nondeterm (i,o,o) (i,o,i).
next: (coord, coord) nondeterm (i,o) (i,i).
move: (positive, coord*).
show: (coord*).
loseMove: (coord*) determ.
clauses
loseMove(Polyline):-
step(Polyline, _, Cell),
list::isMember(Cell, Polyline),
!.
winMove(_Player1, _Player2, Polyline, Polyline1):-
step(Polyline, Polyline1, Cell),
list::isMember(Cell, Polyline).
winMove(Player1, Player2, Polyline, Polyline1):-
step(Polyline, Polyline1, _),
not(winMove(Player2, Player1, Polyline1, _)).
move(2, Polyline):-
step(Polyline, Polyline1, Cell),
list::isMember(Cell, Polyline),
!,
show(Polyline1),
setLocation(coord(0, 14)),
write("Компьютер выиграл!\n\n", Polyline1).
move(2, Polyline):-
winMove(2, 1, Polyline, Polyline1),
!,
move(1, Polyline1).
move(2, Polyline):-
step(Polyline, Polyline1, _),
not(loseMove(Polyline1)),
!,
move(1, Polyline1).
move(2, Polyline):-
step(Polyline, Polyline1, _),
!,
move(1, Polyline1).
move(1, Polyline):-
show(Polyline),
setLocation(coord(0, 14)),
write(Polyline),
std::repeat(),
write("\n\nВаш ход.\nВведите новую клетку в виде"
" coord(2,3): "),
hasDomain(coord, Cell),
Cell = read(), clearInput(),
step(Polyline, Polyline1, Cell),
assert(humanCell(Cell)),
!,
if list::isMember(Cell, Polyline) then
write("\nПоздравляю! Вы выиграли!")
else
move(2, Polyline1)
end if.
move(_, _).
step([A, B | Polyline], [X, A, B | Polyline], X):-
next(A, X),
not(X = B).
step(Polyline, list::append(Polyline, [X]), X):-
[A, B | _] = list::reverse(Polyline),
next(A, X),
not(X = B).
next(coord(X, Y), coord(X - 1, Y)):- X > 1.
next(coord(X, Y), coord(X + 1, Y)):- X < 6.
next(coord(X, Y), coord(X, Y - 1)):- Y > 1.
next(coord(X, Y), coord(X, Y + 1)):- Y < 5.
show(Polyline):-
clearOutput(),
foreach I = std::fromTo(1, 6) do
setLocation(coord(3 * I, 0)), write(I)
end foreach,
foreach J = std::fromTo(1, 5) do
setLocation(coord(0, 2 * J)), write(J)
end foreach,
Attr0 = getTextAttribute(),
foreach coord(X, Y) = list::getMember_nd(Polyline) do
Attr = if humanCell(coord(X, Y)), ! then 13 else 11 end if,
setTextAttribute(Attr),
setLocation(coord(3 * X, 2 * Y)), write("*")
end foreach,
setTextAttribute(Attr0).
run():-
write("Кто ходит первым? (1 - человек, 2 - компьютер): "),
Player = read(), clearInput(),
if Player = 1 then
write("Введите начало отрезка в виде coord(3,3): "),
hasDomain(coord, Cell1),
Cell1 = read(), clearInput(),
write("Введите конец отрезка: "),
hasDomain(coord, Cell2),
Cell2 = read(), clearInput(),
next(Cell1, Cell2),
assert(humanCell(Cell1)),
assert(humanCell(Cell2)),
move(2, [Cell1, Cell2])
else
move(1, [coord(3, 3), coord(4, 3)])
end if,
!,
_ = readLine();
write("Ошибка ввода"),
_ = readLine().
Предикат hasDomain/2 связывает переменную с именем домена. Предикат getTextAttribute возвращает текущие атрибуты текста окна консоли.
Метод ван Эмдена может быть использован только для полей небольших размеров, так как перебор во время поиска выигрышного хода делается довольно большой. Подробный разбор, демонстрирующий этапы проектирования и компьютерной реализации топологической игры "Ползунок", как в консольных, так и в GUI-приложениях на языке Visual Prolog, проделал В. А. Юхтенко (PDC SPb) [12].
Игра "Поле чудес" заключается в следующем. Компьютер случайным образом выбирает слово из словаря и загадывает его пользователю. Пользователь должен угадать это слово. Он может ввести либо букву, либо сразу все слово. Если слово окажется неверным, то игра прекращается, пользователь проигрывает. В противном случае она продолжается до тех пор, пока слово не будет отгадано.
open core, console
class facts
word: (positive, string).
clauses
word(1, "пароход").
word(2, "паровоз").
word(3, "самолет").
word(4, "аэроплан").
word(5, "корабль").
word(6, "поезд").
word(7, "дирижабль").
word(8, "зонд").
word(9, "аэростат").
word(10, "стратостат").
word(11, "ракета").
word(12, "электровоз").
class facts
number : positive := 0.
currentWord : string := "".
secretWord : string := "".
attempt : positive := 0.
class predicates
human_machine: ().
replace : (string, string) -> string.
clauses
human_machine():-
No = math::random(number) + 1,
word(No, Word),
NormWord = string::toUpperCase(Word),
currentWord := NormWord,
Len = string::length(NormWord),
secretWord := string::create(Len, "_"),
std::repeat(),
nl, write(string::replaceAll(secretWord, "_", " _ ")),
write("\n\nНазовите слово или букву: "),
String = string::toUpperCase(readLine()),
attempt := attempt + 1,
LenOfStr = string::length(String),
if LenOfStr = 1, not(_ = string::search(secretWord, String))
then if not(_ = string::search(currentWord, String)) then
write("\nНет такой буквы в этом слове.\n")
else secretWord := replace(secretWord, String) end if
end if,
((string::isWhiteSpace(currentWord); String = NormWord),
writef("\n\nСлово: %!\nКоличество попыток: %!", NormWord,
attempt);
LenOfStr > 1,
writef("\n\nСлово: %\nВы назвали % и проиграли!",
NormWord, String)),
!.
human_machine().
replace(SecretWord, Letter) = replace(SecretWord1, Letter):-
Pos = string::search(currentWord, Letter),
!,
currentWord := string::replacePart(currentWord, Pos, 1, " "),
SecretWord1 = string::replacePart(SecretWord, Pos, 1, Letter).
replace(SecretWord, _) = SecretWord.
run():-
write("Машина загадывает, человек угадывает!\n\n"),
number := list::length([X || word(X, _)]),
human_machine(),
_ = readLine().
Предикат toUpperCase/2 переводит все символы строки в верхний регистр. Предикат search/2 возвращает позицию подстроки в строке. Предикат replaceAll/3 заменяет в строке все вхождения одной подстроки другой подстрокой. Предикат replacePart/4 заменяет подстрокой заданное количество элементов с указанной позиции.
"Отгадай числа" — это игра для двух участников, которая состоит в следующем. Игроки загадывают по 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().
Реализуйте игру "Быки о коровы" в режимах
Игра "Ним" заключается в следующем. Имеется n кучек, в которых лежат камни. Игроки ходят по очереди. За один ход игрок может взять любое ненулевое число камней из произвольной кучки. Напишите программу для игры пользователя с компьютером, в которой игрок, взявший последний камень
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.