Return 在 JS Connect-Four 中获胜的单元格坐标

Return winning cell coordinates in JS Connect-Four

我正在开发一款 JS 连连四游戏。我的 'board' 是一个 7 * 6 维数组(0 = 空,1 = 玩家 A 占用,-1 = 玩家 B 占用)。

var boardTwo = [[1,1,1,1,0,0],[-1,-1,-1,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0]];

这是我的(冗长的)函数,用于检查获胜(任一玩家是否在棋盘上创建了一条完整的水平、垂直或对角线长度 4)。我如何修改它,使它 return 是一个包含获胜计数器坐标的数组,而不是简单的警报消息?我很欣赏最好的解决方案可能包括放弃我原来的 checkWin 函数来代替更简洁的函数。

checkWin = function(board){
    checkVert(board);
    checkHoriz(board);
    checkDia(board);
    }
winAlert = function(checkSum){
    if(checkSum == 4){
        status = "a"
        alert("a wins"); 
    }
    else if(checkSum == -4){
        status = 'b';
        alert("b wins"); 
    }
}
checkVert = function(board){
    for(var i = 0; i < board.length; i++){
       for(var j = 0; j < board[0].length - 3; j++){
           var checkSum = board[i][j] + board[i][j+1] + board[i][j+2] + board[i][j+3];
           winAlert(checkSum);
           }
    }
}

checkHoriz = function(board){
    for(var i = 0; i < board.length-3; i++){
      for(var j = 0; j < board[0].length; j++){
        var checkSum = board[i][j] + board[i+1][j] + board[i+2][j] + board[i+3][j];
        winAlert(checkSum);
      }
    }
  }

checkDia = function(board){
    for(var i = 0; i < board.length-3; i++){
      for(var j = 0; j < board[0].length - 3; j++){
        var checkSum = board[i][j] + board[i+1][j+1] + board[i+2][j+2] + board[i+3][j+3];
    winAlert(checkSum);
        }
      }
    }
checkWin(boardTwo) //alerts "player A wins"

我想要 checkWin(boardTwo) 到 return [[0,0],[0,1],[0,2],[0,3]];

这是一个简单的解决方案:

    如果有人赢了,
  • winAlert 应该 return 一个数字,例如A 为 1,B 为 -1
  • 每个 check 函数都会检查这个结果,如果它是 -1 或 1,那么它将插入它检查的值
  • 如果 check 方法 return 不是未定义的东西,即带有答案的数组,则不应进行其他检查
  • 最后 state 保存谁赢了 (-1, 1 or undefined) 并且 returning 值 checkWin 将是一个数组数组如果有人赢了

我还对 checkDiagonal 方法进行了额外检查,以检查矩阵中存在的其他对角线

function sgn(x) {
  if (x < 0) return -1;
  if (x > 0) return 1;
  return 0;
}

function interpolate(from, to) {
  var coordinates = [];
  var startX = from[0];
  var startY = from[1];
  var limit = Math.max(
    Math.abs(from[0] - to[0]),
    Math.abs(from[1] - to[1])
  ) + 1;
  for (i = 0; i < limit; i += 1) {
    coordinates.push([
      startX + i * sgn(to[0] - from[0]),
      startY + i * sgn(to[1] - from[1])
    ]);
  }
  return coordinates;
}

var state;
function checkWin(board) {
  var ans;
  ans = ans || checkVert(board);
  ans = ans || checkHoriz(board);
  ans = ans || checkDia(board);
  return ans;
}

function winAlert(checkSum) {
  if (Math.abs(checkSum) === 4) {
    state = sgn(checkSum);
    return state;
  }
}

checkVert = function(board) {
  for (var i = 0; i < board.length; i++) {
    for (var j = 0; j < board[0].length - 3; j++) {
      var checkSum = board[i][j] + board[i][j + 1] + board[i][j + 2] + board[i][j + 3];
      if (winAlert(checkSum)) {
        return interpolate([i, j], [i, j + 3]);
      }
    }
  }
}

checkHoriz = function(board) {
  for (var i = 0; i < board.length - 3; i++) {
    for (var j = 0; j < board[0].length; j++) {
      var checkSum = board[i][j] + board[i + 1][j] + board[i + 2][j] + board[i + 3][j];
      if (winAlert(checkSum)) {
        return interpolate([i, j], [i + 3, j]);
      }
    }
  }
}

checkDia = function(board) {
  for (var i = 0; i < board.length - 3; i++) {
    for (var j = 0; j < board[0].length - 3; j++) {
      var checkSum = board[i][j] + board[i + 1][j + 1] + board[i + 2][j + 2] + board[i + 3][j + 3];
      if (winAlert(checkSum)) {
        return interpolate([i, j], [i + 3, j + 3]);
      }
    }
  }
  
  // missing diagonal
  for (i = 3; i < board.length; i += 1) {
    for (var j = 0; j < board[0].length - 3; j++) {
      var checkSum = board[i][j] + board[i - 1][j + 1] + board[i - 2][j + 2] + board[i - 3][j + 3];
      if (winAlert(checkSum)) {
        return interpolate([i, j], [i - 3, j + 3]);
      }
    }
  }
}

var board = [
  [1, 1, 1, 0, 0, 0],
  [-1, -1, -1, -1, 0, 0],
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0]
];

var ans = checkWin(board) || [];
document.write(state + '<pre>' + JSON.stringify(ans) + '</pre>');

我看到现在已经有答案了。我想我应该早点回来。我也一直在 JSFiddle 中研究这个版本。请参阅 link 以了解游戏的工作(虽然简单)版本:http://jsfiddle.net/42tfrsva/2/

这不是实体版游戏的代表,您必须从底部开始逐步向上。但是,“checkScore()”方法在任何一种情况下都将相同,以扫描棋盘以获取胜利。在这种情况下,方法 return 是组成该行的复选框元素,但它可以很容易地修改为 return 每个单元格的坐标。

代码 - HTML

<table>
    <tr>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
    </tr>
    <tr>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
    </tr>
    <tr>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
    </tr>
    <tr>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
    </tr>
    <tr>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
    </tr>
    <tr>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
        <td><input type="checkbox" value="0" /></td>
    </tr>
</table>
<div id="player">Player 1</div>
<button id="reset">Reset</button>

代码 - CSS

.player1 {
    background-color: red;
}

.player2 {
    background-color: blue;
}

.winner {
    background-color: green;
}

代码 - JS

var player = 1;

//Set up check events
var cbs = checkboxes();
for (var t = 0; t < cbs.length; t++){
    cbs[t].onclick = checkClick;
}

//Set up reset event
$id("reset").onclick = resetClick;

function resetClick() {
    var cbs = checkboxes();
    for (var c = 0; c < cbs.length; c++) {
        cbs[c].checked = false;
        cbs[c].value = 0;
        cbs[c].parentNode.className = "";
    }
    player = 1;
    $html("player", "Player 1");
}

//create functions
function $id(id) {
    return document.getElementById(id);
}

function $tags(tag, parent) {
    parent = (parent) ? parent : document;
    return parent.getElementsByTagName(tag);
}

function $html(id, html) {
    var el = $id(id);
    if (el) el.innerHTML = html;
}

function checkboxes() {
    var tags = $tags("input");
    var cbs = [];
    for (var t = 0; t < tags.length; t++) {
        if (tags[t].type == "checkbox")
            cbs.push(tags[t]);
    }
    return cbs;
}

function checkClick(e) {
    if (!e || !e.target || !e.target.parentNode
       || e.target.value != "0") {
        e.preventDefault();
        return false;
    }

    e.target.parentNode.className = "player" + player;
    e.target.value = player;

    var path = checkScore();
    if (path.length == 4) {
        alert("Winner player " + player + "!");
        for (var p = 0; p < path.length; p++)
            path[p].parentNode.className = "winner";
    }

    player = (player == 1) ? 2 : 1;
    $html("player", "Player " + player);
}

function valueArray() {
    var values = [];
    var cbs, trs = $tags("tr", $tags("table")[0]);

    for (var t = 0; t < trs.length; t++) {
        cbs = $tags("input", trs[t]);
        var cbarr = [];

        for (var c = 0; c < cbs.length; c++) {
            cbarr.push(cbs[c].value*1);
        }
        values.push(cbarr);
    }

    return values;
}

function cbArray() {
    var values = [];
    var cbs, trs = $tags("tr", $tags("table")[0]);

    for (var t = 0; t < trs.length; t++) {
        cbs = $tags("input", trs[t]);
        var cbarr = [];

        for (var c = 0; c < cbs.length; c++) {
            cbarr.push(cbs[c]);
        }
        values.push(cbarr);
    }

    return values;
}

function checkScore() {
    var path = [];
    var values = valueArray();
    var cbs = cbArray();

    //check up/down
    for (var r = 0; r < 3; r++) {
        for (var c = 0; c < 7; c++) {
            if (values[r][c] == player && values[r+1][c] == player &&
                values[r+2][c] == player && values[r+3][c] == player) {
                path = new Array(
                    cbs[r][c], cbs[r+1][c],
                    cbs[r+2][c], cbs[r+3][c]
                );
                return path;
            }
        }
    }

    //check left/right
    for (var r = 0; r < 6; r++) {
        for (var c = 0; c < 4; c++) {
            if (values[r][c] == player && values[r][c+1] == player &&
                values[r][c+2] == player && values[r][c+3] == player) {
                path = new Array(
                    cbs[r][c], cbs[r][c+1],
                    cbs[r][c+2], cbs[r][c+3]
                );
                return path;
            }
        }
    }

    //check right diagonal
    for (var r = 0; r < 3; r++) {
        for (var c = 0; c < 4; c++) {
            if (values[r][c] == player && values[r+1][c+1] == player &&
                values[r+2][c+2] == player && values[r+3][c+3] == player) {
                path = new Array(
                    cbs[r][c], cbs[r+1][c+1],
                    cbs[r+2][c+2], cbs[r+3][c+3]
                );
                return path;
            }
        }
    }

    //check left diagonal
    for (var r = 0; r < 3; r++) {
        for (var c = 3; c < 7; c++) {
            if (values[r][c] == player && values[r+1][c-1] == player &&
                values[r+2][c-2] == player && values[r+3][c-3] == player) {
                path = new Array(
                    cbs[r][c], cbs[r+1][c-1],
                    cbs[r+2][c-2], cbs[r+3][c-3]
                );
                return path;
            }
        }
    }

    return path;
}

我意识到您不必检查每个单元格。在 checkScore 方法的每个循环中,row/column 循环仅限于获取垂直线、水平线和对角线所需的单元格。