iT邦幫忙

DAY 30
8

哇咧~夠了(Oracle SQL)系列 第 27

卅、猜一猜,用SQL Plus 設計個小遊戲之10(Oracle SQL 2013/10/15)

來猜數字吧!到底是多少?
奮戰了30天,終於在最後這一天,把這支老是猜不中我到底要幹碼的小小程式給完成了?
卻在剛剛這一刻發現,IT邦你嘛幫幫忙,官網又連不上了,別老是製造緊張氣氛嘛!
但,到底是官網?還是我家網路斷了?真是難猜,

原來是公司網路出了問題...真正是一波三折..
本想用陣列的,這個議題擺了5,6天,腦袋抓終於提出抗議,
我只好乖乖配合改變作法,偷機取巧運用旁門走道給解決了,
這是個出題給電腦猜的遊戲,只須逐次回報它結果即可。

以下SQL,複製到記事本,另存成為d:\day-30-package.sql

-- sqlplus下 SQL> @d:\day-30-package.sql

drop TABLE YAFUU_GUESS_ARRAY;

CREATE TABLE YAFUU_GUESS_ARRAY
   (  SEQ_ID  NUMBER,
      GS01    NUMBER,
      GS02    NUMBER,
      GS03    NUMBER,
      GS04    NUMBER,
      GS_FLAG NUMBER,
      REMARK  VARCHAR2 ( 2000 BYTE )
   );

CREATE UNIQUE INDEX YAFUU_GUESS_ARRAY_N1 ON YAFUU_GUESS_ARRAY (SEQ_ID);

drop table YAFUU_GUESS_HISTORY;

CREATE TABLE YAFUU_GUESS_HISTORY
   (  SEQ_ID   NUMBER,
      GS01     NUMBER,
      GS02     NUMBER,
      GS03     NUMBER,
      GS04     NUMBER,
      GS0A     NUMBER,
      GS0B     NUMBER,
      GS_MATCH VARCHAR2 ( 2000 BYTE ),
      REMARK   VARCHAR2 ( 240 BYTE )
   );

CREATE UNIQUE INDEX YAFUU_GUESS_HISTORY_N1 ON YAFUU_GUESS_HISTORY(SEQ_ID);

create or replace PACKAGE YAFUU168 AS
   FUNCTION MAIN (V_TMP IN VARCHAR2 ) return varchar2;        --主流程
   PROCEDURE INIT_GUESS;                                      --初始化設定
   FUNCTION SHOW_HISTORY RETURN VARCHAR2;                     --當輸入非規定訊息時候,顯示說明以及歷史紀錄
   FUNCTION GET_NEXT_GUESS RETURN VARCHAR2;                   --計算下一組猜測值
   FUNCTION SHOW_GUESS RETURN VARCHAR2;                       --顯示下一組猜測值
   PROCEDURE UPDATE_RESULT(V_TMP VARCHAR2);                   --篩選不符資格者,避免迴圈檢查數過多,Delay
   procedure KILL_SOME_SAMPLES;                               --更新不符合樣本為不合格
   FUNCTION GET_THE_BEST (v_seq_id number) RETURN VARCHAR2;   --找尋最佳解
END yafuu168;
/

create or replace package body YAFUU168 as
   function main (V_TMP in varchar2 ) return varchar2 is --主流程
      PRAGMA AUTONOMOUS_TRANSACTION;
      V_MSG  varchar2(2000); 
   begin
      if UPPER(V_TMP) = 'NEW' then  --重頭玩過
         INIT_GUESS;  --初始化設定
         V_MSG := GET_NEXT_GUESS; --Get v_next Guess
         if V_MSG = 'OK' then  --1 st=1234,2 v_nd = 5678,此版本不改邏輯
            V_MSG := SHOW_GUESS; --Show the Guess....and wait....
         else
            null;  --不會發生
         end if;
         --
      ELSIF UPPER(V_TMP) = 'EXIT' then  --離開
         INIT_GUESS;  --初始化設定
         V_MSG := 'Bye!';
         --
      ELSIF V_TMP in ('00','01','02','03','04','10','11','12','13','20','21','22','30','40') then  --檢核猜測結果
         --
         UPDATE_RESULT(V_TMP); --將結果更新到最後一次的猜測,供後續檢測用
         --
         if V_TMP = '40' then  --Bingo
            --INIT_GUESS;  --初始化設定
            V_MSG := 'Bingo!'||CHR(13)||CHR(10)||  SHOW_HISTORY;
            --
         else  --Not yet finish, keep guess
            V_MSG := GET_NEXT_GUESS; --Get v_next Guess
            if V_MSG = 'OK' then --確實可找到下一組的情況下
               V_MSG := SHOW_GUESS; --Show the Guess....and wait....
            else  --NG
               V_MSG := '@@@ 推算不出結果,請確認!'||CHR(13)||CHR(10)||CHR(13)||CHR(10)|| SHOW_HISTORY;
            end if;
            --V_MSG := '加油!男孩!.....';  --老大參與加油!男孩!的國片演出駱駝一角,為守護糖廠盡一份力!
         end if;
      else  ---當亂輸一通發生時。
         V_MSG := '.......OOXX.......!'||CHR(13)||CHR(10)||SHOW_HISTORY;
      end if;
      --
      return  V_MSG;
   end;
   --

   procedure INIT_GUESS is  --初始化設定
      V_TMP varchar2 ( 2000 ) :=
         '0012346;0022367;0031236;0041489;0051679;0061479;0073456;0083789;0091567;0105678;0112359;0121238;'||
         '0131689;0143479;0151569;0163469;0173489;0183569;0191378;0201379;0213567;0225679;0231245;0242689;'||
         '0251356;0264568;0271579;0283478;0292379;0303468;0311457;0321359;0332569;0342479;0352459;0362467;'||
         '0372478;0381258;0391267;0402678;0412347;0421247;0434567;0441589;0451467;0462368;0475789;0483457;'||
         '0492458;0504679;0512348;0521289;0532345;0541278;0551678;0561789;0571257;0582468;0593578;0601578;'||
         '0613458;0625689;0631369;0642378;0653589;0661389;0672789;0681367;0692679;0702356;0713678;0721568;'||
         '0732456;0741246;0754789;0761269;0772457;0781358;0796789;0802579;0811478;0821259;0831249;0841237;'||
         '0854678;0861346;0872568;0881248;0894689;0902389;0911469;0922349;0931268;0942358;0952369;0961256;'||
         '0971456;0983689;0992589;1001279;1011468;1022567;1033679;1044569;1054589;1061458;1072357;1081347;'||
         '1094578;1101459;1111235;1123579;1132489;1142469;1151348;1161357;1171239;1181368;1191349;1201345;'||
         '1212578;1223459;1231234;1243467;1253568;1264579;';
      V_CNT number;
   begin
      select COUNT ( * )  into V_CNT  from YAFUU_GUESS_ARRAY;
      --檢查樣本庫的筆數,確認是否正常。由於是非連續執行的運作方式,中途可能會被修改樣本。
      if V_CNT <> 126 then
         --第一次執行、或資料庫被刪除、新增了,重新設定之。
         delete   from YAFUU_GUESS_ARRAY;
         --拆解資料重新環原
         for I in 1 .. 126   LOOP
            insert  into YAFUU_GUESS_ARRAY
            (  SEQ_ID, GS01, GS02, GS03, GS04, GS_FLAG )
            values
            (  TO_NUMBER ( SUBSTRB ( V_TMP, ( I - 1 ) * 8 + 1, 3 ) ),
               TO_NUMBER ( SUBSTRB ( V_TMP, ( I - 1 ) * 8 + 4, 1 ) ),
               TO_NUMBER ( SUBSTRB ( V_TMP, ( I - 1 ) * 8 + 5, 1 ) ),
               TO_NUMBER ( SUBSTRB ( V_TMP, ( I - 1 ) * 8 + 6, 1 ) ),
               TO_NUMBER ( SUBSTRB ( V_TMP, ( I - 1 ) * 8 + 7, 1 ) ),
               1 ) ;
         end LOOP;
         commit;
      end if;
      -- 刪除歷史紀錄,可自行修改為可保留紀錄的功能 
      delete from YAFUU_GUESS_HISTORY;
      --還原所有樣本庫全部有效
      update YAFUU_GUESS_ARRAY
          set GS_FLAG = 1,
               REMARK = null;
        --WHERE GS_FLAG != 1;       
      --  
      commit;
   end;
   --

   function SHOW_HISTORY return varchar2 is    --當輸入非規定訊息時候,顯示說明以及歷史紀錄
      cursor C1 is 
         select SEQ_ID, GS01, GS02, GS03, GS04, GS0A, GS0B
           from YAFUU_GUESS_HISTORY
          order by SEQ_ID;
      V_HISTORY  varchar2(2000);      
   begin
      V_HISTORY := '目前電腦猜測的紀錄如下:'||CHR(13)||CHR(10);      
      for I in C1 LOOP      
          V_HISTORY := V_HISTORY||I.SEQ_ID||'.   '||I.GS01||I.GS02||I.GS03||I.GS04||'  結果: '||          
                       I.GS0A||'A '||I.GS0B||'B'||CHR(13)||CHR(10);                       
      end LOOP;
      V_HISTORY := V_HISTORY||'===== End ======'||CHR(13)||CHR(10);      
      --以上如果需要有玩過才顯示,自行增加條件
      --
      V_HISTORY := V_HISTORY||''||CHR(13)||CHR(10);
      V_HISTORY := V_HISTORY||'Help.....'||CHR(13)||CHR(10);
      V_HISTORY := V_HISTORY||'Sql Plus 玩法:'||CHR(13)||CHR(10);
      V_HISTORY := V_HISTORY||'1. SQL> Set verify off.'||CHR(13)||CHR(10);
      V_HISTORY := V_HISTORY||'2. SQL> select YAFUU168.main('||CHR(39)||CHR(38)||'reply'||CHR(39)||') from dual;'||CHR(13)||CHR(10);
      V_HISTORY := V_HISTORY||'3. SQL> / [Enter]'||CHR(13)||CHR(10);
      V_HISTORY := V_HISTORY||'NEW  = 重玩,每次重新玩都必須執行這個參數.'||CHR(13)||CHR(10);
      V_HISTORY := V_HISTORY||'EXIT = 離開.'||CHR(13)||CHR(10);
      --
      return V_HISTORY;  --未來是Function      
      --dbms_output.put_line(v_history);
   end;
   --

   function GET_NEXT_GUESS return varchar2 is   --計算下一組猜測值
      V_MSG  varchar2(2000);  
      V_CNT number;
   begin
      --刪除不合格的樣本
      KILL_SOME_SAMPLES;
      --取得目前回合數
      select nVL(max(SEQ_ID), 0) SEQ_ID      
        into V_CNT
        from YAFUU_GUESS_HISTORY;
      --
      if V_CNT = 0 then
         insert into YAFUU_GUESS_HISTORY (SEQ_ID, GS01, GS02, GS03, GS04, GS0A, GS0B, GS_MATCH, REMARK)
         values (1, 1, 2, 3, 4, null, null, null, null);
         V_MSG := 'OK';
         --
      ELSIF V_CNT = 1 then
         insert into YAFUU_GUESS_HISTORY (SEQ_ID, GS01, GS02, GS03, GS04, GS0A, GS0B, GS_MATCH, REMARK)
         values (2, 5, 6, 7, 8, null, null, null, null);
         V_MSG := 'OK';
         --
      else --第3次以後靠演算出來
         V_MSG := GET_THE_BEST (V_CNT + 1);      --主演算部分..尋找最佳解...check [OK] or [NG]
         --
      end if;
      --
      commit;
      return V_MSG;
   end;
   --

   function SHOW_GUESS  return varchar2 is  --顯示下一組猜測值
      V_MSG  varchar2(2000);  -- add by yafuu 2013/10/12
      cursor C1 is      
         select SEQ_ID, GS01, GS02, GS03, GS04
           from YAFUU_GUESS_HISTORY a
          order by SEQ_ID desc;
   begin
      for I in C1 LOOP
         --
         V_MSG := '第'||I.SEQ_ID||'次我猜: '||I.GS01||I.GS02||I.GS03||I.GS04||'  請告訴我結果是?A?B,ex, 0A1B 請輸入01,依此類推4A0B = 40';
         EXIT;         
      end LOOP;      
      return V_MSG;
   end; 
   --  

   procedure UPDATE_RESULT(V_TMP varchar2) is    --篩選不符資格者,避免迴圈檢查數過多,Delay
      V_GSA  varchar2(3) := SUBSTRB(V_TMP, 1, 1);  --xA
      V_GSB  varchar2(3) := SUBSTRB(V_TMP, 2, 1);  --xB
      V_SEQ_ID  number;
   begin   
      select max(SEQ_ID)   --取得最後的回合數
        into V_SEQ_ID
        from YAFUU_GUESS_HISTORY;
      --
      update YAFUU_GUESS_HISTORY  --將Player回復結果更新回資料庫
          set GS0A = TO_NUMBER(V_GSA),
              GS0B = TO_NUMBER(V_GSB)
       where SEQ_ID = V_SEQ_ID;
      --
      commit;
   end;
   --

   procedure KILL_SOME_SAMPLES is  --更新不符合樣本為不合格
      cursor C_SAMPLE is
         select SEQ_ID, GS01, GS02, GS03, GS04
           from YAFUU_GUESS_ARRAY
          where GS_FLAG = 1;
      cursor D_HISTORY is
         select SEQ_ID, GS01, GS02, GS03, GS04, GS0A, GS0B
           from YAFUU_GUESS_HISTORY
           where GS0A is not null
          order by SEQ_ID;
      V_ALL  number;
      --v_ab varchar2(5);
   begin
   --這裡的比對可以另一個函數?Translate,但沒空仔細研究了。
      for SAM in C_SAMPLE LOOP  --所有有效樣本庫
         for HIST in D_HISTORY LOOP  --拿樣本庫比對歷史紀錄,失敗者註銷樣本庫資格
            V_ALL   := 0;
            --計算數量
            if HIST.GS01 = SAM.GS01 or HIST.GS01 = SAM.GS02 or HIST.GS01 = SAM.GS03 or HIST.GS01 = SAM.GS04 then
               V_ALL := V_ALL + 1;
            end if;
            if HIST.GS02 = SAM.GS01 or HIST.GS02 = SAM.GS02 or HIST.GS02 = SAM.GS03 or HIST.GS02 = SAM.GS04 then
               V_ALL := V_ALL + 1;
            end if;
            if HIST.GS03 = SAM.GS01 or HIST.GS03 = SAM.GS02 or HIST.GS03 = SAM.GS03 or HIST.GS03 = SAM.GS04 then
               V_ALL := V_ALL + 1;
            end if;
            if HIST.GS04 = SAM.GS01 or HIST.GS04 = SAM.GS02 or HIST.GS04 = SAM.GS03 or HIST.GS04 = SAM.GS04 then
               V_ALL := V_ALL + 1;
            end if;
            --
            if V_ALL <> TO_NUMBER(HIST.GS0A) + TO_NUMBER(HIST.GS0B) then
               ----比對不出,已經喪失資格。
               update YAFUU_GUESS_ARRAY
                  set GS_FLAG = 0,
                       REMARK = HIST.GS01 || HIST.GS02 || HIST.GS03 || HIST.GS04 ||'--'||
                                SAM.GS01 || SAM.GS02 || SAM.GS03 || SAM.GS04 ||' == '|| V_ALL || 'vs'|| HIST.GS0A ||'A'||HIST.GS0B ||'B'
                where SEQ_ID = SAM.SEQ_ID;
               EXIT;
            end if;
         end LOOP;
         --
      end LOOP;
      commit;
   end;
   --

   function GET_THE_BEST (V_SEQ_ID number) return varchar2 is    --找尋最佳解
      cursor C_SAMPLE is  --剩下的合格樣本
         select SEQ_ID, GS01, GS02, GS03, GS04
           from YAFUU_GUESS_ARRAY
          where GS_FLAG = 1;
      cursor ROWS24 (V_N1 NUMBER, V_N2 NUMBER, V_N3 NUMBER, V_N4 NUMBER) is  --窮則變、變則通的陣列替代物
         select N1, N2, N3, N4 from --直接變化成24種排列,偷機作法
        (select V_N1 N1, V_N2 n2, V_N3 n3, V_N4 n4 from DUAL union
         select v_n1 n1, v_n2 n2, v_n4 n3, v_n3 n4 From DUAL union
         select V_N1 N1, V_N3 n2, V_N2 n3, V_N4 n4 from DUAL union
         select v_n1 n1, v_n3 n2, v_n4 n3, v_n2 n4 From DUAL union
         select v_n1 n1, v_n4 n2, v_n2 n3, v_n3 n4 From DUAL union
         select v_n1 n1, v_n4 n2, v_n3 n3, v_n2 n4 From DUAL union
         select V_N2 N1, V_N1 n2, V_N3 n3, V_N4 n4 from DUAL union
         select v_n2 n1, v_n1 n2, v_n4 n3, v_n3 n4 From DUAL union
         select v_n2 n1, v_n3 n2, v_n1 n3, v_n4 n4 From DUAL union
         select v_n2 n1, v_n3 n2, v_n4 n3, v_n1 n4 From DUAL union
         select V_N2 N1, V_N4 n2, V_N1 n3, V_N3 n4 from DUAL union
         select V_N2 N1, V_N4 n2, V_N3 n3, V_N1 n4 from DUAL union
         select V_N3 N1, V_N1 n2, V_N2 n3, V_N4 n4 from DUAL union
         select v_n3 n1, v_n1 n2, v_n4 n3, v_n2 n4 From DUAL union
         select V_N3 N1, V_N2 n2, V_N1 n3, V_N4 n4 from DUAL union
         select v_n3 n1, v_n2 n2, v_n4 n3, v_n1 n4 From DUAL union
         select V_N3 N1, V_N4 n2, V_N1 n3, V_N2 n4 from DUAL union
         select V_N3 N1, V_N4 n2, V_N2 n3, V_N1 n4 from DUAL union
         select v_n4 n1, v_n1 n2, v_n2 n3, v_n3 n4 From DUAL union
         select V_N4 N1, V_N1 n2, V_N3 n3, V_N2 n4 from DUAL union
         select V_N4 N1, V_N2 n2, V_N1 n3, V_N3 n4 from DUAL union
         select V_N4 n1, V_N2 n2, V_N3 n3, V_N1 n4 from DUAL union
         select V_N4 N1, V_N3 N2, V_N1 N3, V_N2 N4 from DUAL union
         select v_n4 n1, v_n3 n2, v_n2 n3, v_n1 n4 from DUAL) AA;
      cursor D_HISTORY is  --所有歷史紀錄
         select SEQ_ID, GS01, GS02, GS03, GS04, GS0A, GS0B
           from YAFUU_GUESS_HISTORY
           where GS0A is not null
          order by SEQ_ID desc;
      --
      V_0A  number;
      V_0B  number;
      V_CHK varchar2(2);
      V_MSG  varchar2(10);  
   begin
      V_MSG := 'NG';
      --這裡的比對可以另一個函數?Translate,但沒空仔細研究了。
      for SAM in C_SAMPLE LOOP  --所有有效樣本庫
         for v_nN in ROWS24 (SAM.GS01, SAM.GS02, SAM.GS03, SAM.GS04) LOOP
            for HIST in D_HISTORY LOOP  --拿樣本庫比對歷史紀錄,失敗者註銷樣本庫資格
               V_CHK := 'OK';
               V_0A := 0; V_0B := 0;
               --計算A數量
               if HIST.GS01 = v_nN.N1 then V_0A := V_0A + 1; end if;
               if HIST.GS02 = v_nN.N2 then V_0A := V_0A + 1; end if;
               if HIST.GS03 = v_nN.N3 then V_0A := V_0A + 1; end if;
               if HIST.GS04 = v_nN.N4 then V_0A := V_0A + 1; end if;
               --計算b數量
               if HIST.GS01 = v_nN.N2 or HIST.GS01 = v_nN.N3 or HIST.GS01 = v_nN.N4 then V_0b := V_0b + 1;end if;
               if HIST.GS02 = v_nN.N1 or HIST.GS02 = v_nN.N3 or HIST.GS02 = v_nN.N4 then V_0B := V_0B + 1;end if;
               if HIST.GS03 = v_nN.N1 or HIST.GS03 = v_nN.N2 or HIST.GS03 = v_nN.N4 then V_0B := V_0B + 1;end if;
               if HIST.GS04 = v_nN.N1 or HIST.GS04 = v_nN.N2 or HIST.GS04 = v_nN.N3 then V_0B := V_0B + 1;end if;
               --
               if V_0a != HIST.GS0A or v_0b != HIST.GS0B then  ----比對不出,已經喪失資格。
                  v_chk := 'NG';
                  EXIT;
               end if;
            end LOOP;
            if V_CHK = 'OK' then --找到最佳解
               insert into YAFUU_GUESS_HISTORY (SEQ_ID, GS01, GS02, GS03, GS04, GS0A, GS0B, GS_MATCH, REMARK)
               values (V_SEQ_ID, V_NN.N1, V_NN.N2, V_NN.N3, V_NN.N4, null, null, null, null);
               commit;
               V_MSG := 'OK';
               exit;
            end if;
         end LOOP;
         if V_MSG = 'OK' then
            exit;
         end if;
      end LOOP;
      --
      return V_MSG;
   END;
   --
end YAFUU168;
/
set verify off;
cl scr

prompt 環境建置OK..
prompt 
select 'select YAFUU168.main('||chr(39)||chr(38)||'reply'||chr(39)||') "Guess my number.." from dual;' "拷貝、貼上、執行..." from dual;
prompt 
prompt 第一次,請輸入new

打開SQL Plus連結資料庫後,進到
SQL>
直接執行@d:\day-30-package.sql

它會自動建立好環境

SQL> @d:\day-30-package.sql
已刪除表格.
已建立表格.
已建立索引.
已刪除表格.
已建立表格.
已建立索引.
已建立套裝程式.
已建立套裝程式主體.
環境建置OK..

拷貝、貼上、執行...
--------------------------------------------------------------------------------
select YAFUU168.main('&reply') "Guess my number.." from dual;

第一次,請輸入new

開始囉,用那天的7153測試
SQL> select YAFUU168.main('&reply') "Guess my number.." from dual;

輸入 reply 的值:  new

Guess my number..
--------------------------------------------------------------------------------
第1次我猜: 1234  請告訴我結果是?A?B,ex, 0A1B 請輸入01,依此類推4A0B = 40

SQL> /
輸入 reply 的值:  02

Guess my number..
--------------------------------------------------------------------------------
第2次我猜: 5678  請告訴我結果是?A?B,ex, 0A1B 請輸入01,依此類推4A0B = 40

SQL> /
輸入 reply 的值:  02

Guess my number..
--------------------------------------------------------------------------------
第3次我猜: 2367  請告訴我結果是?A?B,ex, 0A1B 請輸入01,依此類推4A0B = 40

SQL> /
輸入 reply 的值:  02

Guess my number..
--------------------------------------------------------------------------------
第4次我猜: 3456  請告訴我結果是?A?B,ex, 0A1B 請輸入01,依此類推4A0B = 40

SQL> /
輸入 reply 的值:  11

Guess my number..
--------------------------------------------------------------------------------
第5次我猜: 7483  請告訴我結果是?A?B,ex, 0A1B 請輸入01,依此類推4A0B = 40

SQL> /
輸入 reply 的值:  20

Guess my number..
--------------------------------------------------------------------------------
第6次我猜: 6482  請告訴我結果是?A?B,ex, 0A1B 請輸入01,依此類推4A0B = 40

SQL> /
輸入 reply 的值:  00

Guess my number..
--------------------------------------------------------------------------------
第7次我猜: 7153  請告訴我結果是?A?B,ex, 0A1B 請輸入01,依此類推4A0B = 40

SQL> /
輸入 reply 的值:  40

Guess my number..
--------------------------------------------------------------------------------
Bingo!
目前電腦猜測的紀錄如下:
1.   1234  結果: 0A 2B
2.   5678  結果: 0A 2B
3.   2367  結果: 0A 2B
4.   3456  結果: 1A 1B
5.   7483  結果: 2A 0B
6.   6482  結果: 0A 0B
7.   7153  結果: 4A 0B
===== End ======


Guess my number..
--------------------------------------------------------------------------------
Help.....
Sql Plus 玩法:
1. SQL> Set verify off.
2. SQL> select YAFUU168.main('&reply') from dual;
3. SQL> / [Enter]
NEW  = 重玩,每次重新玩都必須執行這個參數.
EXIT = 離開.

7153共跑了7次,效果不好喔,改善方法,倒是不妨考慮,將樣本的排序人工調整一下,
例如:

  1. 把連號的這種往後排
  2. 把7153這種跳躍式取號的優先往前排,用4個數字的標準差,取最大值逆排。
  3. 考慮加入亂數的取樣,沒準,瞎貓碰上死耗子,第3次就搞出個4B。
    不用亂數,是因為亂數,我記得好像oracle 8 以後才有支援吧!

再測試一個5932,哇~才4次就把我的答案找出來~給你個讚!

Guess my number..
----------------------------------
Bingo!
目前電腦猜測的紀錄如下:
1.   1234  結果: 1A 1B
2.   5678  結果: 1A 0B
3.   1498  結果: 0A 1B
4.   5932  結果: 4A 0B
===== End ======

如果想消滅這個環境,
drop TABLE YAFUU_GUESS_ARRAY;
drop table YAFUU_GUESS_HISTORY;
drop PACKAGE YAFUU168 ;

總結,

首先,恭喜完成鍛鍊的眾鐵人,以及努力中的準鐵人,加油!

從第一次看到鐵人賽,第一屆就想參加,但一直很忙,忙著忙著就給忘記了,
很奇怪的是,從接觸電腦的這第30年,看到鐵人30天不間斷,就很有感覺想來參加,緣份吧!
加上初期差點中斷,以為失去資格了,只好另起爐灶,
所以有了這另一組[IT人生]的主題:
鐵人不簡單, 挨踢人生刊, 卅天不間斷, 苦辣加甜酸

終於完成第一次的參賽,感觸頗深。
特別是主辦單位選在光輝的燦爛十月,就是假期特別多,中秋連假,
再來個國慶日差點連假,再加上我公司員工旅遊,
幾乎都是要背著筆記本電腦趴趴走,就怕去了個沒有網路的地方,
就擔心好不容易參加挑戰,就中途夭折,幸好幸好......

Oracle 開發工具很多,但一般都是用Orale Developer 2000的Form, Report來設計的居多,其實直到用過TOAD, SQL Developer, Query Report,...等等工具後,我發現SQL PLus還是頗好用的,我到現在,有些自動排程還是喜歡用它。

這最後倒數10天,心血來潮,想說用SQL Plus來寫個猜數字的遊戲,
本來還擔心寫不出來.....
厚著臉皮,持續抗戰,終於還是趕在最後一張文,截稿了!

耶!這只是個簡單的SQL語言開發,但可能讓很多人想不到SQL Plus也可以這樣玩吧!
寫的過程,並未考慮太多該注意的效能,註解也隨便寫寫,不用太介意,
有興趣的,自己取用吧!

有改寫亂數版本、陣列版本的,可以回饋一下,感謝!

想來個預告明年參賽主題,IT人生中的卅個女人,但,該不會被女王趕出家門吧!
至於技術文...或許女王會給我很好的靈感吧。

[IT人生組] 鐵人不簡單, 挨踢人生刊, 卅天不間斷, 苦辣加甜酸。
http://ithelp.ithome.com.tw/ironman6/player/yafuu168/life/1

[開發技術組]哇咧~夠了(Oracle SQL)
http://ithelp.ithome.com.tw/ironman6/player/yafuu168/dev/1


上一篇
廿九、用SQL Plus 設計個小遊戲之9-小小驗證(Oracle SQL 2013/10/14)
下一篇
整理開發技術組這30篇文,並測試BBCode功能
系列文
哇咧~夠了(Oracle SQL)28
0
CalvinKuo
iT邦大師 7 級 ‧ 2013-10-15 17:29:44

恭喜大大完成鐵人賽。
開心灑花拍手沙發

月半車甫 iT邦研究生 3 級‧ 2013-10-15 19:05:16 檢舉

感謝~哈哈

0
ted99tw
iT邦高手 1 級 ‧ 2013-10-15 19:18:19

yafuu168提到:
IT人生中的卅個女人

哇,A到Z裝不下耶~
喜歡喜歡喜歡

看更多先前的回應...收起先前的回應...
月半車甫 iT邦研究生 3 級‧ 2013-10-15 19:28:12 檢舉

哇,A到Z裝不下耶~

說到這...我身邊的好像都只是A~B之間徘徊,挺難猜到底是裝了幾片水餃?

ted99tw提到:
哇,A到Z裝不下耶~

用德文就可以了開心
abcdefghijklmnopqrstuvwxyz
ä+ö+ü
ß

ted99tw iT邦高手 1 級‧ 2013-10-15 20:48:35 檢舉

期待樓主的曠世鉅著:30個德國女孩的棒棒糖...
喜歡喜歡喜歡

月半車甫 iT邦研究生 3 級‧ 2013-10-15 21:04:23 檢舉

期待樓主的曠世鉅著:30個德國女孩的棒棒糖...

我去哪裡生出30個德國女孩,泰大先開個德文班先

yafuu168提到:
我去哪裡生出30個德國女孩,泰大先開個德文班先

泰大的D槽應該可以找齊三十位德國步兵哈哈

0
總裁
iT邦好手 1 級 ‧ 2013-10-15 20:03:10

這個遊戲我當年在學校也寫過,是組合語言的作業,最麻煩的部分是....產生亂數...Orz

月半車甫 iT邦研究生 3 級‧ 2013-10-15 20:27:04 檢舉

讚~
高階語言用亂數,不值得提啦~ 用高階寫亂數,充充數還可以,要亂真就有點難。
還是組合語言有難度....

0
月半車甫
iT邦研究生 3 級 ‧ 2013-10-16 14:08:41

補充,習慣性,愛用數字跳很大方式出題的,這個方式可以改善猜的次數,
1289(8192,9182,1982...)會排第一。
把應變機制寫到程式內(收集每次4A的內容解析,隨機應變),可以模擬出玩的人的習性。

DECLARE
CURSOR C1 IS
SELECT SEQ_ID,
power ( GS01 - ( GS01 + GS02 + GS03 + GS04 ) / 4, 2 ) +
power ( GS02 - ( GS01 + GS02 + GS03 + GS04 ) / 4, 2 ) +
power ( GS03 - ( GS01 + GS02 + GS03 + GS04 ) / 4, 2 ) +
power ( GS04 - ( GS01 + GS02 + GS03 + GS04 ) / 4, 2 ) stds
FROM YAFUU_GUESS_ARRAY
ORDER BY power ( GS01 - ( GS01 + GS02 + GS03 + GS04 ) / 4, 2 ) +
power ( GS02 - ( GS01 + GS02 + GS03 + GS04 ) / 4, 2 ) +
power ( GS03 - ( GS01 + GS02 + GS03 + GS04 ) / 4, 2 ) +
power ( GS04 - ( GS01 + GS02 + GS03 + GS04 ) / 4, 2 ) desc;
v_seq_id NUMBER := 1001;
BEGIN
FOR i IN c1 LOOP
UPDATE YAFUU_GUESS_ARRAY
set SEQ_ID = V_SEQ_ID
WHERE SEQ_ID = I.SEQ_ID;
V_SEQ_ID := V_SEQ_ID + 1;
END LOOP;
COMMIT;
END;

我要留言

立即登入留言