Помогите пожалуйста в решении задачи, третий день сижу а вместо решения получил только головную боль. :x Задача: Добавить квадрат (3х3) на пустое место, занятые квадраты хранятся в базе (id, y, x). У каждого квадрата есть центр (x%3=0, y%3=0). При каждом добавлении, должна забиваться база, т.е. в базу забиваются координаты новых девяти квадратов с центром. При этом есть switch, который определяет направление нового квадрата, case’ов 8 (север, юг, восток, запад, св, сз, юв, юз). На рисунке я показал примерное расположение координатной сетки с квадратами (указаны только координаты центров). Добавляться должны ближайшие квадраты (отмечены вопросиками), и когда квадрат добавлен, сетка расширяется до бесконечности. В общем «вакантной» зоной является оболочка.
Переформулируй более понятно, желательно с картинками нескольких возможных вариантов. Потому как телепатор обнаруживает слишком много вариантов Игру делаешь?
Вот экспорт базы:[sql] -- phpMyAdmin SQL Dump -- version 2.11.3 -- http://www.phpmyadmin.net -- -- Хост: localhost -- Время создания: Авг 08 2009 г., 22:55 -- Версия сервера: 4.1.8 -- Версия PHP: 4.3.10 SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; -- -- База данных: `exp` -- -- -------------------------------------------------------- -- -- Структура таблицы `exp_territory` -- CREATE TABLE IF NOT EXISTS `exp_territory` ( `id` int(10) NOT NULL auto_increment, `x` int(10) NOT NULL default '0', `y` int(10) default NULL, `country_id` int(10) default NULL, `land` char(2) default NULL, `buildings` varchar(10) default NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=cp1251 AUTO_INCREMENT=17 ; -- -- Дамп данных таблицы `exp_territory` -- INSERT INTO `exp_territory` (`id`, `x`, `y`, `country_id`, `land`, `buildings`) VALUES (14, -1, -1, 1, '1', '1'), (13, 1, 0, 1, '1', '1'), (12, 0, 0, 1, '1', '1'), (11, -1, 0, 1, '0', '1'), (10, 1, 1, 1, '1', '1'), (9, 0, 1, 1, '1', '1'), (1, -1, 1, 1, '1', '1'), (15, 0, -1, 1, '1', '1'), (16, 1, -1, 1, '1', '1'); [/sql] Код рытый перерытый, затирал и начинал заново раз 7, вот что есть: PHP: class Territory { function CreateTerritory($side,$userid) { $db = new DB; $max_min = $db->SetQuery("select min(x) minx, max(x) maxx, min(y) miny, max(y) maxy from exp_territory where x%3=0 and y%3=0"); $width = (abs($max_min[0]->minx)+abs($max_min[0]->maxx)); $heigth = (abs($max_min[0]->miny)+abs($max_min[0]->maxy)); $range_x = floor(($width)/6); if ($range_x==0) $range_x=1; $range_y = floor(($heigth)/6); if ($range_y==0) $range_y=1; $coor = array(); print 'Range '.$range_x.'<br>'; switch($side) { case 1: break; case 2: break; case 3: break; case 4: break; case 5: break; case 6: break; case 7: break; case 8: break; default: return -1; } } }
Да, пытаюсь делать игру, а эта задача будет раздавать земли (участки) новым игрокам, т.е. тут фигуры могут быть самые разные. Главное это, не может быть прорех, или как правильно сказать, «вакантных» квадратов, окруженными занятыми. Вот… Картинки прикрепляю 2. Первыя показывает switch, case. Вторая это возможные варианты фигур, по просьбе antonn’a. 1. 2.
выбор идет по одному квадрату в каждую сторону? а то своими 3*3 запутал. на второй картинке нумер 5 частный случай нумера 3 на той же картинке
как вариант - всегда иметь рамку вокруг поля (да, тут поле конечное) и при выборе новой земли обсчитывать окружающие поля - если находим пустое поле то искать путь до этой белой рамки (например Дейкстрой). Если не найдет пути - значит область внутри захваченных земель.
Первое, что приходит в голову - четыре массива с незанятыми квадратами, по два на каждую ось: один с положительными координатами, другой - с модулем отрицательных координат. Сначала ищем координату по одной оси, затем по другой. Поиск координаты достаточно прост: выталкиваем первое значение массива из положительных и отрицательных координат, смотрим, что меньше, то и ближе к центру, а значит - правильнее. Надеюсь, что правильно понял задачу.
вот как бы я это сделал в дельфи http://desksoft.ru/index.php?downloads= ... nts&id=229 (ищет только вверх/вниз/право/лево, без диагоналей) Плюсы - поиск по всему полю, не даст окружить точку в другой стороне карты, минусы - карта конечна. Как это оптимально перенести в ПХП и на базы - без понятия Зайти еще в какой нить форум геймдева, может там подскажут PS и еще один момент - она делает поиск до точки (1,1) которая всегда должна быть свободна
Да квадрат выбирается только 1, центр 9-ти квадратов. Он отсеивается условием (x%3=0, y%3=0). И насчет картинки: Видишь ли я хотел показать выбор СЮ, СЗ, ЮВ, ЮЗ если до этого выбирали только С или толь Ю. Не должно быть 2.2.3, в случае подобной ситуации должно быть 2.1.3
просто так смотреть ближайшие квадраты нельзя, если тебе действительно нужно, чтобы нельзя было окружить точку. Например такой вариант: Код (Text): 00000 01110 01010 01010 01*10 00000 ты хочешь захватить точку показанную звездочкой. Обходя только ближайшие точки ты не увидишь как захватится точка в тупике, потому я и навернул волновой поиск путей
antonn Вроде получилось,:idea: и Я добавил еще одну таблицу "vacancy" и забил ее 8 квадратами которые граничат с самым 1-м квадратом. И вот что получилось. Проверял, вроде работает. PHP: class Territory { function CreateTerritory($side,$userid) { $db = new DB; $txt = '<table border="0"><form action="index.php?id=5" method="post" name="terr_chose" ><tr><td>№</td><td>Выб.</td><td>Край света</td><td>Долгота</td><td>Широта</td></tr>'; switch($side) { case 1: $vacancy = $db->SetQuery("select x,y from exp_vacancy where y>0 and y>(sqrt(x*x))"); srand ((float)microtime()*100); shuffle ($vacancy); for ($i=0;$i<count($vacancy);$i++) { $txt .= '<tr><td>'.($i+1).'</td><td><input name="terr_new" type="radio" value="'.$vacancy[$i]->x.$vacancy[$i]->y.'" /></td><td>Север от Центра Мира</td><td>'.$vacancy[$i]->x.'</td><td>'.$vacancy[$i]->y.'</td></tr>'; if ($i>5) break; } break; case 2: $vacancy = $db->SetQuery("select x,y from exp_vacancy where y>0 and x>0"); srand ((float)microtime()*100); shuffle ($vacancy); for ($i=0;$i<count($vacancy);$i++) { $txt .= '<tr><td>'.($i+1).'</td><td><input name="terr_new" type="radio" value="'.$vacancy[$i]->x.$vacancy[$i]->y.'" /></td><td>Северо-запад от Центра Мира</td><td>'.$vacancy[$i]->x.'</td><td>'.$vacancy[$i]->y.'</td></tr>'; if ($i>5) break; } break; case 3: $vacancy = $db->SetQuery("select x,y from exp_vacancy where x>0 and x>(sqrt(y*y))"); srand ((float)microtime()*100); shuffle ($vacancy); for ($i=0;$i<count($vacancy);$i++) { $txt .= '<tr><td>'.($i+1).'</td><td><input name="terr_new" type="radio" value="'.$vacancy[$i]->x.$vacancy[$i]->y.'" /></td><td>Восток от Центра Мира</td><td>'.$vacancy[$i]->x.'</td><td>'.$vacancy[$i]->y.'</td></tr>'; if ($i>5) break; } break; case 4: $vacancy = $db->SetQuery("select x,y from exp_vacancy where y<0 and x>0"); srand ((float)microtime()*100); shuffle ($vacancy); for ($i=0;$i<count($vacancy);$i++) { $txt .= '<tr><td>'.($i+1).'</td><td><input name="terr_new" type="radio" value="'.$vacancy[$i]->x.$vacancy[$i]->y.'" /></td><td>Юго-запад от Центра Мира</td><td>'.$vacancy[$i]->x.'</td><td>'.$vacancy[$i]->y.'</td></tr>'; if ($i>5) break; } break; case 5: $vacancy = $db->SetQuery("select x,y from exp_vacancy where y<0 and (sqrt(x*x))<(sqrt(y*y))"); srand ((float)microtime()*100); shuffle ($vacancy); for ($i=0;$i<count($vacancy);$i++) { $txt .= '<tr><td>'.($i+1).'</td><td><input name="terr_new" type="radio" value="'.$vacancy[$i]->x.$vacancy[$i]->y.'" /></td><td>Юг от Центра Мира</td><td>'.$vacancy[$i]->x.'</td><td>'.$vacancy[$i]->y.'</td></tr>'; if ($i>5) break; } break; case 6: $vacancy = $db->SetQuery("select x,y from exp_vacancy where y<0 and x<0"); srand ((float)microtime()*100); shuffle ($vacancy); for ($i=0;$i<count($vacancy);$i++) { $txt .= '<tr><td>'.($i+1).'</td><td><input name="terr_new" type="radio" value="'.$vacancy[$i]->x.$vacancy[$i]->y.'" /></td><td>Юго-запад от Центра Мира</td><td>'.$vacancy[$i]->x.'</td><td>'.$vacancy[$i]->y.'</td></tr>'; if ($i>5) break; } break; case 7: $vacancy = $db->SetQuery("select x,y from exp_vacancy where x<0 and (sqrt(x*x))>(sqrt(y*y))"); srand ((float)microtime()*100); shuffle ($vacancy); for ($i=0;$i<count($vacancy);$i++) { $txt .= '<tr><td>'.($i+1).'</td><td><input name="terr_new" type="radio" value="'.$vacancy[$i]->x.$vacancy[$i]->y.'" /></td><td>Запад от Центра Мира</td><td>'.$vacancy[$i]->x.'</td><td>'.$vacancy[$i]->y.'</td></tr>'; if ($i>5) break; } break; case 8: $vacancy = $db->SetQuery("select x,y from exp_vacancy where x<0 and y>0"); srand ((float)microtime()*100); shuffle ($vacancy); for ($i=0;$i<count($vacancy);$i++) { $txt .= '<tr><td>'.($i+1).'</td><td><input name="terr_new" type="radio" value="'.$vacancy[$i]->x.$vacancy[$i]->y.'" /></td><td>Северо-запад от Центра Мира</td><td>'.$vacancy[$i]->x.'</td><td>'.$vacancy[$i]->y.'</td></tr>'; if ($i>5) break; } break; default: return -1; } print $txt.'</table><input type="submit" name="Submit" class="button" value="Сохранить" /></form>'; } function CreateVacancy($xx,$yy) { $db = new DB; $uje_est = $db->SetQuery("select x,y from exp_territory where (x%3=0 and y%3=0) and (x=".$xx."-3 or x=".$xx."+3 or y=".$yy."-3 or y=".$yy."+3)"); $vacs = $db->SetQuery("select x,y from exp_vacancy where (x=".$xx."-3 or x=".$xx."+3 or y=".$yy."-3 or y=".$yy."+3)"); $uje_est = array_merge($uje_est, $vacs); $coors_busy = array(); for ($i=0; $i<count($uje_est);$i++) { $coors_busy[$i]=$uje_est[$i]->x.$uje_est[$i]->y; } if (!in_array(($xx).($yy+3),$coors_busy)) $db->InsertQuery("INSERT INTO exp_vacancy (x,y) VALUES ('".($xx)."','".($yy+3)."')"); if (!in_array(($xx+3).($yy+3),$coors_busy)) $db->InsertQuery("INSERT INTO exp_vacancy (x,y) VALUES ('".($xx+3)."','".($yy+3)."')"); if (!in_array(($xx+3).($yy),$coors_busy)) $db->InsertQuery("INSERT INTO exp_vacancy (x,y) VALUES ('".($xx+3)."','".($yy)."')"); if (!in_array(($xx+3).($yy-3),$coors_busy)) $db->InsertQuery("INSERT INTO exp_vacancy (x,y) VALUES ('".($xx+3)."','".($yy-3)."')"); if (!in_array(($xx).($yy-3),$coors_busy)) $db->InsertQuery("INSERT INTO exp_vacancy (x,y) VALUES ('".($xx)."','".($yy-3)."')"); if (!in_array(($xx-3).($yy-3),$coors_busy)) $db->InsertQuery("INSERT INTO exp_vacancy (x,y) VALUES ('".($xx-3)."','".($yy-3)."')"); if (!in_array(($xx-3).($yy),$coors_busy)) $db->InsertQuery("INSERT INTO exp_vacancy (x,y) VALUES ('".($xx-3)."','".($yy)."')"); if (!in_array(($xx-3).($yy+3),$coors_busy)) $db->InsertQuery("INSERT INTO exp_vacancy (x,y) VALUES ('".($xx-3)."','".($yy+3)."')"); $db->InsertQuery("DELETE FROM exp_vacancy WHERE x=".$xx." and y=".$yy.""); } } Тут две функции, CreateTerritory($side,$userid) - отвечает за поиск "вакантных мест", а CreateVacancy($xx,$yy) - создает вакантные места, в зависимости от новозанятой территории ($xx,$yy). Спасибо огромное, хорошенько покурил, погулял сел и как запор прорвало
Да тут ты прав... Но в том алгоритме, который предлагал ты возможна такая ситуация: т.е. соседей не будет вовсе. А что если в запросе к базе добавить order by и убрать shuffle :?: Что то типа: PHP: $vacancy = $db->SetQuery("select x,y from exp_vacancy where y>0 and y>(sqrt(x*x)) ORDER BY Y DESC"); for ($i=0;$i<count($vacancy);$i++) { $txt .= '<tr><td>'.($i+1).'</td><td><input name="terr_new" type="radio" value="'.$vacancy[$i]->x.$vacancy[$i]->y.'" /></td><td>Север от Центра Мира</td><td>'.$vacancy[$i]->x.'</td><td>'.$vacancy[$i]->y.'</td></tr>'; if ($i>5) break; } Это когда юзер будет регится, то ему будет предлагаться самые "низкие" варианты, в первую очередь.
не понял по скрину - ну такое возможно в алгоритме, а не должно быть? я то это поправлю в пяток строк, не проблема, а вот на пхп все это перевести...
В принципе пойдет, главное вакантные места останутся вакантными, и когда нибудь кто нибудь их займет. Можно правда ускорить этот процесс, но это позже. antonn ты не разбираешься в GD? Как теперь можно все это хозяйство запечатлеть на изображении? Если нетрудно примерчик какой нибудь... Хотя бы одной фигуры из разными цветами.
не, с GD я толком не разбирался, но можешь поискать тут по форуму - был пример рисования колец олимпиады с АА, там попиксельное рисование вроде как (не помню)
kostyl Спасибо тебе добрый человек. Лучше б посоветовал чего нибудь, но конечно не в этом направлении, а в направлении типа "Добавить квадрат (3х3)"