カードゲームロジック
概要
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を立てても良いけど、あまり使いたくないので、別の方法にした。 プレイヤー人数より多く誰も上がらない回数ループした場合にリセットするように変更した。ああ、疲れた。