保存游戏(使用localStorage)并在重新加载页面后继续游戏的能力

Posted

技术标签:

【中文标题】保存游戏(使用localStorage)并在重新加载页面后继续游戏的能力【英文标题】:the ability to save the game (using localStorage) and after reload the page continue the game 【发布时间】:2021-02-20 04:04:14 【问题描述】:

我正在制作一个宝石拼图。我有一个保存按钮。当你点击它时,游戏的当前状态被保存,这样当页面重新加载时,用户可以从他保存的地方继续玩。据我了解,我必须将表保存在 localStorage 中。并且在重新加载页面时,检查 localeStorage 是否为空。但是如何在页面重新加载时重新渲染游戏?当使用 json.stringify 和 json.parse 时,我有一个错误 Uncaught SyntaxError: Unexpected token o in JSON at position 1. 当我删除 json.stringify 和 json.parse 这是一个错误 Uncaught TypeError: Failed to execute 'appendChild' on '节点”:参数 1 不是“节点”类型。在 LocalStorage 是 [object htmlTableSectionElement]

let saveSession = false;
document.querySelector('.save-btn').addEventListener('click', () => 
  saveSession = true;
)
function start() 
  let button = document.getElementById('newGame');
  button.addEventListener('click', startNewGame, false );
  textMoves = document.getElementById('moves');
  table = document.getElementById('table');
  rows = 4;
  columns = 4;
  startNewGame();


function startNewGame() 
  let arrayOfNumbers = new Array();
  let arrayHasNumberBeenUsed;
  let randomNumber = 0;
  let count = 0;
  moves = 0;
  rows = document.getElementById('rows').value;
  columns = document.getElementById('columns').value;
  textMoves.innerHTML = moves;
  arrayForBoard = new Array(rows);
  for (let i = 0; i < rows; i++)
    arrayForBoard[i] = new Array(columns);
  
  arrayHasNumberBeenUsed = new Array( rows * columns );
  for (let i = 0; i < rows * columns; i++)
    arrayHasNumberBeenUsed[i] = 0;
  
 for (let i = 0; i < rows * columns; i++)
    randomNumber = Math.floor(Math.random()*rows * columns);
    if (arrayHasNumberBeenUsed[randomNumber] == 0) 
      arrayHasNumberBeenUsed[randomNumber] = 1;
      arrayOfNumbers.push(randomNumber);
    else 
      i--;
    
  
  count = 0;
  for (let i = 0; i < rows; i++)
    for (let j = 0; j < columns; j++)
      arrayForBoard[i][j] = arrayOfNumbers[count];     
      count++;
    
  
  showTable();


function showTable() 
  for (let tr of document.querySelectorAll("#table tr")) 
    tr.remove();
  
    let tbody = document.createElement('tbody');
    document.querySelector('#table').appendChild(tbody);
  for (let i = 0; i < rows; i++) 
    let tr = document.createElement('tr');
    for (let j = 0; j < columns; j++) 
      let cell = document.createElement('td');
      if (arrayForBoard[i][j] == 0) 
        cell.className = 'blank';
       else 
        cell.className = 'tile';
        cell.draggable = true;
        cell.addEventListener('click', () => 
          moveThisTile(i, j);
        )
        cell.innerHTML =arrayForBoard[i][j];
      
      tr.appendChild(cell);
     
    tbody.appendChild(tr);
   
  if(saveSession) 
    localStorage.setItem('currentGame', JSON.stringify(tbody));
  
;
window.addEventListener('load', () => 
  if(localStorage.getItem('currentGame') !== null) 
    const tbody = JSON.parse(localStorage.getItem('currentGame'));
    document.querySelector('#table').appendChild(tbody);
   else 
    start();
  
, false );  

【问题讨论】:

问题在于localStorage.setItem('currentGame', JSON.stringify(tbody)); JSON 库并不是一个神奇的解决方案,可以修复整个销售商店的完整文档元素,然后轻松检索它们.. 【参考方案1】:

当您将某些内容保存到 localStorage 并使用 setItem() 时,您可以使用 getItem() 检索它。然而,这里重要的一件事是您的本地存储实际上并不将对象存储为本身。它存储的是 JSON 字符串。

所以你需要在使用 localStorage.setItem() 函数时执行以下操作:

if(saveSession) 
    localStorage.setItem('currentGame', JSON.stringify(tbody));
  

现在,当您需要从 localStorage 中检索此项目时,您必须解析之前存储到 localStorage 中的 JSON 字符串,您可以通过以下方式使用 localStorage.getItem() 函数:

window.addEventListener('load', () => 
     const tbody = JSON.parse(localStorage.getItem('currentGame'));
  

如果您需要检查 localStorage.setItem() 是否正常工作,您可以转到 chrome 开发工具中的“应用程序”选项卡并从那里查看 localStorage。

【讨论】:

我有一个 [object HTMLTableSectionElement] 并且我有一个错误 Uncaught SyntaxError: Unexpected token o in JSON at position 1. 所以我删除了 JSON.stringify 和 JSON.parse: if(saveSession) localStorage. setItem('currentGame', tbody); window.addEventListener('load', () => const tbody = localStorage.getItem('currentGame');document.querySelector('#table').appendChild(tbody);并且还有一个错误无法在'Node'上执行'appendChild':参数1不是'Node'类型。 试图从评论中读取非常不清楚。您能否更新您的问题,添加您尝试过的内容以及收到的错误? 您可以尝试添加 JSON.stringify() 而不是 JSON.parse() 以查看确切的错误发生在哪里。如果只是 stringify 没有给出错误,那么我们可以查看 JSON.parse()。 重点是localStorage只能存储字符串,不能存储JS对象。因此,如果要使用 localStorage,则必须使用 JSON.stringify()。请检查您是否使用了正确的 JSON.stringify() 语法 - developer.mozilla.org/en-US/docs/Web/javascript/Reference/… 当我只使用 JSON.stringify() 而不是 JSON.parse() 时,我有错误 - 无法在 'Node' 上执行 'appendChild':参数 1 不是类型 'Node' 【参考方案2】:

好的,我在看到另一个 localStorage 问题时遇到了这个问题,我现在要尝试回答:D

问题在于localStorage.setItem('currentGame', JSON.stringify(tbody)); JSON 库并不是一个神奇的解决方案,可以解决整个销售商店的完整文档元素,然后轻松检索它们。..

我将只存储元素的一些数据以重新创建它(attributesinneHTMLlocalName

遗漏了什么? elem 的父级,附加到 elem 的任何事件侦听器(函数有很多上下文,elem 的父级也是如此)

//saves an element
function saveElem(name,elem)
  const item=attributes:[],localName:'',innerHTML:''
  item.localName=elem.localName
  item.innerHTML=elem.innerHTML
  let attributes=item
  for(let i=0;i<elem.attributes.length;i++)
    attributes[i]=[elem.attributes[i].name, elem.attributes[i].value];
  
  localStorage.setItem(name,JSON.stringify(item))


//loads an element
function loadElem(name)
  const item=JSON.parse(localStorage.getItem(name))
  const elem=document.createElement(item.localName)
  item.attributes.forEach(([type,value])=>
    elem.setAttribute(type,value)
  )
  elem.innerHTML=item.innerHTML
  return elem



let saveSession = false;
document.querySelector('.save-btn').addEventListener('click', () => 
  saveSession = true;
)
function start() 
  let button = document.getElementById('newGame');
  button.addEventListener('click', startNewGame, false );
  textMoves = document.getElementById('moves');
  table = document.getElementById('table');
  rows = 4;
  columns = 4;
  startNewGame();


function startNewGame() 
  let arrayOfNumbers = new Array();
  let arrayHasNumberBeenUsed;
  let randomNumber = 0;
  let count = 0;
  moves = 0;
  rows = document.getElementById('rows').value;
  columns = document.getElementById('columns').value;
  textMoves.innerHTML = moves;
  arrayForBoard = new Array(rows);
  for (let i = 0; i < rows; i++)
    arrayForBoard[i] = new Array(columns);
  
  arrayHasNumberBeenUsed = new Array( rows * columns );
  for (let i = 0; i < rows * columns; i++)
    arrayHasNumberBeenUsed[i] = 0;
  
 for (let i = 0; i < rows * columns; i++)
    randomNumber = Math.floor(Math.random()*rows * columns);
    if (arrayHasNumberBeenUsed[randomNumber] == 0) 
      arrayHasNumberBeenUsed[randomNumber] = 1;
      arrayOfNumbers.push(randomNumber);
    else 
      i--;
    
  
  count = 0;
  for (let i = 0; i < rows; i++)
    for (let j = 0; j < columns; j++)
      arrayForBoard[i][j] = arrayOfNumbers[count];     
      count++;
    
  
  showTable();


function showTable() 
  for (let tr of document.querySelectorAll("#table tr")) 
    tr.remove();
  
    let tbody = document.createElement('tbody');
    document.querySelector('#table').appendChild(tbody);
  for (let i = 0; i < rows; i++) 
    let tr = document.createElement('tr');
    for (let j = 0; j < columns; j++) 
      let cell = document.createElement('td');
      if (arrayForBoard[i][j] == 0) 
        cell.className = 'blank';
       else 
        cell.className = 'tile';
        cell.draggable = true;
        cell.addEventListener('click', () => 
          moveThisTile(i, j);
        )
        cell.innerHTML =arrayForBoard[i][j];
      
      tr.appendChild(cell);
     
    tbody.appendChild(tr);
   
  if(saveSession) 
    saveElem('currentGame',tbody);
  
;
window.addEventListener('load', () => 
  if(localStorage.getItem('currentGame') !== null) 
    const tbody = loadElem('currentGame');
    document.querySelector('#table').appendChild(tbody);
   else 
    start();
  
, false );

【讨论】:

以上是关于保存游戏(使用localStorage)并在重新加载页面后继续游戏的能力的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 & Javascript Canvas 游戏 - 如何让玩家能够保存他们的游戏

使用 LocalStorage 保存数据

vue 中使用vuex和localStorage保存登录状态

是否可以将 File 对象保存在 LocalStorage 中,然后当用户返回页面时通过 FileReader 重新加载文件?

将令牌保存在 localStorage 和拦截器中

Win 8 LocalStorage 设置未保存