--- id: 59694356a6e7011f7f1c5f4e title: フリーセルのカードを配る challengeType: 5 forumTopicId: 302246 dashedName: deal-cards-for-freecell --- # --description-- *フリーセル* は、ポール・アルフィレ (Paul Alfille) が1978年にPLATOシステムに導入したソリティアというカードゲームです。 Microsoftのジム・ホーン (Jim Horne) は、ゲーム名をフリーセルに変更し、[DOS](https://rosettacode.org/wiki/DOS "DOS")向け、そして[Windows](https://rosettacode.org/wiki/Windows "Windows")向けに、ゲームを再実装しました。 このバージョンでは、32000のゲーム番号が導入されました。 ゲームが普及し、ジム・ホーンがアルゴリズムを開示したため、他のフリーセル実装でもMicrosoftと同様のアルゴリズムでカードが配られるようになりました。 カードの配り方には1から32000まで番号が付けられています。 Microsoftの新しいバージョンでは、1から1000000までの番号が付けられた100万のゲーム番号があります。一部の実装では、この範囲外の番号も使用されています。 Microsoft Cにおける [線形合同法](https://rosettacode.org/wiki/linear congruential generator "linear congruential generator") をアルゴリズムに使用しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52**ゲーム#1** ```js [ ['JD', '2D', '9H', 'JC', '5D', '7H', '7C', '5H'], ['KD', 'KC', '9S', '5S', 'AD', 'QC', 'KH', '3H'], ['2S', 'KS', '9D', 'QD', 'JS', 'AS', 'AH', '3C'], ['4C', '5C', 'TS', 'QH', '4H', 'AC', '4D', '7S'], ['3S', 'TD', '4S', 'TH', '8H', '2C', 'JH', '7D'], ['6D', '8S', '8D', 'QS', '6C', '3D', '8C', 'TC'], ['6S', '9C', '2H', '6H'] ] ``` **ゲーム#617** ```js [ ['7D', 'AD', '5C', '3S', '5S', '8C', '2D', 'AH'], ['TD', '7S', 'QD', 'AC', '6D', '8H', 'AS', 'KH'], ['TH', 'QC', '3H', '9D', '6S', '8D', '3D', 'TC'], ['KD', '5H', '9S', '3C', '8S', '7H', '4D', 'JS'], ['4C', 'QS', '9C', '9H', '7C', '6H', '2C', '2S'], ['4S', 'TS', '2H', '5D', 'JC', '6C', 'JH', 'QH'], ['JD', 'KS', 'KC', '4H'] ] ``` # --instructions-- ゲーム番号を受け取り、このアルゴリズムと同じ順序でカードを配る関数を作成します。 この関数はフリーセルボードを表す2次元配列を返します。 ゲーム番号は、[1000000ゲームのフリーセルソリューション](https://freecellgamesolutions.com/) に照らし合わせて確認することもできます (ビデオソリューションを呼び出し、最初のゲーム番号を表示する)。 # --hints-- `dealFreeCell` という関数です。 ```js assert(typeof dealFreeCell === 'function'); ``` `dealFreeCell(seed)` はオブジェクトを返します。 ```js assert(typeof dealFreeCell(1) === 'object'); ``` `dealFreeCell(seed)` は長さ7の配列を返します。 ```js assert(dealFreeCell(1).length === 7); ``` `dealFreeCell(1)` は例「Game #1」と同一の配列を返します。 ```js assert.deepEqual(dealFreeCell(1), game1); ``` `dealFreeCell(617)` は「Game #617」と同一の配列を返します。 ```js assert.deepEqual(dealFreeCell(617), game617); ``` # --seed-- ## --after-user-code-- ```js const replaceThis = 3; const game1 = [ ['JD', '2D', '9H', 'JC', '5D', '7H', '7C', '5H'], ['KD', 'KC', '9S', '5S', 'AD', 'QC', 'KH', '3H'], ['2S', 'KS', '9D', 'QD', 'JS', 'AS', 'AH', '3C'], ['4C', '5C', 'TS', 'QH', '4H', 'AC', '4D', '7S'], ['3S', 'TD', '4S', 'TH', '8H', '2C', 'JH', '7D'], ['6D', '8S', '8D', 'QS', '6C', '3D', '8C', 'TC'], ['6S', '9C', '2H', '6H'] ]; const game617 = [ ['7D', 'AD', '5C', '3S', '5S', '8C', '2D', 'AH'], ['TD', '7S', 'QD', 'AC', '6D', '8H', 'AS', 'KH'], ['TH', 'QC', '3H', '9D', '6S', '8D', '3D', 'TC'], ['KD', '5H', '9S', '3C', '8S', '7H', '4D', 'JS'], ['4C', 'QS', '9C', '9H', '7C', '6H', '2C', '2S'], ['4S', 'TS', '2H', '5D', 'JC', '6C', 'JH', 'QH'], ['JD', 'KS', 'KC', '4H'] ]; ``` ## --seed-contents-- ```js function dealFreeCell(seed) { return true; } ``` # --solutions-- ```js // RNG function FreeCellRNG(seed) { return { lastNum: seed, next() { this.lastNum = ((214013 * this.lastNum) + 2531011) % (Math.pow(2, 31)); return this.lastNum >> 16; } }; } // Get cards function getDeck() { const ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K']; const suits = ['C', 'D', 'H', 'S']; const cards = []; for (let i = 0; i < ranks.length; i += 1) { for (let j = 0; j < suits.length; j += 1) { cards.push(`${ranks[i]}${suits[j]}`); } } return cards; } function dealFreeCell(seed) { const rng = FreeCellRNG(seed); const deck = getDeck(); const deltCards = [[], [], [], [], [], [], []]; let currentColumn = 0; let currentRow = 0; let rand; let temp; let card; while (deck.length > 0) { // Choose a random card rand = rng.next() % deck.length; // Swap this random card with the last card in the array temp = deck[deck.length - 1]; deck[deck.length - 1] = deck[rand]; deck[rand] = temp; // Remove this card from the array card = deck.pop(); // Deal this card deltCards[currentRow].push(card); currentColumn += 1; if (currentColumn === 8) { currentColumn = 0; currentRow += 1; } } return deltCards; } ```