|
|
Регистрация Восстановить пароль |
Повторная активизация e-mail |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
|
Опции темы | Поиск в этой теме |
14.10.2009, 00:21 | #1 |
Пользователь
Регистрация: 14.10.2009
Сообщений: 15
|
Игра "Вперед и вверх"
Приветствую вас, великие программисты.
Прошу помощи: получил задание - разработать программу игры "вперед и вверх". Код труда не представляет, но в игре необходимо выделить беспроигрышную тактику (которой будет следовать компьютер). Поэтому вот краткая характеристика игры: игра идет на поле в клетку размерами M*N. Пользователь задает максимальную длину линии - X по горизонтали (X<=N) и Y по вертикали (Y<=M). Суть игры: из точки в левом нижнем углу пользователь и компьютер по очереди рисуют линии, не превышающие вышеописанных длин, при том начало очередной линии совпадает с концом предыдущей. Победа в игре: добраться, так сказать, своей линией до конечной точки - верхний правый угол вышеописанного поля. Уважаемые программисты, осознаю, что поиск беспроигрышной ситуации - не ваше дело, но, возможно, кто-то встречался когда-либо с подобным заданием. (Варианты выигрыша нужна как в случае, если компьютер ходит первым, так и для случая, если ходит вторым). |
14.10.2009, 00:46 | #2 |
Форумчанин
Регистрация: 10.10.2009
Сообщений: 680
|
Алгоритм решения подобных задач, в тому случае, если математически делать влом:
1. Пишем динамику с поиском выиграшных/проиграшных позиций. 2. Вклеиваем в нее масив указателей, чтобы понять, как действовать в выиграшной/проиграшной позиции. Сейчас я спать пойду, нету времени самому кодить что-то, суть динамического решения такая: крайная верхняя правая клетка - выиграш. Далее просматриваем массив посрочно сверху вниз (В каждой стоке просматриваем справа налево, а не наоборот), если с данной клетки можно попасть только в выиграшные - она проиграшная. Иначе - выиграшная. Если выиграшная - понятно, ходим в проиграшную, а после хода противика повторяем все то же самое с новой клетки. З.Ы. Усный анализ показвает, что далеко не во всех случаях есть выиграшная стратегия (самый простой пример - поле 2 на 2 и ограничение на длину хода 1). Тогда придется надеятся, что игрок неоптимален и сделает ошибку, после которой можно перейти на выиграшную стратегию. |
14.10.2009, 19:40 | #3 |
Пользователь
Регистрация: 14.10.2009
Сообщений: 15
|
Благодарю за ответ, однако, это несколько не то, что я ожидал увидеть.
Как я понимаю, должна быть этакая формула (с использованием переменных n,m,x,y) по которой компьютер будет делать каждый очередной ход. |
14.10.2009, 19:45 | #4 |
Форумчанин
Регистрация: 10.10.2009
Сообщений: 680
|
Сейчас у меня нету желания что-либо решать математически, когда будет время - напишу то, что посоветовал вам, и сяду выводить решение сам. К вечеру будет готово.
А какие ограничения? может, вообще не нужна никакая стратегия? если поле 100 на 100, то можно и заранее просчитать Код:
Последний раз редактировалось Stilet; 15.10.2009 в 09:31. |
15.10.2009, 13:54 | #5 |
Пользователь
Регистрация: 14.10.2009
Сообщений: 15
|
Всё несколько сложнее...
1. поле может быть квадратным или прямоугольным (10*10, 15*4) 2. длина максимального хода по горизонтали и вертикали могут быть различны (х=3, у=5) 3. размеры поля и макс. длина хода вводятся пользователем. Вчера написал код, определяющий выигрышные позиции на поле, посмотрите, пожалуйста: uses crt; var point: array[0..100,0..100] of integer; {m*n;m-i;n-j} n,m,x,y,i,ii,j,jj:integer; procedure paint(i,j:integer); var ii,jj:integer; begin point[i,j]:=1; jj:=j+1; ii:=i-1; while (m>=jj) and ((j+x)>=jj) do begin if point[i,jj]=1 then point[i,j]:=0; jj:=jj+1; end; while (n>=ii) and ((i-y)<=ii) do begin if point[ii,j]=1 then point[i,j]:=0; ii:=ii-1; end; end; begin clrscr; m:=20; n:=30; x:=6; y:=3; point[1,m]:=1; i:=m; j:=1; while (i>0) and (n>j) do begin for ii:=i downto 1 do paint(j,ii); for jj:=j+1 to n do paint(jj,i); i:=i-1; j:=j+1; end; for i:=1 to n do begin for j:=1 to m do begin write(point[i,j],' '); end; writeln; end; Тактика такова: конечная клетка, естественно, выигрышная. А от нее начинаем отсчитывать по схеме: если из клетки можно провести линию в выигрышную клетку - то эта клетка считается проигрышной, если из клетки линию можно провести только на проигрышные - она выигрышная. В коде единичкой указаны выигрышные точки, ноликом проигрышные. Теперь задача заставить компьютер ходить по единичкам... |
15.10.2009, 14:47 | #6 |
Высокая репутация
СуперМодератор
Регистрация: 27.07.2008
Сообщений: 15,580
|
Упростим задачу.
Допустим, имеется игровое поле: горизонтальная линия из N клеток. За 1 ход можно продвигаться вперёд от 1 до K клеток. Выигрывает тот, кто при своём ходе достигнет конца игрового поля. Обозначим за P текущую позицию в игровом поле. 1. Если на нашем ходе P >= N - K, то, очевидно, что мы выиграли, т.к. можно походить (N - P) и достичь конца поля. 2. Если же P = N - K - 1, то, очевидно, что это проигрышная позиция, т.к., как ни пойди, получим 1-й случай для нашего противника, в котором он побеждает. Задача сводится к тому, что бы прийти не к победе, а к позиции (N - K - 1). Обозначим N1 = N - K - 1. Условие задачи остаётся тем же, только теперь нам требуется достичь не позицию N, а позицию N1. Аналогично, те же 2 случая, что и для исходной игры. И т.д.... Остаётся вычислить эту цепочку: N, N1, N2, ..., которая гарантированно приводит нас к победе: N0 = N N1 = N - K - 1 N2 = N1 - K - 1 = N - K - 1 - K - 1 = N - 2 * K - 2 N3 = N2 - K - 1 = N - 2 * K - 2 - K - 1 = N - 3 * K - 3 ... Ni = N - i * K - i = N - i * (K + 1) Вычисляем, сколько всего Ni будет существовать, т.е. каково максимальное i: imax = N div K - 1 Вычитаем 1, т.к. нумерация N у нас от 0. И так, ход компьютера, текущая позиция после хода игрока P (в начале игры P = 0). Определяем индекс i текущего хода: i = (N - P) div (K + 1) Нам необходимо сделать следующий ход (обозначим его за L): L = Ni - P Если L = 0 (значит противник играет по оптимальной стратегии), то ходим L = 1, т.е. продвигаемся вперёд на минимальное расстояние, что бы затянуть игру и повысить вероятность ошибки игрока. Ваша же задача состоит из 2 одинаковых подзадач, которые я описал выше. Т.е. движение по горизонтали и вертикали можно рассматривать как независимые подзадачи. Как именно ходить (по вертикали или по горизонтали) надо определять исходя из того, где мы сбились с оптимального пути, т.е. надо выйти на Ni как по горизонтали, так и по вертикали. На самом деле идея очень простая, если понять принцип. Это только в описании много получилось, но тут нет ничего сложного. Может, чуть позже, напишу программку в Делфи, демонстрирующую этот принцип. E-Mail: arigato.freelance@gmail.com
Последний раз редактировалось Arigato; 15.10.2009 в 18:30. |
15.10.2009, 14:49 | #7 |
Высокая репутация
СуперМодератор
Регистрация: 27.07.2008
Сообщений: 15,580
|
Sl1mka.
Такой нюанс: линия рисуется только горизонтально или вертикально или же под произвольным углом? Если под произвольным углом, то тут не совсем понятно, как именно она будет рисоваться, т.к. длинна же считается в пикселях. E-Mail: arigato.freelance@gmail.com
|
15.10.2009, 15:55 | #8 |
Пользователь
Регистрация: 14.10.2009
Сообщений: 15
|
Arigato, рассматривал такой ход решения, но, вероятно, где-то сбился с мысли. Буду благодарен за полный анализ (и вертикаль, и горизонталь).
Линии рисуются или только вправо, или только вверх. За один ход нельзя нарисовать кривую линию, также нельзя рисовать линии под углом (след. две рядом стоящие линии дадут или угол 180 гр., если идут в одном и том же направлении, или же 90 гр., если идут в разных направлениях). С таким ходом решения не справился из-за того, что поле может быть не квардатным, т.е. n<>m, а также вертикальный и горизонтальный предел хода может быть различен, т.е. x<>y. Не справился с выведением формулы. Однако был замечен интересный момент: каким бы образом не строились линии (по какой бы траектории не проходил путь к выйгрышной точке), сумарное количество клеток, встречаемых на пути будет равно (n+m)-1 и при том неизменно, независимо от траектории, т.е. (n+m)-1=const Пример: для поля 10*10. n=10, m=10. Количество клеток, по которым могут быть совершены ходы от начальной точки до конечной будет равно (m+n)-1=(10+10)-1=19 |
15.10.2009, 16:00 | #9 | |
Высокая репутация
СуперМодератор
Регистрация: 27.07.2008
Сообщений: 15,580
|
Цитата:
Просто за N принимаем (n + m - 1) - расстояние до победы. А дальше всё точно так же, как я расписал выше. Только двигаться надо или вверх или вправо, главное, сокращать расстояние на требуемое значение (если вверх не хватает клеток, идём вправо; если вправо не хватает, идём вверх; если можно идти и вправо и вверх, идём куда угодно, главное, заданное число клеток преодолеть). P.S. Как мне кажется, всё же лучше именно разделить на 2 подъигры и параллельно играть в обе (отдельно двигаться вправо и отдельно вверх), контролируя, что бы в обоих подъиграх путь был выигрышным. Т.к. если рассматривать только расстояние до победы, может получиться, что мы будем стоять на диагонали, а в верху и справа поле будет заканчиваться раньше, чем то расстояние, которое мы должны пройти. Сейчас попробую реализовать игру в Делфи, посмотрим, что получится. E-Mail: arigato.freelance@gmail.com
Последний раз редактировалось Arigato; 15.10.2009 в 16:03. |
|
15.10.2009, 16:35 | #10 | |
Форумчанин
Регистрация: 10.10.2009
Сообщений: 680
|
Цитата:
Суть тактики подобрана верно. Arigato, фактически Вы правы, так и надо. Действительно, как мне кажетася, оптимальный вариант - именно независимая игра по 2 направлениям. Если противник движется по иксам - уравниваем по иксам, если движется по игрекам - уравниваем по игрекам. Довольно легко доказать, что это всегда возможно. |
|
|
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
при вводе на листе "магазин"- код товара появлялось "описание" товара из "склада" с "продажной ценой" | aleksei78 | Microsoft Office Excel | 13 | 25.08.2009 12:04 |
Игра "Ghost Recon Advanced Warfighter 1"(GRAW) | Air | Gamedev - cоздание игр: Unity, OpenGL, DirectX | 0 | 27.07.2008 08:07 |
Игра "четный" "нечетный" | bigcat | Помощь студентам | 1 | 01.03.2008 00:24 |