思路:首先找到当前current方格在网格中对应的横纵坐标x和y,再根据按键移动方向控制x和y的变化,尤其注意边界条件,即上下和左右的边界调整。其中找到横纵坐标x和y,使用的方法是,首先找到所有tr,并遍历tr是否包含current,如果是则锁定在哪一行即纵坐标,接着再找到该tr内的所有td,并遍历td是否等于current,如果是则锁定在哪一列即横坐标,注意querySelectorAll得到的是伪数组,需要使用Array.from转换为真数组。

<body>
    <div id="jsContainer">
        <table class="game">
            <tbody>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td class="current"></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
            </tbody>
        </table>
    </div>
    <script type="text/javascript">
        function bind() {
    		const con = document.getElementById("jsContainer")
    		const rows=con.querySelectorAll('tr')
    		const cols=rows[0].querySelectorAll('td')
    		document.onkeydown = event => {
        		if (!event) return;
        		var code = event.keyCode || '';
        		if (!{'37': 1, '38': 1, '39': 1, '40': 1}[code]) return;
        		event.preventDefault && event.preventDefault();
        		//TODO: 请实现按键控制
        		const cur=con.querySelector('.current')
        		let x=0
        		let y=0
        		// 找到cur对应的横纵坐标 y是哪一行即纵 x是哪一列即横
        		Array.from(rows).forEach((tr,index)=>{
            		if(tr.contains(cur))
            		{
                		y=index
                		Array.from(tr.querySelectorAll('td')).forEach((td,i)=>{
                    		if(td===cur)
                    		{
                        		x=i
                    		}
                		})
            		}
        		})
        		//上
        		if(Number(code)===38)
        		{
            		if(y===0)
                		y=rows.length-1
            		else
                		y--
        		}
                //下
        		else if(Number(code)===40)
        		{
            		if(y===rows.length-1)
                		y=0
            		else
                		y++
        		}
                //左
        		else if(Number(code)===37)
        		{
            		if(x===0)
                		x=cols.length-1
            		else
                		x--
        		}
                //右
        		else if(Number(code)===39)
        		{
            		if(x===cols.length-1)
                		x=0
            		else
                		x++
        		}
        		cur.classList.remove('current')
        		rows[y].querySelectorAll('td')[x].classList.add('current')
    		};
		}
		bind()
    </script>
</body>

总结:在javascript中,判断父子节点的包含关系以及寻找父子节点,是一个频繁使用的事情,此处特意总结一下以便后续复习。parentNode属性用于获取当前节点的父节点;childNodes属性用于获取当前节点的所有子节点列表;children属性用于获取当前节点的所有子节点元素列表(不包含文本节点和注释节点);firstChild属性用于获取当前节点的第一个子节点;lastChild属性用于获取当前节点的最后一个子节点;firstElement属性用于获取当前节点的第一个子元素节点;lastElement属性用于获取当前节点的最后一个子元素节点;nextSibling属性用于获取当前节点的下一个兄弟节点;previousSibling属性用于获取当前节点的上一个兄弟节点;contains方法用于判断当前节点是否是另一个节点的后代节点;

<div id="parent">
  <p>这是一个段落</p>
  文本节点
  <span>这是一个span元素</span>
  <!-- 这是一个注释节点 -->
</div>
var parent = document.getElementById("parent");
var childNodesList = parent.childNodes;
console.log(childNodesList.length); // 输出:4,包括文本节点、元素节点和注释节点
var childrenList = parent.children;
console.log(childrenList.length); // 输出:2,只包括元素节点,不包括文本节点和注释节点
console.log(childNodesList[0].nodeType); // 输出:1,元素节点
console.log(childNodesList[1].nodeType); // 输出:3,文本节点
console.log(childNodesList[3].nodeType); // 输出:8,注释节点

注意:childNodesList包含了父节点<div>下的所有子节点,包括文本节点、元素节点和注释节点,而childrenList只包含了元素节点<p>和<span>。通过nodeType属性可对各个节点类型进行判断,其中1表示元素节点,3表示文本节点,8表示注释节点。