今回でラストです。Web版素数大富豪、別名「素数の出会い系サイト」を完成させます。
動作確認はこちらから ⇒ Web版素数大富豪、別名 素数の出会い系サイト
最初に難易度の設定を可能にします。いまのままでは人間に勝ち目がありません。
HTML部分
HTML部分を示します。ボタンが増えました。
index.html
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>JavaScriptで素数大富豪をつくる</title> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> #body { background-color: #000000; } #table { width: 800px; height:650px; margin: 0 auto 0; background-color: #008000; } .button { position: absolute; width: 80px; height: 25px; margin-top: 450px; } .button2 { position: absolute; width: 130px; margin-top: 450px; } #button-confirm { margin-left: 30px; } #button-clear { margin-left: 130px; } #button-pass { margin-left: 230px; } #button-draw { margin-left: 330px; } #button-help { margin-left: 430px; } #button-start { margin-left: 500px; } .button-composite { position: absolute; margin-top: 490px; margin-top: 490px; } #checkbox-composite-label { margin-left: 30px; color: white; font-size: 14px; } #button-x { margin-left: 200px; width: 50px; height: 25px; } #button-hat { margin-left: 280px; width: 50px; height: 25px; } #text{ position: absolute; margin-top: 520px; margin-left: 30px; color: white; font-size: 14px; } #comp-text{ position: absolute; margin-top: 550px; margin-left: 30px; color: white; font-size: 14px; } #checkbox-penalty-label { position: absolute; margin-top: 490px; margin-left: 420px; color: white; font-size: 14px; } #checkbox-show-label { position: absolute; margin-top: 515px; margin-left: 420px; color: white; font-size: 14px; } #radio-label1 { position: absolute; margin-top: 590px; margin-left: 40px; color: white; font-size: 14px; } #radio-label2 { position: absolute; margin-top: 620px; margin-left: 40px; color: white; font-size: 14px; } </style> </head> <body id = "body"> <div id = "table"> <button id = "button-confirm" class = "button" onclick="Confirm()">確定</button> <button id = "button-clear" class = "button" onclick="ClearPlayerCards()">クリア</button> <button id = "button-pass" class = "button" onclick="PlayerPass()">パス</button> <button id = "button-draw" class = "button" onclick="PlayerDraw()">1枚とる</button> <button id = "button-help" class = "button" onclick="PlayerHelp()">Help</button> <button id = "button-start" class = "button2" onclick="GameStart()">ゲームスタート</button> <label id = "checkbox-composite-label" class = "button-composite"><input type="checkbox" id = "checkbox-composite">素因数を指定する</label> <button id = "button-x" class = "button-composite" onclick="InsertX()">×</button> <button id = "button-hat" class = "button-composite" onclick="InsertHat()">^</button> <label id = "checkbox-penalty-label"><input type="checkbox" id = "checkbox-penalty">ペナルティーあり</label> <label id = "checkbox-show-label"><input type="checkbox" id = "checkbox-show">コンピュータのカードを表示する</label> <label id = "radio-label1">コンピュータが親のときに素数として出すカードの上限 <input type = "radio" id = "four" name = "group1" value="" checked>4まで <input type = "radio" id = "three" name = "group1" value="">3まで <input type = "radio" id = "two" name = "group1" value="">2まで </label> <div id = "radio-label2">レベル <input type = "radio" id = "level-4" name = "group2" value="" checked>最強(Lv4) <input type = "radio" id = "level-1" name = "group2" value="">ランダム(Lv1) <input type = "radio" id = "level-2" name = "group2" value="">時々本気出す(Lv2) <input type = "radio" id = "level-3" name = "group2" value="">時々本気出す(Lv3) </div> <p id = "text">入力値</p> <p id = "comp-text">コンピュータの手</p> </div> <script src="./card.js"></script> <script src="./game.js"></script> <script> </script> </body> </html> |
コンピュータの強度を下げる
コンピュータが親の時に出すカードの枚数を制限します。制限なしだと最大で4枚出します。また複数の候補のなかからコンピュータの手を選ぶとき、最適のものを探すのではなく、適当に選ばせることで強度を下げます。
レベル4のときはカードを多く消費するものを選びます。レベル1の場合はつねにランダムに選びます。またランダムに選ぶだけでもかなり強い手を選んでしまう場合があるので弱い手を出すときは枚数も制限します。
game.js
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
function CompPutCards2(){ let isThree = document.getElementById('three').checked; let isTwo = document.getElementById('two').checked; let level_1 = document.getElementById('level-1').checked; let level_2 = document.getElementById('level-2').checked; let level_3 = document.getElementById('level-3').checked; let level_4 = document.getElementById('level-4').checked; let candidates = GetCandidates(); if(isThree && cardCount == -1){ candidates = candidates.filter(candidate => { return candidate.GetCardNumbersToPlayField().length < 4} ); } if(isTwo && cardCount == -1){ candidates = candidates.filter(candidate => {return candidate.GetCardNumbersToPlayField().length < 3} ); } let candidate = null; let isStrong = true; if(level_4) isStrong = true; else if(level_1) isStrong = false; else { let rand = Math.random(); console.log(rand); if(level_2) isStrong = rand > 0.7; if(level_3) isStrong = rand > 0.3; } if(isStrong){ // ここはこれまでどおり candidates = GetCandidatesUseEvenNumbers(candidates); candidate = GetCandidatesUseManyCards(candidates); if(candidate == null && candidates.length > 0){ let index = Math.floor(Math.random() * candidates.length); candidate = candidates[index]; } } else{ if(cardCount == -1){ // ランダムに枚数制限をかける let rand = 2 + Math.floor(Math.random() * 3); candidates = candidates.filter(candidate => {return candidate.GetCardNumbersToPlayField().length < rand} ); } // 得られた候補のなかから適当に選ぶ if(candidates.length > 0){ let index = Math.floor(Math.random() * candidates.length); candidate = candidates[index]; } } // ここから下はこれまでと同じ let text = document.getElementById('comp-text'); text.innerHTML = ''; if(candidate == null){ CompPass(); return false; } // 1枚出しの結果、偶数のカードばかりになる場合はパスする let len = candidate.GetCardNumbersToPlayField().length; if(len == 1){ let arr = []; compCards.forEach(card => { arr.push(card.Number); }); let pass = true; for(let i=0;i<arr.length; i++){ if(arr[i] % 2 != 0) pass = false; } if(pass == true){ CompPass(); return false; } } numberMin = candidate.Number; cardCount = candidate.CardNumbers.length; let joker = CompMoveCard(candidate); if(candidate.PrimeNumberCards.length != 0) text.innerHTML = 'コンピュータの手は ' + candidate.Number + ' = ' + candidate.GetFormula(); else text.innerHTML = 'コンピュータの手は ' + candidate.Number; ShowCards(); if(compCards.length == 0){ InitBottons(); return false; } if(joker){ ShowPassMessage('ジョーカーを出したのでコンピュータが親です'); return false; } if(candidate.Number == 57 && candidate.GetCardNumbersToFactorField()) { ShowPassMessage('グロタンディーク素数 57を出したのでコンピュータが親です'); return false; } if(candidate.Number == 1729 && candidate.GetCardNumbersToFactorField()){ isRevolution = isRevolution ? false : true; if(isRevolution) ShowCompRevolutionMassage('1729を出したのでラマヌジャン革命です'); else ShowCompRevolutionMassage('1729を出したのでラマヌジャン革命返しです'); } return true; } |
プレイヤーの候補手を表示させる
あとなにを出していいかわからない場合、ヘルプボタンで候補を示してくれる機能も追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function PlayerHelp(){ let candidates = GetCandidates(playerCards); if(candidates.length == 0) ShowNotificationMessage('残念ですがパスするしかありません'); else{ let num = candidates[0].Number; let formula = candidates[0].GetFormula(); let str = ''; if(formula == '') str = num; else str = num + ' = ' + formula; ShowNotificationMessage(str + 'はどうでしょうか?'); EnableBottons(false); } } |
GetCandidates関数を使い回しています。これまでどおり引数なしの場合はコンピュータの手を探し、プレイヤーのカードを引数に渡したときはプレイヤーの手を探します。
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 |
function GetCandidates(_playerCards){ // 引数なしの場合はコンピュータの手を探す if(_playerCards == undefined) _playerCards = compCards; // コンピュータのカードから順列を取得する let permutationOfNumbers = []; permutationOfNumbers = permutationOfNumbers.concat(GetPermutationCardNumber(_playerCards, 1)); permutationOfNumbers = permutationOfNumbers.concat(GetPermutationCardNumber(_playerCards, 2)); permutationOfNumbers = permutationOfNumbers.concat(GetPermutationCardNumber(_playerCards, 3)); permutationOfNumbers = permutationOfNumbers.concat(GetPermutationCardNumber(_playerCards, 4)); // 重複を取り除く permutationOfNumbers = RemoveArrayDuplication(permutationOfNumbers); // コンピュータのカードから取得した順列を素数をつくるものと合成数をつくるものにわける let primeNumberArrays = []; let notPrimeNumberArrays = []; DivideNumberArray(permutationOfNumbers, primeNumberArrays, notPrimeNumberArrays); // 素数を候補として取得 let candidates1 = GetPrimeCandidates(primeNumberArrays); // 素因数分解のために使う素因数も取得する let primeNumberFromCardsList = GetPrimeFactors(primeNumberArrays); let candidates2 = GetCompositeCandidates(notPrimeNumberArrays, primeNumberFromCardsList); return candidates1.concat(candidates2); } |
以上、Web版素数大富豪でした。素数とのよき出会いを!