资讯专栏INFORMATION COLUMN

关于井字游戏自己的解题思路吧.

wums / 1960人阅读

摘要:题目来源于面试公司先看看题目吧假设我们现在有一个的井字棋游戏,我们用一个二维数组代表棋盘,代表玩家下的棋子,代表玩家下的棋子,代表该格没有棋子。

题目来源于面试公司,先看看题目吧

假设我们现在有一个 3 x 3 的井字棋游戏,我们用一个二维数组代表棋盘,’x’ 代表玩家 X 下的棋子,’o’ 代表玩家 O 下的棋子,’e’ 代表该格没有棋子。例如:一个空白的棋盘以下面的二维数组表示:
[[‘e’, ‘e’, ‘e’],
 [‘e’, ‘e’, ‘e’],
 [‘e’, ‘e’, ‘e’]
]
如果玩家 X 在第一行第一列下了一步棋,玩家 O 在第二行第二列下了一步棋,则表示如下:
[[‘x’, ‘e’, ‘e’],
 [‘e’, ‘o’, ‘e’],
 [‘e’, ‘e’, ‘e’]]
现在需要一个 function,接受一个已有任意棋子的棋盘(和上面二维数组一样的格式),和玩家的标志(’x’ 或 ‘o"),返回该玩家下一步有几种可能的获胜方式(获胜方式以数组表示,[0, 0] 代表在第一行第一列下一步棋即可获胜,[2, 2] 代表在第三行第三列下一步棋即可获胜)。例如:
someFunction(
‘x’,
[[‘o’, ‘e’, ‘e’],
 [‘o’, ‘x’, ‘o’],
 [‘x’, ‘x’, ‘e’]])
// return [ [2, 2], [0, 1], [0, 2] ]
someFunction(
‘x’,
[[‘x’, ‘o’, ‘o’],
 [‘x’, ‘x’, ‘e’],
 [‘e’, ‘o’, ‘e’]])
// return [[2, 2], [1, 2], [2, 0]]
someFunction(
‘x’,
[[‘x’, ‘x’, ‘o’],
 [‘e’, ‘e’, ‘e’],
 [‘e’, ‘e’, ‘e’]])
// return [ ]
someFunction(
‘o’,
[[‘o’, ‘o’, ‘o’],
 [‘e’, ‘e’, ‘e’],
 [‘e’, ‘e’, ‘e’]])
// return [ ]

最后是加分项:

代码可读性高

代码量少

性能高

有可运行的单元测试

使用 ES6 语法实现

使用 functional programming

下面是自己的代码实现.

var getSuccess;
+function(){
    //假设3个相连即可获胜.
    const linkLen = 3;
    //实际上, 我们可以理解为, 围绕某个没有棋子的点,在 X 和 十 字这4个方向上的比较
    //因此这里提供获取该4个方向上获取棋盘点的简易计算公式.
    const _getTraverlConfig = function(distance){
        return [{
            cStartRow : -1 * linkLen + 1, 
            cStartLine : -1 * linkLen + 1,
            rowAdd : 1,
            lineAdd : 1,
        }, {
            cStartRow : -1 * linkLen + 1, 
            cStartLine : linkLen - 1,
            rowAdd : 1,
            lineAdd : -1,
        }, {
            cStartRow : -1 * linkLen + 1, 
            cStartLine : 0,
            rowAdd : 1,
            lineAdd : 0,
        }, {
            cStartRow : 0, 
            cStartLine : -1 * linkLen + 1,
            rowAdd : 0,
            lineAdd : 1,
        }];
    }
    //提供一个target字符串重复n次自己的方法
    const _strRepeat =    function (target, n){
        var s = target, total = "";
        while( n > 0 ) {
            if(n % 2 == 1)
                total += s;
            if(n == 1) 
                break;
            s += s;
            n = n >>1 ;
        } 
        return total;
    }
    //最终对外暴露的方法, 第一个参数是下棋的人, 第二个是棋盘的点数组.
    getSuccess = function( piece, chessboard ){
        var availablePosition = [], distance = chessboard.length,
            traversalConfig, maxLen, compareStr, chessStr;
        //根据几个点连成线获取4个方向上的计算公式;
        traversalConfig = _getTraverlConfig(linkLen);
        //计算方向上的点数量.
        maxLen = 2 * (linkLen - 1) + 1;
        //如果传入的piece为x,那么这里的值就为xxx
        compareStr = _strRepeat(piece, linkLen);
        //这一步很重要, 将棋盘转为一个字符串,为的就是更快.
        chessStr = chessboard.reduce( 
                (x,y) => x + y.join("")
        , "")
        //检查每一个字符串, 如果是空的话就判断能否获胜.
        for( let i = 0, len = chessStr.length; i < len; i++)
            if( "e" == chessStr.charAt(i) ) _checkAvailable(i);
            
        function _checkAvailable( sqnm ){
            //计算点在棋盘上的行和列.
            let curRow = Math.floor(sqnm / distance), curLine = sqnm % distance;
            //以传入的参数填在该空点上,得到一个新的棋盘字符串.
            let tempChessStr = chessStr.substring(0, sqnm) + piece + chessStr.substring(sqnm + 1, chessStr.length);
            //4个方向上的检查
            for( let i = 0, len = traversalConfig.length; i < len; i++) {
                let { cStartRow, cStartLine, rowAdd, lineAdd } = traversalConfig[i];
                let tempStr = "";
                let j = 0;
                let row = curRow + cStartRow;
                let line = curLine + cStartLine;
                
                while( j < maxLen ) {
                    //超出边界视为空字符串.
                    if(row < 0 || row > distance || line > distance || line < 0){
                        tempStr += "";
                    }
                    else {
                        //方向上棋盘的实际棋子的集合字符串.
                        tempStr += tempChessStr.charAt(row * distance + line);
                    }
                    row += rowAdd;
                    line += lineAdd;
                    j++;
                }
                //如果在该字符串中含有需要比较的重复字符串即可认为该点可以获胜.
                if( -1 != tempStr.indexOf(compareStr) ) {
                    availablePosition.push([curRow, curLine]);
                    return;
                }
            }    
        }
        console.log(availablePosition);
    }
}(); 

写的不好, 请多指教.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108026.html

相关文章

  • 哈哈哈~井字棋(无心版),快来初步感受一下代码世界乐趣

    摘要:文章目录前言正文一,游戏实现基本流程二游戏实现步骤创建工程及分配功能给头文件上内容当当当,主函数出场游戏函数里面打印游戏菜单棋盘初始化打印棋盘玩家下棋电脑下棋判断结果三游戏结果演示恭喜友友获胜啦电脑获胜,很遗憾,再接再厉 ...

    不知名网友 评论0 收藏0
  • 【三子棋(井字棋)】如何用C语言实现

    摘要:三子棋目录一问题介绍三子棋,在民间又叫井字棋。因为人们在游玩时常常不画棋盘的边框,正如汉字中的井字,多称为井字棋。 三子棋 目录 一、问题介绍         三子棋,在民间又叫井字棋。因为人们在游玩时常常不画棋盘的边框,正如汉字中的井字,多称为井字棋。 三子棋的游戏规则十分的简单: ...

    jsbintask 评论0 收藏0
  • 井字游戏 - 做一款回忆童年游戏

    摘要:说起井字游戏,真是满满的童年味道,还记得最疯狂的时候是小时候跟同桌拿着一张草稿纸就能玩一节课,回到家跟弟弟也能继续玩,对于没有太多娱乐节目的童年来说,真是一款玩不厌的小游戏。 99% of information we read, we forget anyway. The best way to remember is to DO. 体验地址:http://www.hoohack.m...

    vpants 评论0 收藏0
  • Minimax 和 Alpha-beta 剪枝算法简介,以及以此实现井字游戏(Tic-tac-t

    摘要:我们在前文中考虑的那张图就来自这篇文章,之后我们会用剪枝算法来改进之前的解决方案。剪枝算法的实现接下来讨论如何修改前面实现的算法,使其变为剪枝算法。现在我们已经有了现成的和剪枝算法,只要加上一点儿细节就能完成这个游戏了。 前段时间用 React 写了个2048 游戏来练练手,准备用来回顾下 React 相关的各种技术,以及试验一下新技术。在写这个2048的过程中,我考虑是否可以在其中加...

    wemall 评论0 收藏0
  • Minimax 和 Alpha-beta 剪枝算法简介,以及以此实现井字游戏(Tic-tac-t

    摘要:我们在前文中考虑的那张图就来自这篇文章,之后我们会用剪枝算法来改进之前的解决方案。剪枝算法的实现接下来讨论如何修改前面实现的算法,使其变为剪枝算法。现在我们已经有了现成的和剪枝算法,只要加上一点儿细节就能完成这个游戏了。 前段时间用 React 写了个2048 游戏来练练手,准备用来回顾下 React 相关的各种技术,以及试验一下新技术。在写这个2048的过程中,我考虑是否可以在其中加...

    Eirunye 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<