Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Игра Болтянского на Pascal

Автор: NickolsoN 4.12.2010 3:25

Помогите написать программу.
Решение задании должно садержать
1. Доказательство выигрышной стратегии для игроков
2. Реализацию игры на компьютере с соблюдением уловий
- одним игроком в игре должен быть компьютер
- начальное состояние игры, два тех игр, где оно явно не задано, должно формироваться случайным образом (случайное число выбирается из экстетического представления картинки на экране);
- после представления начального состояния, а игре должен быть запрос Кто будет ходить
первым?»;
- игра должна быть оформлена с помощью графических средств*
- игра должна иметь «Заставку» и Правила игры
- управление игрой должно осуществляться либо с помощью управляющих клавиш клавиатуры либо мышкой
- компьютер должен играть по выигрышной стратегии: либо вследствие начальных данных игры, либо, следя за ходом человека, перехватив инициативу из-за его ошибки

Игра Болтянского
Играют двое. Первый выбирает натуральное число от 2 до 9, Второй умножает это число на выбираемое натуральное число от 2 до 9, затем первый выбирает число и умножает результат на любое натуральное число от 2 до 9 и т.д. Выигрывает тот, у кого впервые получится произведение,
больше заданного положительного числа C
Выяснить при каких С существует выигрышная ситуация у первого игрока,
при каких - у второго.

помогите пожалуйста, можно и без графики

Автор: Unconnected 4.12.2010 3:31

И нафига тут графика вообще, интересно.. ну, обоснование выигрышной стратегии в программу не входит.

Что-то гугл не знает про такую игру.

Цитата
Играют двое. Первый выбирает натуральное число от 2 до 9, Второй умножает это число на выбираемое натуральное число от 2 до 9, затем первый выбирает число и умножает результат на любое натуральное число от 2 до 1 и т.д. Выигрывает тот, у кого впервые получится произведение,
больше заданного положительного числа C


[выделенное]от двух до одного?
А стратегия тут вроде бы умножать на максимум всегда..

Автор: NickolsoN 4.12.2010 3:52

Цитата(Unconnected @ 3.12.2010 23:31) *

И нафига тут графика вообще, интересно.. ну, обоснование выигрышной стратегии в программу не входит.

Что-то гугл не знает про такую игру.
[выделенное]от двух до одного?
А стратегия тут вроде бы умножать на максимум всегда..

я тоже про эту игру ниче в гугле не нашел...от 2 до 9, извините, помогите написать прогу плиз

Автор: Unconnected 4.12.2010 4:14

Со стратегией наврал я.. наверное, выигрышная стратегия состоит в домножении на "максимум", при котором противник, домножив произведение на 9 (максимальный максимум)) - не выиграет.

Так тебе с графикой надо или без? Пробовал что сделать?

Автор: Lapp 4.12.2010 13:48

Цитата(NickolsoN @ 3.12.2010 23:25) *
Игра Болтянского
Играют двое. Первый выбирает натуральное число от 2 до 9, Второй умножает это число на выбираемое натуральное число от 2 до 9, затем первый выбирает число и умножает результат на любое натуральное число от 2 до 9 и т.д. Выигрывает тот, у кого впервые получится произведение,
больше заданного положительного числа C
Выяснить при каких С существует выигрышная ситуация у первого игрока,
при каких - у второго.

Болтянский - хороший математик. Его самого я почти не видел, правда - так, мельком, в президиуме )). Но имя его встречал часто (сборник задач, реколлегия Кванта.. не говоря о научных трудах)).

Я немного пораскинул мозгами.. Стратегию сочинил некоторую, но доказывать ее мне в лом. Она простенькая )).

Вот, короче, моя версия игровой проги. Распаковывайте и запускайте (вирусов нема, не держим их)). Играйте на здоровье! Интерфейс на англицком, но там все понятно. Если что-то будет неясно - спрашивайте.


Прикрепленные файлы
Прикрепленный файл  boltyan.rar ( 20.06 килобайт ) Кол-во скачиваний: 223

Автор: NickolsoN 4.12.2010 14:04

Цитата(Lapp @ 4.12.2010 9:48) *

Болтянский - хороший математик. Его самого я почти не видел, правда - так, мельком, в президиуме )). Но имя его встречал часто (сборник задач, реколлегия Кванта.. не говоря о научных трудах)).

Я немного пораскинул мозгами.. Стратегию сочинил некоторую, но доказывать ее мне в лом. Она простенькая )).

Вот, короче, моя версия игровой проги. Распаковывайте и запускайте (вирусов нема, не держим их)). Играйте на здоровье! Интерфейс на англицком, но там все понятно. Если что-то будет неясно - спрашивайте.

мне нужен не отткомпилированный файлик .pas,который будет работать в Turbo Pascale, у нас тока в нем принимают, не могли бы выложить плиз?
просто это моя домашка по проге, кроме работающей программы надо еще куча бумажной работы, спецификация, связь и тд и тп..а тут без исходного алгоритма и объяснения его никуда...к сожалению))

Автор: Lapp 4.12.2010 15:20

Цитата(NickolsoN @ 4.12.2010 10:04) *
мне нужен не отткомпилированный файлик .pas,который будет работать в Turbo Pascale, у нас тока в нем принимают, не могли бы выложить плиз?
просто это моя домашка по проге, кроме работающей программы надо еще куча бумажной работы, спецификация, связь и тд и тп..а тут без исходного алгоритма и объяснения его никуда...к сожалению))
Нужен файлик .pas? А.. Ну, так ты, эта.. пиши его! Напишешь - и будет у тебя файлик .pas, который работает в TP.. или не очень работает.. Не важно. Ты приноси ХОТЬ ЧТО-ТО.

Когда я увижу, что ты в состоянии сам написать хотя бы begin - я начну с тобой на эту тему разговаривать. А так - ... не люблю я лоботрясов. И не вижу АБСОЛЮТНО НИКАКОЙ причины, почему я тебе должен давать файлик .pas . Будешь говорить ПО ДЕЛУ - с радостью тебе отвечу. А твоя домашка меня НУ АБСОЛЮТНО не трогает.. Не разжалобишь )), скорее наоборот. Мне на нее плевать на твою домашку. Ага.

Проявишь ИНТЕРЕС - будет тебе помощь. Все.

Автор: -TarasBer- 4.12.2010 15:52

> Со стратегией наврал я.. наверное, выигрышная стратегия состоит в домножении на "максимум", при котором противник, домножив произведение на 9 (максимальный максимум)) - не выиграет.

Очевидно, что нет. Игру про спички знаешь же? Каждый выбирает число от 1 до 9 и ПРИБАВЛЯЕТ к результату.
Думаешь, ты выиграешь, выбирая 9тки первую половину игры?
Вряд ли.

Автор: Unconnected 4.12.2010 15:56

Почему бы и нет, наверное выиграю. Какая разница, какими шагами идти до того момента, когда можно одним ходом сгрести все оставшиеся палочки (или, домножив, перепрыгнуть число С).

Ан нет, что-то такой стратегией не удается прогу переиграть.. Что-то её вообще выиграть не получается))

Автор: RathaR 4.12.2010 16:50

Lapp, а то что твоя прога разрешает умножать на единицу - так и задумано?

Автор: Unconnected 4.12.2010 16:54

Может, в этом секрет выигрышной стратегии rolleyes.gif ))

Автор: -TarasBer- 4.12.2010 16:56

> Почему бы и нет, наверное выиграю. Какая разница, какими шагами идти до того момента, когда можно одним ходом сгрести все оставшиеся палочки (или, домножив, перепрыгнуть число С).

Ты что, игру про спички не знаешь?!
ОМБ...

Страта там такая - надо всегда дополнять кол-во оставшихся до победы элементов до кратного 10и.

Автор: Lapp 4.12.2010 17:01

Цитата(RathaR @ 4.12.2010 12:50) *
Lapp, а то что твоя прога разрешает умножать на единицу - так и задумано?
Там нет никаких проверок.. Предполагается, что ЧЕЛОВЕК не мухлюет! ))
можешь умножить хоть прямо на 100000 и выиграть одним ходом )).

Автор: NickolsoN 4.12.2010 21:36

короче с 5 вечера, до почти 1часа ночи пытался уловить, выйгрышную игру компа....без результатов, вот пока что получилось, комп выдает числа рандомом, и еще вывод сообщения о том кто именно выйграл кривоват. Lapp, помогите пожалуйста....


program boltyanskiyy;
uses crt;
var
a,b,c,p,d,winner:integer;
function isWinner(who,num,c,winner:integer):integer;
begin
if (winner = 0) and (num>=c) then begin
isWinner:=who; {1-chelovek 2-comp}
end
else begin 2
isWinner:=0;
end;
end;
begin
clrscr;
p:=1; {prisvaivaem proizvedeniuy 1}
d:=1;
randomize;
write('vvidite polozhitelnoe chislo C ( 0 - random C) = '); {zadaem C}
readln©;
if c=0 then
c:=random(1000);
writeln('chislo C = ',c);
write('kto hodit pervim?(1 - vi, 0 - komp) - '); {vibor pervogo hoda}
readln(a);
winner:=0;
if a=1 then
repeat
winner:=isWinner(1,p*d,c,winner);
writeln('vvedite chislo ot 2 do 9 - ');
read(b);
d:=random(7)+2;
p:=p*b*d;
winner:=isWinner(2,p,c,winner);
writeln('vi vveli - ',b ,', ya vvel - ',d,' proizvedenie - ',p);
until (p>=c)
else
repeat
winner:=isWinner(1,p*d,c,winner);
d:=random(7)+2;
writeln('ya vvel - ',d);
writeln('vvedite chislo ot 2 do 9 - ');
read(b);
p:=p*b*d;
winner:=isWinner(2,p,c,winner);
writeln('vi vveli - ',b,' proizvedenie - ',p);
until (p>=c);
writeln('pobedil - ',winner,',(1-chelovek, 2-komp) ');
while not keypressed do;
end.
.

Автор: Lapp 5.12.2010 5:00

Цитата(NickolsoN @ 4.12.2010 17:36) *
вот скелет проги написал
Хорошо, это совсем другой разговор! smile.gif

Так, во-первых, в игре тебе понадобится цикл (по ходам). И еще нужна булева переменная, чтобы понимать, чей сейчас ход. Если она FALSE - это значит, что сейчас ход компьютера, если TRUE - ход человека. Назови ее Player. Примерно так:
  writeln('kto hodit pervim?(1 - vi, 2 - komp)');
readln(a);
Player:= a=2;
- тут мы делаем НАОБОРОТ: если первым ходит комп, то p=TRU. Это потому, что мы сменим p при входе в цикл по ходам. Затем, перед входом в цикл мы должны присвоить начальное значение тому самому числу, которое умножается в игре. Начальное значение равно 1 (понятно, почему?) Потом в ходим в цикл. Сами ходы лучше всего оформить как подрограммы (ты с ними знаком?). Тогда описанный кусок кода будет выглядеть примерно так:
n:= 1;
repeat
Player:= not Player;
if p then m:= UserMove(n) else m:= CompMove(n);
WriteLn('Игрок ',PlayerName[Player],' сделал ход ',m,', новое число равно ',n)
until n>=c;
WriteLn(PlayerName[Player],' выиграл!')


Сделай пока программу UserMove, которая делает ручной ход, и поставь ее на оба места в операторе if, вот так:
  if p then m:= UserMove(n) else m:= UserMove(n);

Такая программа позволит играть юзеру за компьютер. Когда это будет готово, начнем разбираться со стратегией игры.

Давай, делай и приноси результат. Что непонятно - спрашивай. Не стесняйся даже глупых вопросов.
Успехов тебе.

Добавлено через 3 мин.
О, сколько ты наваял! )
все же сделай, как я просил.
Стратегия - после интерфейса. Всему свое время.

Автор: NickolsoN 5.12.2010 19:12

вот щас подлатал прогу, вывод нормально работает и нормально пишит кто выйграл, комп числа выдает случайным образом, без стратегии. Можно но ли, знаяя стратегию, отредактировать мою прогу? а насчет графики....никогда не пользовался))даже не представляю как)может вы поможете сначала со стратегией??пожалуйста=)


program boltyanskiy;
uses crt;
var
a,b,c,p,d,e:integer;
flag:boolean;

begin
repeat
clrscr;
p:=1; {prisvaivaem proizvedeniuy 1}
d:=1;
randomize;
write('Vvidite polozhitelnoe chislo C ( 0 - random C) = '); {zadaem C}
readln©;
if c=0 then
c:=random(1000);
writeln('chislo C = ',c);
write('kto hodit pervim?(1 - vi, 0 - komp) - '); {vibor pervogo hoda}
readln(a);
if a=1 then flag:=true;
repeat
if flag then begin
write('vvedite chislo ot 2 do 9 - ');
read(b);
p:=p*b;
writeln('vi vveli - ',b,', proizvedenie - ',p);
end else begin
d:=random(7)+2;
p:=p*d;
writeln('ya vvel - ',d,' ,proizvedenie - ',p); end;
flag:=not flag;
until (p>=c);
if flag then writeln('Ura!Ya viygral!') else writeln('Pozdravlyayu, vi viygrali!');
write('Esche sigraem? (1 - yes, 0 - no) - ');
read(e);
until (e=0);
end.

Автор: Lapp 6.12.2010 9:18

Хорошо. Ты сделал достаточно много, чтоб я убедился, что ты умеешь работать. Но ты не выполняешь все мои просьбы, и это затрудняет разговор. Это не упрек, скорее оправдание, почему я выкладываю свой вариант. Посмотри на него и сам сделай выводы.

Обрати внимание на такие моменты..
1. Форматирование программы. Сдвиги делаются не там, где тебе кажется красивее, а по правилам. Постарайся понять их на примере моего кода. Это тебе сильно поможет в будущем при написании более длинных программ.
2. Процедуры и функции используй не только для повторяющегося кода, но и для структуризации, чтоб выделить блоки, отличающиеся по смыслу.
3. Убери CRT. Никогда не делай ClrScr без осознанной необходимости. Мне уже надоело это всем говорить, читай тут: http://forum.pascal.net.ru/index.php?s=&showtopic=26952&view=findpost&p=150391
4. Всегда старайся все числа убрать в константы. Например, тут есть числа 2 и 9. Вроде бы, они не должны меняться. На самом же деле может оказаться, когда ты придешь сдавать эту прогу препу, что он скажет: "хорошо, молодой человек, вы справились; а теперь та же задача для пределов 5 и 28..." И ты станешь ползать по всей программе, выискивая двойки и девятки..

Теперь по поводу стратегии.. Хорошо, я не буду убирать из своей проги алгоритм выигрышной стратегии. Постарайся с ним разобраться. Тебе придется это сделать, так как в задании есть вопрос: при каких С есть выигрышная стратегия. Задавай вопросы, если будет что-то неясно )).

const
d1= 2;
d2= 9;
Name: array [false..true] of string=(' I','You');
OfName: array [false..true] of string=(' My','Your');

var
c,m,n: LongInt;
Player: boolean; // false=computer, true=user


function AI: integer; // Artificial Intellect
var
d,e: LongInt;
begin
d:=c;
repeat
e:=(d-1)div n+1;
d:=(d-1)div(d2*d1)+1
until e<=9;
if e<2 then e:=2;
AI:=e
end;

function ManualMove: integer;
var
m: integer;
begin
Write('Make your move (',d1,' through ',d2,') : ');
ReadLn(m);
ManualMove:=m
end;

begin
repeat
WriteLn('Well, let''s play!');
Write('Enter the goal (0 for random) : ');
ReadLn©;
if c=0 then c:=Random(10000);
WriteLn('The goal is now set to ',c);
Write('Who moves first? 0 for computer (yes, that''s me!)), 1 for you : ');
ReadLn(m);
Player:=m=0;
n:=1;
while n<c do begin
Player:=not Player;
if Player then m:=ManualMove else m:=AI;
n:=n*m;
WriteLn(OfName[Player],' move was ',m,', the number is now ',n);
end;
WriteLn(Name[Player],' win!');
Write('Wanna play more? 0 for No, 1 for Yes: ');
ReadLn(m)
until m=0
end.

Автор: NickolsoN 7.12.2010 1:49

Lapp, спасибо ВАМ !вот сидел алгоритм ваш пытался понять))вышло, сразу скажу, не очень=((вот написал комментарии с коду


const
d1= 2;
d2= 9;
Name: array [false..true] of string=(' I','You');
{массиви строк, принимающие значение тру и фолс?и не понятно мне =(' I','You')}
OfName: array [false..true] of string=(' My','Your');

var
c,m,n: LongInt; {почему лонгит, а не интегер?}
Player: boolean; {false=computer, true=user}


function AI: integer; // Artificial Intellect
var
d,e: LongInt;{d-введенное с, e-ход компа}
begin
d:=c;
repeat
e:=(d-1)div n+1; {заданная длинна-1 делится на цело на текущее произведение +1}
d:=(d-1)div(d2*d1)+1 {заданная длинна изменяется, вообще не пойму для чего=(())}
until e<=9; {выполнется пока ход компа не будет в диапазоне от 2 до 9}
if e<2 then e:=2;
AI:=e
end;

function ManualMove: integer;
var
m: integer;
begin
Write('Make your move (',d1,' through ',d2,') : ');
ReadLn(m);
ManualMove:=m
end;

begin
repeat
WriteLn('Well, let''s play!');
Write('Enter the goal (0 for random) : ');
ReadLn©;
if c=0 then c:=Random(10000);
WriteLn('The goal is now set to ',c);
Write('Who moves first? 0 for computer (yes, that''s me!)), 1 for you : ');
ReadLn(m);
Player:=m=0;
n:=1;
while n<c do begin
Player:=not Player;{меняем игрока}
if Player then m:=ManualMove else m:=AI;{если плеер тру, то ходит чел, иначе комп}
n:=n*m;
WriteLn(OfName[Player],' move was ',m,', the number is now ',n);
end;
WriteLn(Name[Player],' win!');
Write('Wanna play more? 0 for No, 1 for Yes: ');
ReadLn(m)
until m=0
end.


путаюсь в догатках, как вы вывели такую стратегию(( e:=(d-1)div n+1; d:=(d-1)div(d2*d1)+1

Автор: Lapp 7.12.2010 5:13

Цитата(NickolsoN @ 6.12.2010 21:49) *
массиви строк, принимающие значение тру и фолс?
Да. Не применял? Поиграйся, это удобно.

Цитата
и не понятно мне =(' I','You')
Типизированная константа, изобретение Borland. Почитай в хелпе.

Цитата
почему лонгит, а не интегер?
Как почему? А ты назвал диапазон чисел? Нет? Вот я и стараюсь, чтоб влезло побольше..

Цитата
путаюсь в догатках, как вы вывели такую стратегию(( e:=(d-1)div n+1; d:=(d-1)div(d2*d1)+1
Я и сам путаюсь. Интуиция.. ))

Автор: Lapp 7.12.2010 14:41

Так. Кажется, я придумал, как объяснить эту интуицию.

См. рисунок: Прикрепленное изображение (масштаб пропорций не выдержан, иначе пришлось бы слишком мельчить)

Идет игра до цели C. Пусть МЫ играем проив НИХ. Игра находится в некоторой промежуточной стадии, произведение в настоящий момент равно P. Ход наш. И мы думаем то, что можем думать..

Во-первых, договоримся о терминах:
начало хода - это чему равно произведение к этому ходу;
сам ход - это на что мы домножаем (от 2 до 9);
результат хода - то, что получается после умножения начала на ход.
Например, если начало хода равно 12, а наш ход равен 3, то результат нашего хода есть 36.

Допустим, что выиграть сразу одним ходом мы не можем, потому что C слишком велико. Так вот, с самого начала ясно, что нам НЕЛЬЗЯ (если, конечно, мы хотим выиграть), чтоб результат нашего хода попал в промежуток от C/9 до C, потому что они (если они не дураки) сразу смогут выиграть. Этот ПЛОХОЙ для нас интервал изображен толстой красной линией.

Но с другой стороны, мы хотим, чтобы результат ИХ хода попал на этот участок. Желательно ЗАСТАВИТЬ их сделать такой ход. Для этого попробуем определить такой участок, любой ход с которого попадет в красный. Это сделать легко (проанализируй сам и поймешь), этот участок - от C/9/2 до C/9. Нам надо, чтобы они начинали свой ход внутри этого участка. А их начало - это наш предыдущий результат! Значит, нам надо СТРЕМИТЬСЯ попасть в этот кусок предыдущим ходом. На рисунке этот кусок изображен толстой зеленой линией.

Таким образом, мы выяснили, что нам желательно попасть ЗА число C/9/2. Другими словами, нашей ДАЛЬНЕЙ целью все еще является C, но появилась цель поближе. Назовем ее C1 (подразумевая, что то C было как бы C0). То есть, C1=C/18.

После этого мы можем абстрагироваться от дальней цели и заняться выполнением более близкой. Иными словами, теперь игра ведется не до C, а до C1. Если мы выиграем эту игру, то мы выиграем и всю игру. И мы можем повторить все те же самые рассуждения, но теперь про C1. И тогда мы найдем число C2, которое снова станет нашей новой целью. А между C2 и C1 - красный участок потоньше и зеленый участок потоньше. А за ним последкет C3 и так далее..

Так будет продолжаться до тех пор, пока текущее произведение P не попадет ЗА очередную Ci. Если оно окажется на красном куске - отлично, мы ходим так, чтобы попасть на следующий зеленый. Если нет - мы ходим как-то (при этом желательно выбрать маленький ход, чтоб затянуть игру) и хдем ИХ ошибки.

Это, так сказать, сухая теория. На практике все немного усложняется из-за того, что целые числа делятся не точно, а с остатком. Попробуй с учетом всего вышесказанного осмыслить функцию AI. Что будет неясно - задавай вопросы.
smile.gif

Автор: NickolsoN 8.12.2010 22:29

Lapp, вы гений!! столь развернутый ответ дали!как же у вас родился такой алгоритм) и все же, для меня остается не решенным вопрос том, как зависит выйгрыш компа или человека от заданного С?

Автор: TarasBer 9.12.2010 14:59

Кстати, известная идея - все возможные позиции разделить на "начинающий выигрывает" и "начинающий проигрывает".

Автор: Lapp 9.12.2010 20:07

Цитата(NickolsoN @ 8.12.2010 18:29) *
Lapp, вы гений!! столь развернутый ответ дали!как же у вас родился такой алгоритм) и все же, для меня остается не решенным вопрос том, как зависит выйгрыш компа или человека от заданного С?

Все очень просто.
Замени ручной ход на AI. Или просто вместо того if влепи m:=AI, да и все.
Теперь запускай прогу, вводи РАЗНЫЕ целевые числа и ВСЕГДА выбирай, что первым ходит комп (то есть 0). Если выиграл комп (I win!), то жто значит, что при этом C выигрышная стратегия была у ходящего первым. Если прога сказала "You win!" - значит, при этом C выигрышная стратегия у ходящего вторым.

Если ты все это зациклишь и прогонишь для всех чисел в нужном диапазоне (типа от 10 до 100000) и соберешь результаты в массив, то по ним ты сможешь составить себе предста...

мне продолжать? smile.gif

Большая просьба - не пинать меня больше в личке. Я все читаю, когда у меня есть время. И отвечаю, когда есть желание.
Все.

Автор: NickolsoN 9.12.2010 20:19

Lapp, извините!в личке баловать больше не буду)попробую разобраться с С)
И еще, не подскажете что с графикой делать?Я хочу что бы при запуске проге висела заставка:

New game
Rules
Exit

После нажатия новой игры, при ходе человека на экране появлялись 8 активных квадратикой, и на них числа от 2 до 9, что бы после нажатия на них, комп считывал это. Это вообще посильная задача?Потому что я в графике 0 =)Подскажите плиз, может статейки есть хорошие по графике в паскале?

Автор: Lapp 9.12.2010 20:43

Какая тебе нужна графика? турбо-паскалевская?
Если да, то вот тебе пример простейшей графической программы:

uses
Graph;

var
gd,gm: integer;

begin
InitGraph(gd,gm,'');
Line(0,0,GetMaxX,GetMaxY);
MoveTo(100,100);
OutText('Hi World!');
ReadLn;
CloseGraph
end.