How to avoid very big win condition in old woman’s game?

Asked

Viewed 339 times

5

I made an old game that checks the user’s win conditions with if, however did not find an elegant solution. I am trying to develop a method to verify the condition of victory with array, but I’m not succeeding, follow the code:

// Variaveis Globais
var jogador = 'x';
var jogadas = 0;
//var vitoria = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]];

// Inicia a jogada
function chkJogo(id) {
    var src = chkSrc(id);

    // Muda a imagem de acordo com o jogador
    if (src == "branco.png") {
        document.getElementById(id).src = "img/" + jogador + ".png";
        jogadas++;

        if (chkVitoria()) {
            alert("Fim do jogo! Vitória do " + jogador);
            return;
        }

        // Verifica se deu empate
        if (jogadas >= 9) {
            alert('Empate!');
            return;
        }

        if (jogador == 'x') {
            jogador = 'o';
        } else {
            jogador = 'x';
        }
    } else {
      //  alert('som erro, célula já usada');
    }

    // Verifica se é a vez do computador jogar, caso sim, o computador faz a jogada
    if (jogador == 'o') {
        chkJogo(compJogar());
    }
};

// Selecionando elemento da célula
function chkSrc(id) {
    var src = document.getElementById(id).src;
    return src.substring(src.length - 10, src.length);
};

// Computador realiza a sua jogada
function compJogar() {
    return Math.floor(Math.random() * 8);
}


// Condições de vitória
function chkVitoria() {
    if ((chkSrc('0') == chkSrc('1')) && (chkSrc('0') == chkSrc('2')) && chkSrc('0') != 'branco.png') {
        return true;
    }
    if ((chkSrc('3') == chkSrc('4')) && (chkSrc('3') == chkSrc('5')) && chkSrc('3') != 'branco.png') {
        return true;
    }
    if ((chkSrc('6') == chkSrc('7')) && (chkSrc('6') == chkSrc('8')) && chkSrc('6') != 'branco.png') {
        return true;
    }
    if ((chkSrc('0') == chkSrc('3')) && (chkSrc('0') == chkSrc('6')) && chkSrc('0') != 'branco.png') {
        return true;
    }
    if ((chkSrc('1') == chkSrc('4')) && (chkSrc('1') == chkSrc('7')) && chkSrc('1') != 'branco.png') {
        return true;
    }
    if ((chkSrc('2') == chkSrc('5')) && (chkSrc('2') == chkSrc('8')) && chkSrc('2') != 'branco.png') {
        return true;
    }
    if ((chkSrc('0') == chkSrc('4')) && (chkSrc('0') == chkSrc('8')) && chkSrc('0') != 'branco.png') {
        return true;
    }
    if ((chkSrc('2') == chkSrc('4')) && (chkSrc('2') == chkSrc('6')) && chkSrc('2') != 'branco.png') {
        return true;
    }
};
#tabela {
    border: 1px solid dodgerblue;
    align="center";
}

body {
    background-color: beige;
}
<!DOCTYPE html>
<html>

<head lang="pt-br">
    <meta charset="utf-8">
    <title>Jogo da Velha</title>
    <script type="text/javascript" src="js/jogoDaVelha.js"></script>
    <link rel="stylesheet" type="text/css" href="css/jogoDaVelha.css">
</head>

<body>

    <table id="tabela">
        <tr>
            <td><img src="img/branco.png" id="0" onclick="chkJogo(this.id)"></td>
            <td><img src="img/branco.png" id="1" onclick="chkJogo(this.id)"></td>
            <td><img src="img/branco.png" id="2" onclick="chkJogo(this.id)"></td>
        </tr>
        <tr>
            <td><img src="img/branco.png" id="3" onclick="chkJogo(this.id)"></td>
            <td><img src="img/branco.png" id="4" onclick="chkJogo(this.id)"></td>
            <td><img src="img/branco.png" id="5" onclick="chkJogo(this.id)"></td>
        </tr>
        <tr>
            <td><img src="img/branco.png" id="6" onclick="chkJogo(this.id)"></td>
            <td><img src="img/branco.png" id="7" onclick="chkJogo(this.id)"></td>
            <td><img src="img/branco.png" id="8" onclick="chkJogo(this.id)"></td>
        </tr>
    </table>

</body>

</html>

As can be verified, with numerous functions if works, but as I said is repeating the code a lot. How to reduce this repetition (mainly in win condition).

  • Behold: Check Old Play Winner. Has a if validation and a single if and a loop in the logic of checking the winner. It’s in Java but I don’t think it’s a problem for you.

2 answers

6

I found the method below in that Old game tutorial and adapted in its function, as I have not tested, it is possible that it is necessary to convert the calculation to string to work properly.

function chkVitoria() {

// checar linhas
   for(var i = 0; i <= 6; i = i + 3) {
        if(chkSrc(i) !== "branco.png" && chkSrc(i) == chkSrc(i + 1) && chkSrc(i + 1) == chkSrc(i + 2)) {
            return true;
        }
    }


// checar colunas
   for(var i = 0; i <= 2 ; i++) {
        if(chkSrc(i) !== "branco.png" && chkSrc(i) == chkSrc(i + 3) && chkSrc(i + 3) == chkSrc(i + 6)) {
            return true;
        }
    }


//checar diagonais
    for(var i = 0, j = 4; i <= 2 ; i = i + 2, j = j - 2) {
        if(chkSrc(i) !== "branco.png" && chkSrc(i) == chkSrc(i + j) && chkSrc(i + j) == chkSrc(i + 2*j)) {
            return true;
        }
    }

};
  • 2

    The idea I think is cool, it is worth mentioning to simplify a bit reusing the same loops(s) (use the row and column with the coordinates reversed, for example). A loop and 4 test lines is one of the possible variations. 2 chained loops is another.

6

If the problem is having a lot of if, can do with zero if:

function chkVitoria() {
    return ((chkSrc('0') == chkSrc('1')) && (chkSrc('0') == chkSrc('2')) && chkSrc('0') != 'branco.png') ||
           ((chkSrc('3') == chkSrc('4')) && (chkSrc('3') == chkSrc('5')) && chkSrc('3') != 'branco.png') ||
           ((chkSrc('6') == chkSrc('7')) && (chkSrc('6') == chkSrc('8')) && chkSrc('6') != 'branco.png') ||
           ((chkSrc('0') == chkSrc('3')) && (chkSrc('0') == chkSrc('6')) && chkSrc('0') != 'branco.png') ||
           ((chkSrc('1') == chkSrc('4')) && (chkSrc('1') == chkSrc('7')) && chkSrc('1') != 'branco.png') ||
           ((chkSrc('2') == chkSrc('5')) && (chkSrc('2') == chkSrc('8')) && chkSrc('2') != 'branco.png') ||
           ((chkSrc('0') == chkSrc('4')) && (chkSrc('0') == chkSrc('8')) && chkSrc('0') != 'branco.png') ||
           ((chkSrc('2') == chkSrc('4')) && (chkSrc('2') == chkSrc('6')) && chkSrc('2') != 'branco.png');
};

I put in the Github for future reference.

It also has how to create a array and check with for, but I don’t know if it pays.

I’m not analyzing whether the condition of victory is correct.

  • I understand, but it’s still repeating a lot of code. In any case I’ll keep trying. Thank you very much for your help!

  • Deleting Code repetition should not be a goal to be pursued. http://answall.com/q/120931/101

  • I will leave to review later anyway, when my knowledge is greater, otherwise I will waste a lot of time. Again thank you!

  • What if it was a larger board, therefore needing more and more conditions? It is not very flexible. Not to mention that if one is to cherish elegance, one will want something more concise (but this is still a matter of style)

  • 2

    @Emoon this is an old-fashioned game.

  • 2

    Who negative can say what’s wrong that I correct.

  • 2

    @bigown Probably someone who will make a "super stylish" algorithm of 15 or 20 lines, to eliminate 9 of comparison :P "ah, but it goes that in the future the game of the old woman will have 20 houses" kkk PS: before someone says some bullshit, it is clear that his answer was to what was asked, and to create a situation to think about, and not a dispute of generic algorithms, but it is a conversation that unfortunately here does not help much.

  • @Bacco Funny, because the other answer managed to produce the same result with a bit less characters. But I guess you figured that out already, huh?

  • 1

    @Emoon I think code doesn’t just evaluate by number of characters, and probably Bigown would have a lot of alternatives to post, shorter and longer (at least, I would have). The question is that the answer focuses on what the author said about decreasing the number of ifs, and a solution was shown without any if. Both answers solve, are correct (I voted for both) and loops is even less performative. I think whoever gave you -1 doesn’t know very well what they’re evaluating, that’s my point. Now, it may be that the person has a legitimate reason, but then just comment on the reason.

  • 1

    Even, if the person comments, has 2 paths, both good: one of them is the Bigown recognize some problem and improve the answer (I can not speak for it, but if it was with me it would be so). Or, whoever voted may have an explanation of why the answer was made that way, and perhaps add some knowledge. See my comment in the reply with loops, for example. If the code were mine, it would be much shorter, but I’m not going to deny an answer that’s right. In addition, there is a reason for the site to have a question and multiple answers: allow different ways to solve problems.

  • @Bacco of course can speak for me, after all it was what I have always done here, whenever someone says there is something really wrong, I repair or erase the answer. But I think the negative was a little nitpicking with some detail that doesn’t really matter, so there’s nothing to fix. I may be wrong, but the person doesn’t pronounce. In fact I gave the simplest solution, that any programmer understands, mainly for the AP that is still beginner. As a bonus it is more performative. I could do others, but this is the most appropriate question.

  • If it is p/ make a solution Clever I’d do a lot better than the other answer, but that’s not the point. I believe he can do it too, but you don’t have to look for the shortest thing, the one with the least characters. There’s a difference between meeting a requirement and standing around disputing who made the most ingenious algorithm. I trust my answer, if I could not switch to another.

  • @Bacco I agree that code is not evaluated by characters only, but at the same time I would never implement a more elegant solution if it were to make the code even bigger (unlike what you - sarcastically - suggested). And, of course, there is the question of performance, but it is up to those who implement, put in the balance and see what more compensates according to their convictions

  • 1

    @Bigown I was the one who was negative (sorry if that wasn’t clear) for the simple reason that it doesn’t solve what the OP wants: elegance and reduce repetitions. Whether or not he is right in wanting this, is another story; and it goes according to the style of code of each. Besides, there is nothing I could talk about, beyond what I have already said, to improve the answer, because there we again bump into the question of opinion. Therefore, the downvote is just my way of (respectfully) disagreeing

  • 1

    @Emoon respect this opinion of yours, my comment was only an irony to the -1, because I found it inappropriate. As I said, I find both valid. Endearing that someone might not like the answer given here and vote only on the other, for example. Negative something that works only because it does not follow a certain style, I find it a little exaggerated. Remembering also that part of the volume of the answer given is more lack of optimization in the original code than in the answer. More than that: if anyone is in favor of negativizing the wrong thing here on the site is me, even more I q see both positive wrong. I just found it disproportionate.

  • 3

    @Emoon as to your right to disagree, it’s really your right. But I irony is a way to express myself too, in the face of something I disagree with. I hope that has become clear the reason for the comment as well. But in every way, if you understand that it is correct, it is your right to vote, although I understand that the purpose of -1 is another (although it is used as a disagreement on the Meta site, specifically). Obviously, if there had been an open manifestation of the negative, I, instead of "nudging", would have already directly exposed the reason for the disagreement.

  • 1

    @Bacco is no use, it’s a waste of time, it was clear that size is what matters to him, see "I would never implement a more elegant solution if it were to make the code even bigger". At least it was clear that the vote was opinionated and not that there was any mistake. Whoever reads it will see that it is a vote of exaggeration based on an opinion that I obviously disagree with. Codes should be pragmatic, they should not take into account the number of characters. What was useful to reduce I reduced. Can you do better? Certainly, but have to redo all the code. AP may not understand anything of the solution "short".

Show 12 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.