2016-07-02 14 views
0

私はいくつかのデータベース手順に基づいて、Risiko!のゲームのように動作するデスクトップアプリケーションを開発しています。SQLクエリ:別のテーブルの異なる行にテーブルの列のランダムな異なる値を割り当てる方法はありますか

私は、他のプレイヤーに割り当てられた互いに等しいではない行の合計を各プレイヤーに割り当てる必要があります。

私はこのような何かをしようとしましたが、動作しません:

`create or replace PROCEDURE "giveterritory" 
    (idpartita NUMBER,nr_partecipanti number) 
    is 

begin 

DECLARE 

CURSOR cur_file IS 

SELECT * 
FROM Player 
WHERE idgame = Player.idgame ; 

var_cur cur_file%ROWTYPE; 

cont number ; 
nr_territories_gioc_prec number ; 
G1_Terr int ; 
G2_Terr int ; 
G3_Terr int ; 
G1_ID number; 
G2_ID number; 
G3_ID number; 
begin 

cont:=0 ; 

for var_cur in cur_file 

loop 

cont := cont + 1 ; 

    update territory 
    set Player_owner = var_cur.id_Player 
    where ROWNUM = MOD(MOD (number_RANDOM(),42) ,ROWNUM); 
G1_Terr := var_cur.number_territories_tot ; -- mi salvo i territories del primo Player 
G1_ID := var_cur.id_Player ; 
end if ; 
    if (cont=2) then 


    update territory 
    set Player_owner = var_cur.id_Player 
    where ROWNUM = MOD(MOD (number_RANDOM(),42 -G1_Terr) , ROWNUM) and id_territory NOT IN (select Player_owner from territory where ; 

    G2_Terr := var_cur.number_territories_tot ;  
    end if ; 
if (cont=3) then 


    update territory 
    set Player_owner = var_cur.id_Player 
    where ROWNUM <= 42 - G1_Terr - G2_Terr; 
    --where ROWNUM <= 42 - var_cur.number_territories_tot * 2 ; 
G3_Terr := var_cur.number_territories_tot ; 
end if ; 
end loop; 
end; 

end;` 

number_randomコード:私が正しく理解していれば

 create or replace FUNCTION "NUMBER_RANDOM" 
     return NUMBER 
     is 
     numbrndm int; 
     begin 

     select dbms_random.value(1,99999999) into numbrndm 
     from dual; 
    return numbrndm; 
    end; 
+2

ご質問はありますか?サンプルデータと望ましい結果が役立ちます。 –

+0

物事を無作為化する方法はたくさんありますが、構造とサンプルデータを投稿すると便利です。次に、もう1つの質問は、あなたの地域がバランスが取れるようにランダムに、あるいはより多くのラウンドロビンを本当にしたいのですか? – Matt

+0

平衡化とランダム化 –

答えて

0

、あなたは、各プレイヤーaを割り当てるしようとしています領土のランダムなセット?

場合は、地域をランダムにソートしてラウンドロビンに割り当てます。これを行うべきであるMERGEステートメントがあります。軽微な構文エラーについてはお詫び申し上げます:私は今Oracleデータベースの前にいません。

MERGE INTO territory t 
USING (
WITH players AS (SELECT rownum player#, id_player 
        FROM player 
        WHERE idgame=:idgame), 
players_count AS (SELECT count(*) players_count FROM players) 
-- Get the id_player for each assignment 
SELECT assignedt.id_territory, p.id_player 
FROM 
(
    -- Assign the randomly-ordered territories to players in round-robin format 
    SELECT randt.id_territory, 
    mod(rownum, pc.players_count)+1 player# 
    FROM (
    -- Query the territories in a random order 
    SELECT t.id_territory 
    FROM territory t 
    ORDER BY dbms_random.random) randt, players_count pc 
    -- Optional: 
    -- ... add a where clause to limit rownum <= some number to make 
    -- ... sure each player receives an even number of territories. 
    -- ... You'd need the count of territories to do that. 
) assignedt inner join players p on p.player# = assignedt.player# 
) u 
ON (u.id_territory = t.id_territory) 
WHEN MATCHED THEN UPDATE SET t.id_player = u.id_player; 
0

私は、各行のSQL selectに乱数列を挿入します。次に、SQLで乱数でレコードセットを直接注文することができます。

プレイヤーと地域リストの両方でこれを行います。

この例は、任意の数の地域およびプレーヤーで機能するはずです。領土が均等に分割されない場合、プレイヤーは1つの余分な領域をランダムに取得します。

地域リストを一度ランダムに順番に繰り返します。私たちは最後までプレイヤーのリストを進んでから、再びプレイヤーリストをリロードします。これは必要な回数だけ発生します。

構文やロジックについてはこれを修正する必要があります。私はそれをテストするOracleインスタンスがありません。

CREATE OR REPLACE PROCEDURE giveterritory (pID_GAME PLS_INTEGER) IS 
    CURSOR c_player IS 
     SELECT id_player, dbms_random.value() rnd 
     FROM players 
     WHERE id_game = pID_GAME 
     ORDER BY 2 desc; 
    -- 
    CURSOR c_territory IS 
     SELECT id_territory, dbms_random.value() rnd 
     FROM territories 
     WHERE id_game = pID_GAME 
     FOR UPDATE of id_player 
     ORDER BY 2 desc; 
    -- 
    l_player_row c_player%ROWTYPE; 
    l_territory_row c_territory%ROWTYPE; 
BEGIN 
    OPEN c_player; 
    FETCH c_player into l_player_row; 
    -- 
    FOR r in c_territory 
    LOOP 
     UPDATE territories 
     SET id_player = l_player_row.id_player 
     WHERE CURRENT OF c_territory; 
     -- 
     FETCH c_player INTO l_player_row; 
     IF c_player%NOTFOUND THEN 
      CLOSE c_player; 
      OPEN c_player; 
      FETCH c_player INTO l_player_row; 
     END IF; 
    END LOOP; 
END; 
+0

それは機能しません、それはすべての領域を最後のプレイヤーに割り当て、現在のゲームに属していない領域も割り当てます –

+0

編集されました。どういたしまして。 –

+0

あなたは美しい人です!ありがとう、それは動作します! –

関連する問題