Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 20.11.2011, 18:17   #1
FeonoR
 
Регистрация: 01.10.2011
Сообщений: 4
Печаль Переправа рыцарей и оруженосцев

Доброго всем времени суток. Вроде бы, простите, не дурак, но признаюсь, что эта задача уже сломала мне мозг окончательно. Посему прошу помоши в решении следующей задачи на Делфи:

Условие:
Помогите переправиться с одного берега реки на другой четырем рыцарям А, Б, В и Г и их оруженосцам а, б, в и г , если единственное средство передвижения – лодка, вмещающая трех человек, а по условиям тех времен никто из оруженосцев не должен оставаться в обществе незнакомых рыцарей без своих хозяев.

На форме 3 листбокса: соответственно левый, правый берега и лодка; кнопка.
По двойному щелчку на элементе в любом ЛБксе он должен перемешать(или не-) в лодку(смотря где она) или из лодки(опять же смотря где она).

Вот тот код который я написал, знаю что может содержать ошибки или ещё что-то ненужное...
Код:

var
  Form1: TForm1;
  i, j,k, c,er, x: integer;
  r,o,rol,rob,ero:Byte;
  rside,lside,boat:string;
implementation

{$R *.dfm}

procedure TForm1.lb1Click(Sender: TObject);
begin
if (lb2.Items.Count<3) then
  begin
  lb2.Items.Add((sender as TListBox).Items[(sender as TListBox).Itemindex]);
  (sender as TListBox).DeleteSelected;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);//проверка условий по нажатию кнопки 
begin
 label4.Caption:='';
rob:=0;
rol:=0;
o:=0;
r:=0;
ero:=0;

  for i:=0 to (lb1.Count-1) do
  lside:=lside+' '+lb1.Items[i][1]+lb1.Items[i][length(lb1.Items[i])]+' ';

   for i:=0 to (lb2.Count-1) do
  boat:=boat+' '+lb2.Items[i][1]+lb2.Items[i][length(lb2.Items[i])]+' ';

   for i:=0 to (lb3.Count-1) do
  rside:=lside+' '+lb3.Items[i][1]+lb3.Items[i][length(lb3.Items[i])]+' ';

 if (lb2.Count=1) then r:=1;

 if (lb2.Count>1)and (lb3.Count=0) then
  begin
   { for i:=1 to Length(lside) do
    while Pos('O',lside)<>0 do
     begin
       o:=o+1;
     end;  }


 
  for i:=0 to (lb2.Count-2) do
   for j:=i+1 to (lb2.Count-1) do
    begin
    if (lb2.Items[i][1]<>lb2.Items[j][1]) and
     (lb2.Items[i][length(lb2.Items[i])]=lb2.Items[j][length(lb2.Items[j])]) then
      rol:=1;

    if (lb2.Items[i][1]='Î') and (lb2.Items[i][1]=lb2.Items[j][1]) and
     (lb2.Items[i][length(lb2.Items[i])]<>lb2.Items[j][length(lb2.Items[j])]) then
      o:=o+1;

    if r<>0 then
     if rol<o then ero:=1;

    if (lb2.Items[i][1]='Ð') and (lb2.Items[i][1]=lb2.Items[j][1]) and
     (lb2.Items[i][length(lb2.Items[i])]<>lb2.Items[j][length(lb2.Items[j])]) then
      ero:=1;
     end;    
  end;

 if (lb2.Count>1)and (lb3.Count>0) then
 begin
  for i:=0 to (lb2.Count-2) do
   for j:=i+1 to (lb2.Count-1) do
   begin
    if (lb2.Items[i][1]<>lb2.Items[j][1]) and
     (lb2.Items[i][length(lb2.Items[i])]=lb2.Items[j][length(lb2.Items[j])]) then
    rol:=1;

    if (lb2.Items[i][1]='Î') and (lb2.Items[i][1]=lb2.Items[j][1]) and
     (lb2.Items[i][length(lb2.Items[i])]<>lb2.Items[j][length(lb2.Items[j])]) then
      o:=o+1;
    if r<>0 then
     if rol<o then ero:=1;
   end;

  for i:=0 to (lb3.Count-1) do
   for j:=i+1 to (lb3.Count-2) do
     if (lb3.Items[i][1]='Î') and (lb3.Items[i][1]=lb3.Items[j][1]) and
     (lb3.Items[i][length(lb3.Items[i])]<>lb3.Items[j][length(lb3.Items[j])]) then
      o:=o+1;

  for i:=0 to (lb2.Count-2) do
   for j:=i+1 to (lb3.Count-1) do
   begin
    if (lb2.Items[i][1]='Ð') and (lb2.Items[i][1]<>lb3.Items[j][1]) and
     (lb2.Items[i][length(lb2.Items[i])]=lb3.Items[j][length(lb3.Items[j])]) then
     if o>=2 then
        ero:=1
       else rob:=1;
   end;
 end;


 if (lb2.Left=160)then
  if ((rol=1)or(rob=1)or(r=1)or(o>0)) and (ero=0) then
     begin
     lb2.Left:=344;
     lb1.Enabled:=false;
     lb3.Enabled:=true;
     end
  else Label4.Caption:='incorrect';

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
form1.Height:=194;
c:=0;
rside:='';
lside:='';
boat:='';
 for i:=0 to (lb1.Count-1) do
  lside:=lside+' '+lb1.Items[i][1]+lb1.Items[i][length(lb1.Items[i])]+' ';
end;



procedure TForm1.lb2DblClick(Sender: TObject);
begin
c:=0;
x:=0;
if lb2.Items.Count=0 then  button1.Enabled:=false;
if lb2.Left=160 then
    begin
    lb1.Items.Add(lb2.Items[lb2.Itemindex]);
    lb2.DeleteSelected;
    end;

if lb2.Left=344 then

    begin
    lb3.Items.Add(lb2.Items[lb2.Itemindex]);
    lb2.DeleteSelected;
     end;
end;

procedure TForm1.btn1Click(Sender: TObject); // переправа лодки обратно - делал, чтобы не загружать себя задачей на 2 фронта... наверное нужно как-то в один обработчик сделать...ну или 2кнопки поставить..
begin
 if lb2.Left=344 then
 begin
 lb2.Left:=160;
 lb1.Enabled:=true;
 lb3.Enabled:=false;
 end
end;
FeonoR вне форума Ответить с цитированием
Старый 20.11.2011, 20:36   #2
9i.
Форумчанин
 
Регистрация: 29.09.2011
Сообщений: 103
По умолчанию

перевезите 3х оруженосцев потом 3 хозяив потом оставшихся 2
9i. вне форума Ответить с цитированием
Старый 21.11.2011, 00:40   #3
FeonoR
 
Регистрация: 01.10.2011
Сообщений: 4
По умолчанию

Суть программы не в том, как кого перевозить, а в том, чтобы проверить действия пользователя на соответствие\несоответствие условиям и сказать правильный ход или нет, а я не могу правильно написать условия, в этом и прошу помощи.
FeonoR вне форума Ответить с цитированием
Старый 21.11.2011, 02:49   #4
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

Имхо, вас слишком затянуло в GUI. Какие бы кнопки, листбоксы и прочие едиты юзер бы ни нажимал, всё должно сводиться к простым вызовам:

1) проверка допустимости операции на сущностями.
Нужно убедиться, что:
-- все переданные сущности находятся в данный момент на одном берегу с лодкой
-- их меньше 4 (но больше 0)
-- переправляющиеся оруженосцы (если они есть) не окажутся без хозяев в лодке/на другом берегу в присутствии чужих рыцарей
-- оставшиеся оруженосцы (если они есть) не окажутся без хозяев в присутствии чужих рыцарей на своём берегу

2) если вешепреведенная проверка успешна, то операция выполняется:
-- сущности переносятся на противоположный берег
-- лодка переносится на противоположный берег
Гуй обновляется, всё повторяется с начала.

Если проверка не прошла, юзеру выводится сообщение, что что-то не так, и операция не выполняется.

Вот полная программа, сущности передаются строкой, текущее их расположение задано строками leftSide, rightSide, позиция лодки кодируется переменной boat ('L' или 'R'):

Код:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils, Classes;

var
  leftSide, rightSide: string;
  boat: char;


// --  --
function loCase(c: char): char;
begin
  result := lowerCase(c)[1];
end;

// --  --
function has(who: char; const s: string): boolean;
begin
  result := (1 <= Pos(who, s));
end;

// --  --
function hasAnyKnights(const s: string): boolean; overload;
begin
  result := has('A', s) or has('B', s) or has('C', s) or has('D', s);
end;

// --  --
function hasAnyKnights(const s: string; okKnight: char): boolean; overload;
begin
  result := hasAnyKnights(s) and not has(okKnight, s);
end;

// --  --
procedure makeOperation(const s: string);
var
  i: Integer;
  side, otherSide: string;
begin
  if ('L' = boat) then begin
    //
    side := leftSide;
    otherSide := rightSide;
  end
  else begin
    //
    side := rightSide;
    otherSide := leftSide;
  end;
  //
  for i := 1 to length(s) do begin
    //
    Delete(side, Pos(s[i], side), 1);
    otherSide := otherSide + s[i];
  end;
  //
  if ('L' = boat) then begin
    //
    leftSide := side;
    rightSide := otherSide;
    boat := 'R';
  end
  else begin
    //
    rightSide := side;
    leftSide := otherSide;
    boat := 'L';
  end;
  //
  if ('L' = boat) then
    writeLn('L: ', leftSide:8, ' []    | R: ' + rightSide:8)
  else
    writeLn('L: ', leftSide:8, '       | R: ' + rightSide:8, ' []')
end;

// --  --
function checkOperation(const s: string): boolean;
var
  i: Integer;
  side, otherSide: string;
begin
  result := true;
  //
  //-- их меньше 4 (но больше 0)
  if ((0 < length(s)) and (length(s) < 4)) then begin
    //
    if ('L' = boat) then begin
      //
      side := leftSide;
      otherSide := rightSide;
    end
    else begin
      //
      side := rightSide;
      otherSide := leftSide;
    end;
    //
    //-- все переданные сущности находятся в данный момент на одном берегу с лодкой
    for i := 1 to length(s) do
      if (not has(s[i], side)) then begin
        //
        // -- кто-то не на той стороне!
        result := false;
        break;
      end;
    //
    if (result) then begin
      //
      for i := 1 to length(s) do begin
        //
        case (s[i]) of

          'a'..'d': begin
            //
            // -- переправляющиеся оруженосцы (если они есть) не окажутся без хозяев в лодке/на другом берегу в присутствии чужих рыцарей
            if (not has(upCase(s[i]), s)) then
              result := not hasAnyKnights(s, upCase(s[i])) and not hasAnyKnights(otherSide, upCase(s[i]));
          end;

          'A'..'D': begin
            //
            //-- оставшиеся оруженосцы (если они есть) не окажутся без хозяев в присутствии чужих рыцарей на своём берегу
            if (has(loCase(s[i]), side) and not has(loCase(s[i]), s)) then
              result := not hasAnyKnights(side, s[i]);
          end;
        end;
        //
        if (not result) then
          break;
      end;
    end;
  end
  else
    result := false;    // вас слишком много
  //
  if (result) then
    makeOperation(s)
  else
    writeLn('Not allowed: [', s, ']');
end;

// -- main --

begin
  leftSide := 'AaBbCcDd';
  rightSide := '';
  boat := 'L';
  //
  if (checkOperation('abc')) then
    if (checkOperation('a')) then
      if (checkOperation('ad')) then
        if (checkOperation('a')) then
          if (checkOperation('BCD')) then
            if (checkOperation('Bb')) then
              if (checkOperation('BA')) then
                if (checkOperation('c')) then
                  if (checkOperation('cab')) then
                    writeLn('We make it!');
end.
Навесить на это дело гуй — пара пустяков.

> перевезите 3х оруженосцев потом 3 хозяив

лодка сама не плавает
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 21.11.2011, 03:26   #5
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

ха, забыл ещё условие:

-- если плывёт рыцарь, все оруженосцы на другой стороне должны быть при хозяевах (или их хозяева должны плыть на лодке)

Исправить исходное сообщение не могу, т.к. оно становится больше 5000 символов.
Вот как выглядит обновлённая проверка:

Код:
      for i := 1 to length(s) do begin
        //
        case (s[i]) of

          'a'..'d': begin
            //
            // -- переправляющиеся оруженосцы (если они есть) не окажутся без хозяев в лодке/на другом берегу в присутствии чужих рыцарей
            if (not has(upCase(s[i]), s)) then
              result := not hasAnyKnights(s, upCase(s[i])) and not hasAnyKnights(otherSide, upCase(s[i]));
          end;

          'A'..'D': begin
            //
            //-- оставшиеся оруженосцы (если они есть) не окажутся без хозяев в присутствии чужих рыцарей на своём берегу
            if (has(loCase(s[i]), side) and not has(loCase(s[i]), s)) then
              result := not hasAnyKnights(side, s[i]);
            //
            //-- если плывёт рыцарь, все оруженосцы на другой стороне должны быть при хозяевах
            //-- (или их хозяева должны плыть на лодке)
            result := result and hasMasters(otherSide, s);
          end;
        end;
        //
        if (not result) then
          break;
      end;
ну и доп. функция понадобилась:

Код:
// --  --
function hasMasters(const s: string; const onBoat: string): boolean;
var
  i: Integer;
begin
  result := true;
  //
  for i := 1 to length(s) do begin
    //
    case (s[i]) of

      'a'..'d': result := has(upCase(s[i]), s) or has(upCase(s[i]), onBoat);

    end;
    //
    if (not result) then
      break;
  end;
end;
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 21.11.2011, 09:15   #6
FeonoR
 
Регистрация: 01.10.2011
Сообщений: 4
По умолчанию

Спасибо - буду разбираться!
FeonoR вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Переправа солдат Toni Milano Помощь студентам 6 13.10.2011 09:22
Переправа через реку mivel Помощь студентам 3 19.04.2010 21:41
Переправа Spark3r Общие вопросы C/C++ 6 13.01.2010 12:35