Добрый день, мне нужен совет по процедурам в 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; |
|