有没有办法避免使用javascript创建一个tic tac toe游戏时的object.prototype.constructor?

时间:2021-07-14 16:46:04

I created a tic tac toe game with JavaScript and took a purely functional approach. However, now I am stuck because I can't seem to be able to make the player be able to choose between x and o. The player is automatically assigned x, but never o. I'm using bootstrap, and I have a modal that appears when the user lands on the page. I have to fulfill a user story in which the user can choose between x and o via the modal buttons. Then the opposite symbol, ie o, would be on the tic tac toe board when the modal is dismissed. That part works fine right now. HOWEVER, if the user is to choose o, and x appears on the board, when the user clicks on a square, another x appears. I don't want an x to appear. An o should appear instead. So basically the user is playing against the board (or you could call it computer if you like), but is able to choose whether he/she wants to play as x or o by pressing on either the x or o button in the modal. Is there any way of making this possible without having to create an object.prototype.constructor? The link to my github repo: https://interglobalmedia.github.io/xoApp/ - sorry for the initial dead link- now it works!

我用JavaScript创建了一个tic tac toe游戏,采用了纯粹的功能方法。但是,现在我被卡住了,因为我似乎无法让玩家能够在x和o之间进行选择。播放器自动分配x,但从不o。我正在使用bootstrap,当用户登陆页面时,我会看到一个模态。我必须完成一个用户故事,用户可以通过模态按钮在x和o之间进行选择。然后,当模态被解除时,相反的符号,即o,将在tic tac toe board上。那部分现在工作正常。但是,如果用户要选择o,并且x出现在电路板上,当用户点击正方形时,会出现另一个x。我不希望出现x。应该出现o。因此,基本上用户正在与棋盘对战(或者如果你愿意,你可以称之为电脑),但是可以通过按下模态中的x或o按钮来选择他/她是想要以x还是o进行游戏。有没有办法使这成为可能,而无需创建object.prototype.constructor?我的github repo的链接:https://interglobalmedia.github.io/xoApp/ - 抱歉最初的死链接 - 现在它可以正常工作!

function fetchBoard() {
   var board = ['', '', '', '', '', '', '', '', ''];
   $(".game-field").each(function (index) {
       board[index] = $(this).html();
   });
   return board;
}

/* return 1 if all params 'x', -1 if o, and otherwise 0 */
function checkRow(a, b, c) {
    if (a === 'x' && b === 'x' && c === 'x') {
        return 1;
    } else if (a === 'o' && b === 'o' && c === 'o') {
        return -1;
    } else {
        return 0;
    }
}
function checkWin(board) {
    return checkRow(board[0], board[1], board[2]) // rows
    + checkRow(board[3], board[4], board[5])
    + checkRow(board[6], board[7], board[8])
    + checkRow(board[0], board[3], board[6]) // columns
    + checkRow(board[1], board[4], board[7])
    + checkRow(board[2], board[5], board[8])
    + checkRow(board[0], board[4], board[8]) // main diagonal rows
    + checkRow(board[2], board[4], board[6]) // reverse diagonal row
}

function selectMove(board) {
    var i, options;
    options = [];
    for (i = 0; i < 9; i += 1) {
        if (board[i] === '') {
            options.push(i);
        }
    }
    if (options.length === 0) {
        return -1;
    } else {
        return options[Math.floor(Math.random() * options.length)];
    }
}

function showGameOver(result) {
    var target = $("#result");
    if (result > 0) {
        target.css('color', '#db0000');
        target.html("you win!");
    } else if (result < 0) {
        target.css('color', "#db0000");
        target.html("i win!");
    } else {
        target.css('color', '#db0000');
        target.html("tie game.");
    }
}

function resetGame() {
    var target;
    $(".game-field").html('');
    target = $("#result");
    target.css('color', '#db0000');
    target.html('click a square');
}

function moveAt() {
    var xCell, board, result, oLocation, oCell;
    xCell = $(this);

    if (xCell.html() !== '' || checkWin(fetchBoard()) !== 0) {
        return;
    }
    xCell.css('color', '#db0000');
    xCell.html('x');
    board = fetchBoard();
    result = checkWin(board);
    if (result !== 0) {
        showGameOver(result);
        return;
    }
    oLocation = selectMove(board);
    if (oLocation < 0) {
        showGameOver();
        return;
    }
    board[oLocation] = 'o';
    oCell = $('#cell' + oLocation);
    oCell.css('color', '#fff');
    oCell.html('o');

    result = checkWin(board);
    if (result !== 0) {
        showGameOver(result);
        return;
    }
}

$(document).ready(function() {
    $('#iconModal').modal('show');
    $('.game-field').click(moveAt);
    $('#tictacreset').click(resetGame);
    resetGame();
});

[1]: https://github.com/interglobalmedia/xoApp/tree/master/src/html

1 个解决方案

#1


0  

now I am stuck because I can't seem to be able to make the player be able to choose between x and o. The player is automatically assigned x, but never o.

现在我被困了,因为我似乎无法让玩家能够在x和o之间做出选择。播放器自动分配x,但从不o。

How are the players assigned? Is this just meant to be played locally on the same browser? When the mouse is clicked, a player's turn is over, and then it is the next player's turn?

如何分配球员?这只是想在同一个浏览器上本地播放吗?当点击鼠标时,玩家的回合结束,然后是下一个玩家的回合?

Is there any way of making this possible without having to create an object.prototype.constructor?

有没有办法使这成为可能,而无需创建object.prototype.constructor?

I might recommend you look at the Kestrel ('constant') combinator

我可能会建议你看一下Kestrel('常数')组合子

const K = x => y => x

const p1 = K('x')
const p2 = K('o')

console.log(p1(), p2(), p1(), p2())
// x o x o

with K, you can pass any value in and all subsequent calls to the resulting function will result in the initial value. If you wanted to associate any other data with a player, you could use K(['x', otherData]) and continue building selectors as needed.

使用K,您可以传入任何值,并且对结果函数的所有后续调用都将产生初始值。如果您想将任何其他数据与播放器相关联,您可以使用K(['x',otherData])并根据需要继续构建选择器。


Or you could define the player using a lambda, I've chosen two fields here, but there's practically no limit on how many you could implement in this way. Add as many as you'd like ^_^

或者您可以使用lambda定义播放器,我在这里选择了两个字段,但实际上没有限制以这种方式实现的数量。添加尽可能多的^ _ ^

const player = (name,marker) => p => p(name,marker)
const playerName = p => p((name,marker) => name)
const playerMarker = p => p((name,marker) => marker)

const p1 = player('Bob', 'x')
const p2 = player('Alice', 'o')

console.log(playerName(p1), playerMarker(p1))
// Bob x

console.log(playerName(p2), playerMarker(p2))
// Alice o

I hope I understood the intent of your question and that the information provided here is helpful in some way. If not, please let me know. I'm happy to helper further.

我希望我理解你的问题的意图,并且这里提供的信息在某种程度上是有帮助的。如果没有,请告诉我。我很乐意进一步帮忙。

#1


0  

now I am stuck because I can't seem to be able to make the player be able to choose between x and o. The player is automatically assigned x, but never o.

现在我被困了,因为我似乎无法让玩家能够在x和o之间做出选择。播放器自动分配x,但从不o。

How are the players assigned? Is this just meant to be played locally on the same browser? When the mouse is clicked, a player's turn is over, and then it is the next player's turn?

如何分配球员?这只是想在同一个浏览器上本地播放吗?当点击鼠标时,玩家的回合结束,然后是下一个玩家的回合?

Is there any way of making this possible without having to create an object.prototype.constructor?

有没有办法使这成为可能,而无需创建object.prototype.constructor?

I might recommend you look at the Kestrel ('constant') combinator

我可能会建议你看一下Kestrel('常数')组合子

const K = x => y => x

const p1 = K('x')
const p2 = K('o')

console.log(p1(), p2(), p1(), p2())
// x o x o

with K, you can pass any value in and all subsequent calls to the resulting function will result in the initial value. If you wanted to associate any other data with a player, you could use K(['x', otherData]) and continue building selectors as needed.

使用K,您可以传入任何值,并且对结果函数的所有后续调用都将产生初始值。如果您想将任何其他数据与播放器相关联,您可以使用K(['x',otherData])并根据需要继续构建选择器。


Or you could define the player using a lambda, I've chosen two fields here, but there's practically no limit on how many you could implement in this way. Add as many as you'd like ^_^

或者您可以使用lambda定义播放器,我在这里选择了两个字段,但实际上没有限制以这种方式实现的数量。添加尽可能多的^ _ ^

const player = (name,marker) => p => p(name,marker)
const playerName = p => p((name,marker) => name)
const playerMarker = p => p((name,marker) => marker)

const p1 = player('Bob', 'x')
const p2 = player('Alice', 'o')

console.log(playerName(p1), playerMarker(p1))
// Bob x

console.log(playerName(p2), playerMarker(p2))
// Alice o

I hope I understood the intent of your question and that the information provided here is helpful in some way. If not, please let me know. I'm happy to helper further.

我希望我理解你的问题的意图,并且这里提供的信息在某种程度上是有帮助的。如果没有,请告诉我。我很乐意进一步帮忙。