Perl, 293 байта
-9 байт благодаря @Dom Hastings
{$==7+rand 30;@r=$"=();@a=((C)x4,(E)x3,("#")x1369,(" ")x1369);for$i(0..7+rand 30){$r[$i][$_]=splice@a,rand@a,1for 0..$=}$r[0][$=]=F;$r[-1][0]=P;$_=$r=join$/,$v="#"x($=+=3),(map"#@$_#",@r),$v;1while$r=~s/F(.{$=})?[^#F]/F$1F/s||$r=~s/[^#F](.{$=})?F/F$1F/s;$r!~/[CEP]/&&/C.*C/s&&/E/?last:redo}say
Добавьте -E
флаг для запуска:
perl -E '{$==7+rand 30;@r=$"=();@a=((C)x4,(E)x3,("#")x1369,(" ")x1369);for$i(0..7+rand 30){$r[$i][$_]=splice@a,rand@a,1for 0..$=}$r[0][$=]=F;$r[-1][0]=P;$_=$r=join$/,$v="#"x($=+=3),(map"#@$_#",@r),$v;1while$r=~s/F(.{$=})?[^#F]/F$1F/s||$r=~s/[^#F](.{$=})?F/F$1F/s;$r!~/[CEP]/&&/C.*C/s&&/E/?last:redo}say'
Однако запуск занимает много времени, поэтому я рекомендую использовать эту версию:
perl -E '{${$_}=8+rand 30for"=","%";@r=$"=();@a=((C)x4,(E)x3,("#")x($v=rand $=*$%),(" ")x($=*$%-$v));for$i(0..$%-1){$r[$i][$_]=splice@a,rand@a,1for 0..$=-1}$r[0][$=-1]=F;$r[$%-1][0]=P;$_=$r=join$/,$v="#"x($=+=2),(map"#@$_#",@r),$v;1while$r=~s/F(.{$=})?[^#F]/F$1F/s||$r=~s/[^#F](.{$=})?F/F$1F/s;$r!~/[CEP]/&&/C.*C/s&&/E/?last:redo}say'
Попробуйте онлайн!
объяснение
{ # введите блок (который используется как цикл) { $ == 7 + rand 30 ; # Случайным образом выбрать ширину карты -2 # (-2 , потому что мы не включаем границы пока) @r = $ «= (); # сброс @R, и множество $» на неопределенное значение @a = ( # создать список персонажей, которые могут быть на доске ( C ) x4 , # 4 монеты 'C' ( E ) x3 , # 3 враги 'E' ( "#" ) x1369 , # 37 * 37 '#' (
"" ) x1369 ); # 37 * 37 пробелов для $ i ( 0..7 + rand 30 ) # создать 2D-карту (7 + rand 30 - высота, которая генерируется только сейчас) для
$ r [ $ i ] [ $ _ ] = # index [$ i] [$ _] получает ...
splice @ a , rand @ a , 1 # .. случайный символ из ранее созданного списка # (символ затем удаляется из списка благодаря функции "splice") } }
$ r [
$ _ ( 0 .. $ = - 1 ) { 0 ] [ $ =] = F ; # добавить финишную ячейку
$ r [- 1 ] [ 0 ] = P ; # добавить начальную ячейку
$ _ = $ r = # здесь мы генерируем строковое представление карты
join $ /,
# объединяем следующие элементы с символами новой строки
$ v = "#" x ( $ = + = 3 ), # a first # только строка ( map "# @ $ _ #" , @r ), # добавьте # в начало и конец каждой строки
$ v ; # последняя строка #
1 while # следующее регулярное выражение заменит каждую доступную ячейку на F
$ r = ~ s / F (. { $ =})? [^ # F ] / F $ 1F / s # ячейку справа или снизу F ячейка заменяется || # или
$ r = ~ s / [^ # F ] (. { $ =})? F / F $ 1F / s ; # ячейка слева или верхняя часть ячейки F заменяется
$ r ! ~ / [CEP] / #, если на карте нет C, E или P (то есть все они были доступны) &&
/C.*C/ s # а там как минимум 2 монеты && / E / ? # и 1 враг последним : # карта действительна, мы выходим из цикла redo # else, начинаем заново }
say # и печатаем доску
Запуск занимает много времени, потому что список, из которого мы случайным образом выбираем символы для размещения на доске ( @a
), содержит 1369 пробелов и #
, и только 4 монеты и 3 врага. Так что, если размеры ширины и высоты невелики, есть много мест #
по сравнению с монетой и врагами, так что вполне вероятно, что случайная карта не будет действительной. Вот почему «оптимизированы» версия быстрее: список , из которого мы выбираем символы просто немного больше , чем карта (список @a=((C)x4,(E)x3,("#")x($v=rand $=*$%),($")x($=*$%-$v))
: случайное число $v
из #
(ниже размера карты), и size of the map - $v
пробелы).