実現したいこと
localStorageに保存された内容をゲームの勝敗に応じて正しく更新させたい
前提
自作のブラウザゲームにて、JavaScriptのlocalStorageを用いて下記のように連勝数を記録・表示する仕組みを実装したいと考えています。
- ページ読み込み時・難易度変更時: 難易度に応じた連勝数を表示
- 勝利時: 数値化した連勝数に1を足して更新・表示
- 引き分け時: 連勝数を変更せずに表示
- 敗北時: 連勝数を0にリセットし表示
発生している問題・エラーメッセージ
連続して勝った際に連勝数が1増える仕組みには問題ないものの、1度敗北して連勝数が0にリセットされた後に同じ難易度で挑戦し勝利した場合、何故か以前の連勝数が戻ってしまいます。
※例: 10連勝↠負けて0連勝↠勝って10連勝に戻る
なおコンソール上エラーは起きていないように見受けられます。
該当のソースコード
JavaScript
1document.addEventListener("DOMContentLoaded", () => { 2 // ゲーム本体に関わる変数定義(省略) 3 const highscore = document.getElementById('highscore'); // 連勝数表示領域 4 // ゲーム初期設定(省略) 5 6 // ページ読み込み時に難易度をEasyに設定、連勝数保存状況を確認して表示 7 let difficulty = "easy"; 8 if(localStorage.getItem('cdoEasy')) { 9 highscore.textContent = localStorage.getItem('cdoEasy'); 10 } else { 11 localStorage.setItem('cdoEasy', '0'); 12 highscore.textContent = '0'; 13 } 14 15 // ゲーム初期化(大部分省略) 16startGameButton.addEventListener("click", () => { 17 // ... 18 // 盤面生成・ゲーム終了確認 19 function renderBoard() { 20 // ... 21 if (currentPlayer === playerPiece) { 22 const playerMoves = getValidMoves(playerPiece); 23 if (playerMoves.length === 0) { 24 // プレイヤーの取れる手がない場合 25 alert("あなたの置ける場所がありません。敵のターンです。"); 26 currentPlayer = opponentPiece; 27 28 // 敵の取れる手があるか確認 29 if (getValidMoves(opponentPiece).length === 0) { 30 checkEndGame(); // 両社共に取れる手がない場合、ゲーム終了 31 } else { 32 setTimeout(() => handleOpponentMove(), 500); 33 } 34 } 35 } 36 } 37// ゲーム本体のコード(省略 38 39// ゲーム終了時、勝敗判定及び連勝数記録 40function checkEndGame() { 41 const playerValidMoves = getValidMoves(playerPiece); 42 const opponentValidMoves = getValidMoves(opponentPiece); 43 44 if (playerValidMoves.length === 0 && opponentValidMoves.length === 0) { 45 if (!gameOver) { 46 gameOver = true; 47 48 // 集計 49 const playerCount = board.flat().filter(piece => piece === playerPiece).length; 50 const opponentCount = board.flat().filter(piece => piece === opponentPiece).length; 51 52 document.getElementById('controls-section').classList.remove('hidden'); 53 // 勝利時 54 if (playerCount > opponentCount) { 55 playWin(); // 効果音再生(別ファイルにて定義) 56 setTimeout(function(){ 57 alert(`ゲーム終了\nおめでとうございます! あなたの勝利です。 ${playerPiece}\n${playerPiece}: ${playerCount}/${opponentPiece}: ${opponentCount}`); 58 }, 4000); 59 // 難易度によって連勝数を更新 60 if(difficulty == 'easy') { 61 let cdoCur = Number(localStorage.getItem('cdoEasy')) + 1; 62 localStorage.setItem('cdoEasy', String(cdoCur)); 63 highscore.textContent = localStorage.getItem('cdoEasy'); 64 } else if(difficulty == 'medium') { 65 let cdoCur = Number(localStorage.getItem('cdoMedium')) + 1; 66 localStorage.setItem('cdoMedium', String(cdoCur)); 67 highscore.textContent = localStorage.getItem('cdoMedium'); 68 } else { 69 let cdoCur = Number(localStorage.getItem('cdoMedium')) + 1; 70 localStorage.setItem('cdoHard', String(cdoCur)); 71 highscore.textContent = localStorage.getItem('cdoHard'); 72 } 73 } else if (opponentCount > playerCount) { 74 // 敗北時 75 playLose(); // 効果音再生(別ファイルにて定義) 76 setTimeout(function(){ 77 alert(`ゲーム終了\n残念、あなたの負けです... ${opponentPiece}\n${playerPiece}: ${playerCount}/${opponentPiece}: ${opponentCount}`); 78 }, 6500); 79 // 難易度によって連勝数を更新 80 if(difficulty == 'easy') { 81 localStorage.removeItem('cdoEasy'); // 備考あり 82 localStorage.setItem('cdoEasy', '0'); 83 highscore.textContent = localStorage.getItem('cdoEasy'); 84 } else if(difficulty == 'medium') { 85 localStorage.removeItem('cdoMedium'); // 備考あり 86 localStorage.setItem('cdoMedium', '0'); 87 highscore.textContent = localStorage.getItem('cdoMedium'); 88 } else if(difficulty == 'hard') { 89 localStorage.removeItem('cdoHard'); // 備考あり 90 localStorage.setItem('cdoHard', '0'); 91 highscore.textContent = localStorage.getItem('cdoHard'); 92 } 93 } else { 94 // 引き分け時 95 playDraw(); // 効果音再生(別ファイルにて定義) 96 setTimeout(function(){ 97 alert(`ゲーム終了\n結果は引き分けです。\n${playerPiece}: ${playerCount}/${opponentPiece}: ${opponentCount}`); 98 }, 4000); 99 if(difficulty == 'easy') { 100 highscore.textContent = localStorage.getItem('cdoEasy'); 101 } else if(difficulty == 'medium') { 102 highscore.textContent = localStorage.getItem('cdoMedium'); 103 } else if(difficulty == 'hard') { 104 highscore.textContent = localStorage.getItem('cdoHard'); 105 } 106 } 107 } 108 } 109} 110}); 111 112// 難易度変更時に連勝数表示を更新 113document.getElementById("difficulty-choice").addEventListener('change', function() { 114 let difficulty = document.getElementById("difficulty-choice").value; 115 let highscore = document.getElementById('highscore'); 116 if(difficulty == 'easy') { 117 if(localStorage.getItem('cdoEasy')) { 118 highscore.textContent = localStorage.getItem('cdoEasy'); 119 } else { 120 localStorage.setItem('cdoEasy', '0'); 121 highscore.textContent = '0'; 122 } 123 } else if(difficulty == 'medium') { 124 if(localStorage.getItem('cdoMedium')) { 125 highscore.textContent = localStorage.getItem('cdoMedium'); 126 } else { 127 localStorage.setItem('cdoMedium', '0'); 128 highscore.textContent = '0'; 129 } 130 } else if(difficulty == 'hard') { 131 if(localStorage.getItem('cdoHard')) { 132 highscore.textContent = localStorage.getItem('cdoHard'); 133 } else { 134 localStorage.setItem('cdoHard', '0'); 135 highscore.textContent = '0'; 136 } 137 } 138});
試したこと
上記ソースコード内、「備考あり」と記載がある箇所に一度localStorageを削除する処理を追記しました。
ただこちらの対応をして以来、今度は
- 敗北し連勝数をリセット
- 勝利して以前の連勝数が戻る
- その後勝利しても連勝数が変わらない
と状況が悪化してしまいました。
こちらの問題の解決方法をご存じの方がいましたら、ご教示いただけますと幸いです。
よろしくお願いいたします。
localStorageの中身も要所要所で出力させて、中身を確認しながらのデバッグ…などは行ってみましたか?
とりあえず動作する状態で提示するか、動作するサイトにアップしてください
>yambejpさん
コメント・回答を頂きありがとうございます。
まず「動作するウェブサイト」について、上記を反映済のサイトがあるのですが、こちらに外部サイトのURLを掲載することは規約・マナー上問題ないでしょうか。
また記録と現在の連勝数についてですが、該当ページでは「連勝記録」は保持せず、「現在の連勝数」のみを更新・表示したいと考えています。
>maisumakunさん
ありがとうございます。現在ゲーム終了時にlocalStorageが出力されるよう調整・検証してみています。
ご提示のコードを試してみましたが、特に問題は起きませんでした。
ここに書かれていない、numinさんが問題に関係がないと思って省略している部分に原因があるかもしれませんので、現状のコードのコピーを作って、問題に関係がないと思っている部分を少しずつ削除して検証してみると原因の部分が見つかるかもしれません。
>外部サイトのURLを掲載することは規約・マナー上問題ない
広告があるようなサイトだと誘導とみなされる可能性はありますね
codepenのようなソースサンプルサイトなら大丈夫ですよ
参考までにサンプルデータ回答につけておきました
回答2件
あなたの回答
tips
プレビュー