Модераторы: LSD
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Шахматы в PL\SQL 
:(
    Опции темы
Golar
Дата 16.5.2006, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 8.5.2006
Где: Россия, Воронеж

Репутация: нет
Всего: нет



Добрый день, мне нужен совет по процедурам в  PL\SQL. Можно ли писать commit и roolback внутри процедур и функций? Мне необходимо проверить можно ли сделать ход из одной клетки (x1,y1) в другую (x2,y2) на шахматной доске. Я примерно набросала функцию, пожалуйста посмотрите.
У меня есть таблица Chess, хранящая ситуацию на досках:
Код
/* col = 1 - white; 0 - ничего, -1 - черная */
Create table Chess
( Doska integer,
  St integer CHECK ((st>=1) and (st<=8)),  
  Str integer CHECK ((str>=1) and (str<=8)),
  Fig varchar2(1),
  Col integer
);

Процедура проверки (здесь rek=true, если вошли по рекурсии):
Код
CREATE OR REPLACE FUNCTION Mozhno(d in integer,x1 in integer,y1 in integer,x2 in integer,y2 in integer,rek in boolean) RETURN boolean
IS

Cursor SearchF( d,x,y integer) IS /*по коорд ищет фигуру и цвет*/
 Select fig, col
 From Chess
 where (Doska = d) and (st = x) and (str = y);

Cursor SearchK( d integer, f varcar2(1), c integer) IS /*по фигуре и цвету ищет коорд*/
 Select st, str
 From Chess
 where (Doska = d) and (fig = f) and (col = c);

Cursor Search(d integer,c integer) IS /* ищет все занятые координаты опр цветом*/ 
 Select st,str
 From Chess
 where (Doska = d) and (col=c);

 x,y integer;
 fig1,fig2 varchar2(1);
 col1,col2 integer;
 boy,vs boolean;
BEGIN
/*ищем клетку с кот надо делать ход*/
open SearchF (d, x1,y1);
fetch SearchF into fig1,col1;
vs:= (col1 = 0)
close SEarchF;
if vs then 
        if not rek DBMS_OUTPUT.put_line('Nechem xodit');
        end if;
        return false;        
else
/*смотрим клетку, куда идем*/
   open SearchF(d, x2,y2);
   fetch SearchF into fig2,col2;
   vs:=not(col2 = 0);
   close SEarchF;
end if;
   if (vs and (col1=col2)) 
        if not rek DBMS_OUTPUT.put_line('Nelzya,tam nawa figura');
        end if;
        return false;
   else
   if vs and (col1<>col2)
              boy:=true;
   else boy:=false;
   end if;
      case fig1 
      when 'p','P' then begin
                 res:=( ((x1=x2)and((y2=y1+col1)or(y2=y1+2*col1)and((y1=1+col1)or(y1=8+col1))))
                 or(boy and ((x1=x2+1)or(x1=x2-1))and(y2=y1+clo1)));
                 if not rek
                     if res DBMS_OUTPUT.put_line('Mozhno xodit');
                     else DBMS_OUTPUT.put_line('Nelzya xodit');
                     end if;
                 end if;
                 return res;
                end;
     when  'l','L' then begin
                 if (y1=y2)
                   if (x2-x1)<0
                           l:=-1;
                   else  l:=1;
                   end if;
                   k=0; 
                else
                if (x1=x2)
                    if  (y2-y1)<0
                           k:=-1;
                    else   k:=1;
                    end if;
                    l=0; 
                else
                 if not rek DBMS_OUTPUT.put_line('Nelzya xodit');
                 end if;
                 return false; /*расположена не по направлению*/ 
                end if;
               end if;
               vs:= true;/*нет др. фигуры на пути*/
               x:=x1;
               y:=y1;
              while vs and not((y<>y2)and(x<>x2))
                 loop
                  x:=x+l;
                  y:= y+k;
                  open SearchF(d,x,y);
                  fetch Search in fig2,col2;
                  close Search;
                  vs:= col2=0;
                 end loop;
              if (y = y2)and(x = x2)
                  if not rek DBMS_OUTPUT.put_line('Mozhno xodit');
                  end if;
                  return true;
              else 
                  if not rek DBMS_OUTPUT.put_line('Nelzya xodit');
                  end if;
                  return false;
              end if;
            end;

   when 'h','H'  then  begin
             res:=((x1=x2-1)and((y1=y2-2)or(y1=y2+2)))or
                  ((x1=x2+1)and((y1=y2-2)or(y1=y2+2)))or
                  ((x1=x2-2)and((y1=y2-1)or(y1=y2+1)))or 
                  ((x1=x2+2)and((y1=y2-1)or(y1=y2+1)));
             if not rek
                     if res DBMS_OUTPUT.put_line('Mozhno xodit');
                     else DBMS_OUTPUT.put_line('Nelzya xodit');
                     end if;
                 end if;     
             return res;                     
           end;

   when 's','S' then 
           begin
            k:=0;l:=0;
            if (x2-x1>0)and(y2-y1>0)   
                   k:=1;l:=1;end if;
            if (x2-x1>0)and(y2-y1<0)   
                   k:=-1;l:=1;end if;
            if (x2-x1<0)and(y2-y1>0)   
                   k:=1;l:=-1;end if;
            if (x2-x1<0)and(y2-y1<0)   
                   k:=-1;l:=-1;end if;
            if (k=0)and(l=0)
                   if not rek DBMS_OUTPUT.put_line('Nelzya xodit');
                   end if;
                   return false;/*расположена не по направлению*/
            end if;
            vs:= true;/*нет др. фигуры на пути*/
            x:=x1;
            y:=y1;
            while vs and not((y<>y2)and(x<>x2))
                 loop
                  x:=x+l;
                  y:= y+k;
                  open SearchF(d,x,y);
                  fetch Search in fig2,col2;
                    close Search;
                  vs:= col2=0;
                 end loop;
            if (y = y2)and(x = x2)
                if not rek DBMS_OUTPUT.put_line('Mozhno xodit');
                  end if;
                return true;
            else 
                if not rek DBMS_OUTPUT.put_line('Nelzya xodit');
                  end if;
                return false;
            end if;
           end;

    when  'k','K' then
            begin
            res:= ((x1=x2)and((y2=y1+1)or(y2=y1-1)))or
                  ((y1=y2)and((x2=x1+1)or(x2=x1-1)))or
                  ((x2=x1+1)and((y2=y1+1)or(y2=y1-1)))or
                  ((x2=x1-1)and((y2=y1+1)or(y2=y1-1)));
             if not rek
                     if res DBMS_OUTPUT.put_line('Mozhno xodit');
                     else DBMS_OUTPUT.put_line('Nelzya xodit');
                     end if;
                 end if;           
            return res;
           end;
     when  'f','F'  then
            begin
            k:=0;l:=0;
            if (x2-x1>0)and(y2-y1>0)   
                   k:=1;l:=1;end if;
            if (x2-x1>0)and(y2-y1<0)   
                   k:=-1;l:=1;end if;
            if (x2-x1<0)and(y2-y1>0)   
                   k:=1;l:=-1;end if;
            if (x2-x1<0)and(y2-y1<0)   
                   k:=-1;l:=-1;end if;
            if (str1=str2)
                if (x2-x1)<0
                           l:=-1;
                else
                  l:=1;
                end if;
               k=0; 
            else
            if (x1=x2)
                if  (y2-y1)<0
                           k:=-1;
                else
                    k:=1;
                end if;
                 l=0; 
             end if;
            end if;
            if (k=0)and(l=0)
                  if not rek DBMS_OUTPUT.put_line('Nelzya xodit');
                  end if;
               return false; /*расположена не по направлению*/ 
            end if;
             x:=x1;
             y:=y1;
             vs:= true;/*нет др. фигуры на пути*/
            while vs and not((x<>x2)and(y<>y2))
                 loop
                  x:=x+l;
                  y:= y+k;
                  open SearchF(d,x,y);
                  fetch Search in fig2,col2;
                    close Search;
                  vs:= col2=0;
                 end loop;
            if (x = x2)and(y = y2)
                if not rek DBMS_OUTPUT.put_line('Mozhno xodit');
                  end if;
                return true;
            else 
                if not rek DBMS_OUTPUT.put_line('Nelzya xodit');
                  end if;
                return false;
            end if;
           end;

           end;
       end//case
      
  end if;
end if;

if (not rek) then //т.е еще можно ходить и не рекурсия, тогда ходим
    Update Chess /*ушли с клетки*/
    set fig= ' ',col = 0
    where (doska = d)and(st = x1)and(str = y1);
              
    Update Chess /*пришли в клетку*/
    set fig= fig1,col = col1
    where (doska = d)and(st = x2)and(str = y2);

    /*теперь смотрим, есть ли шах нашему королю*/
    if col1 = 1 
       open SearchK(d,'k',col1);
    else open SearchK(d,'K',col1);
    end if;   
    fetch SearchK in x,y;
    close SearchK;

    open Search(d,col1*(-1));/*нашли все ф-ры др цвета*/
    fetch Search in x1,y1;
    vs:= true;
    while (Search%found) and vs /*пока есть ф-ра и не нашли шах*/
     loop
        /*можно ли ходить ф-рой др цвета на нашего короля*/
        vs=  Mozhno(d,x1,y1,x,y, true); 
        fetch Search in x1,y1;
     end loop;
    
    if vs then /*если вышли из цикла, потому что нашли ф-ру, дающую шах*/
           return false;
    else 
      return true;
    end if;
   Rollback;
end if;
end Mozhno;
    
PM MAIL   Вверх
batigoal
Дата 16.5.2006, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: 2
Всего: 151



Цитата(Golar @  16.5.2006,  17:05 Найти цитируемый пост)
Можно ли писать commit и roolback внутри процедур и функций?

Можно. Но вот оправданно ли это в данной ситуации, судить не берусь (про себя думаю, что нет: всё-таки откат транзакции - это не инструмент программной логики). 


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
Golar
Дата 16.5.2006, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 8.5.2006
Где: Россия, Воронеж

Репутация: нет
Всего: нет



А как Вы посоветуете здесь "откатиться"? Просто, заранее оправдаюсь, с  PL\SQL  имею дело не больше недели и поэтому есть большие пробелы в умении им пользоваться. Не посоветуете, может в корне по-другому сделать?  smile  
PM MAIL   Вверх
Sqlninja
Дата 16.5.2006, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 353
Регистрация: 15.5.2006
Где: San Francisco, CA

Репутация: 13
Всего: 13



Совершенно верно - COMMIT и ROLLBACK - это просто операторы управления транзакциями. Использовать их для описания логики - плохая практика. Опишите все ситуации явно, через CASE или IF THEN. В крайнем случае через исключения. И еще смените стиль. Ваш код ужжжасен.  smile  


--------------------
It's better to burn out than to fade away.
PM MAIL WWW ICQ   Вверх
Golar
Дата 16.5.2006, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 8.5.2006
Где: Россия, Воронеж

Репутация: нет
Всего: нет



я не спорю, был бы прекрасен - за помощью бы не обращалась! smile как его сменить - поконкретней! 
PM MAIL   Вверх
Sqlninja
Дата 16.5.2006, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 353
Регистрация: 15.5.2006
Где: San Francisco, CA

Репутация: 13
Всего: 13



Просто сделайте так, чтобы откатываться не пришлось. ROLLBACK - это звучит гордо, но не используйте его не в исключительных ситуациях.

Кроме того, оставьте в покое базу! Создайте структуры типа RECORD и меняйте их динамически, если уж хотите написать шахматы на PL\SQL. Он вообще мало для этого подходит.  smile  


--------------------
It's better to burn out than to fade away.
PM MAIL WWW ICQ   Вверх
Golar
Дата 16.5.2006, 16:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 8.5.2006
Где: Россия, Воронеж

Репутация: нет
Всего: нет



Конечно! Знаете, я поняла уже, что Pl\SQL для этого мало подходит!!! Но задание сделать это все  на нем, родимом!   smile  хотя, прикольно! smile  А как без отката проверить нет ли угрозы королю?  

Это сообщение отредактировал(а) Golar - 16.5.2006, 16:50
PM MAIL   Вверх
Sqlninja
Дата 16.5.2006, 16:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 353
Регистрация: 15.5.2006
Где: San Francisco, CA

Репутация: 13
Всего: 13



Ладно, вот вам советы:

1)  Давайте всем переменным осмысленные имена. Ничего, если они будут немного длиннее.
2)  Не используйте таблицы, это нерационально в Вашем случае.
3)  Используйте записи и коллекции.
4)  Разбейте Ваш код на маленькие процедуры и функции.
5)  Остальные советы сводятся к общим best practices по программированию.
 


--------------------
It's better to burn out than to fade away.
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Oracle"
Zloxa
LSD

Данный раздел предназначен для обсуждения проблем с Oracle Database, другие продукты Oracle здесь не обсуждаются. Просьба при создании темы, придерживаться следующих правил:

  • при создании темы давайте ей осмысленное название, описывающее суть проблемы
  • указывайте используемую версию базы, способ соединения и язык программирования
  • при ошибках обязательно приводите код ошибки и сообщение сервера
  • приводите код в котором возникла ошибка, по возможности дайте тестовый пример демонстрирующий ошибку
  • при вставке кода используйте соответсвующие теги: [code=sql] [/code] для подсветки SQL и PL/SQL кода, [code=java] [/code] - для Java, и т.д.

  • документация по Oracle: 9i, 10g, 11g
  • книги по Oracle можно поискать здесь
  • действия модераторов можно обсудить здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Zloxa, LSD.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Oracle | Следующая тема »


 




[ Время генерации скрипта: 0.0762 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.