LoginSignup
0
1

More than 1 year has passed since last update.

カードゲームロジック

Posted at

カードゲームロジック

概要

paizaのゲームのプログラムが思ったより難しくて、偉い時間がかかったので、
消すのももったいないので、ノートとして記録してみる。

設問はこちら。
難しいので、この設問では、1人1枚という制限が付けられていたけど、それだと面白くないので、何人でも計算できるように、上位互換でのロジックで組んだ。

playersを変更すれば何人でも計算できる。設問の場合は52にする必要がある。

簡単な内容は、配られたカードを一定のルールでカードを出していくと、どの順番にクリアしていくか。というもの。

動作コード

こちらで動作確認が出来る。

コード

    const players = 52;
    const power = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2']; // カードの強さの純
    const cards = lines[0].split(' ');
    
    let havings = [...Array(players)].reduce((a, c, i) => { a['r' + i] = []; return a; }, {});   // 各プレイヤーが持っているトランプ
    
    cards.forEach((o, i) => havings['r' + i % players].push(o)); // 初期カードを配る
    
    let rank = [];                      // ランキング(上がった順番)
    let share = null;                   // 場
    let i = 0;                          // 現在のターンのプレイヤIDのindex
    let roundCount = 0;                 // 一周回っている数
    
    while (Object.keys(havings).length > 0) {
        // プレイヤーが全員いなくなるまで続ける
        const id = Object.keys(havings)[i];
        
        if (roundCount >= Object.keys(havings).length) {
            // 一周回った
            share = null;
            roundCount = 0;
        }
         
        if (share == null || power.findIndex(e => havings[id][0] == e) > power.findIndex(e => share == e)) {
            share = havings[id].shift();
            roundCount = 0;

            // あがり
            if (havings[id].length == 0) {
                rank.push(id);
                delete havings[id];
                i = (i - 1) % (Object.keys(havings).length); // 消した場合はindexは動かない
            }
        } else {
            roundCount++;
        }
        
        i = (i + 1) % (Object.keys(havings).length);
    }
    
    const finalRank = rank.map(o => +o.replace(/[^0-9]*/, '') + 1); // 上がる順番のID
    const oppositeRank = finalRank.reduce((a, c, i) => { a[c] = i + 1; return a; }, []).filter(o => o != null);

    console.log(oppositeRank.join('\n'));

あとがき

遅くなった原因として反省点はいくつかある。

主に見通しの甘さ。

連想配列にすべきカード情報(havings)を配列にしていた。

最初はカード情報を保持するだけなので、配列で十分かと思っていたが、持っているカードが0になった時に、ゲームから降りるために、havingsから削除していた。すると、indexが狂ってしまうので、しばらくindexの位置を再計算するなど、試行錯誤していたが、もうわけわからんくなってきたので、連想配列に切り替えた。indexではなくidで削除や索引するように組みなおした。最初から連想配列で組んでいればもっと早く解決できたと思う。

誰もカードを出せなくなった時のリセットタイミング(roundCount)を回数にすべき所を、idにしていた

今度は逆に、idで管理していたが、これが逆にロジックを難しくしてしまった。カードを出した時に、自分のidをroundCountに書いていたが、これだとカードを出した次のステップで1周してしまったとプログラムが勘違いしてしまうため、皆そのまま全員上がってしまった。flagを立てても良いけど、あまり使いたくないので、別の方法にした。 プレイヤー人数より多く誰も上がらない回数ループした場合にリセットするように変更した。

ああ、疲れた。

0
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1