Java 测试井字游戏获胜条件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18548265/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 08:57:06  来源:igfitidea点击:

testing tic tac toe win condition

javaalgorithmperformance

提问by wjhplano

I'm looking for the most efficient javaway to test if somebody has won at tic tac toe. The data is in a 2d array like so...

我正在寻找最有效的Java方式来测试是否有人在井字游戏中获胜。数据在一个二维数组中,就像这样......

char[][] ticTacToe = 
    {{'X',' ','O'},
     {'O','X','O'},
     {'X',' ','X'},};

I know this isn't the professional way to initialize an array but I'm just testing here.

我知道这不是初始化数组的专业方法,但我只是在这里测试。

The best I can do for right now is an exhaustive if/else tree. Here's one of those trees...

我现在能做的最好的是一个详尽的 if/else 树。这是其中一棵树...

if (ticTacToe[1][1] == 'X'){
        if (ticTacToe[0][0] == 'X'){
            if (ticTacToe[2][2] == 'X'){
                System.out.println("X wins");
            }
        }
        else if (ticTacToe[0][1] == 'X'){
             if (ticTacToe[2][1] == 'X'){
                System.out.println("X wins");
            }
        }
        else if (ticTacToe[1][0] == 'X'){
             if (ticTacToe[1][2] == 'X'){
                System.out.println("X wins");
            }
        }
        else if (ticTacToe[2][0] == 'X'){
             if (ticTacToe[0][2] == 'X'){
                System.out.println("X wins");
            }
        }
    }

This one only cares about what's in the middle

这个只关心中间的东西

This is very basic and I want to improve it as far as minimizing lines of code goes.

这是非常基本的,我想改进它,尽量减少代码行。

采纳答案by MrLore

It's a bit verbose, but I think this is probably the most efficient way to do it (unless someone can come up with a clever way to check both diagonals at once).

这有点冗长,但我认为这可能是最有效的方法(除非有人能想出一种聪明的方法同时检查两条对角线)。

public class TicTacToe
{
    char[][] ticTacToe = 
    {{'X',' ','O'},
     {'O','X','O'},
     {'X',' ','X'},};

    private Character winner = null;

    public Character getWinner()
    {
        return this.winner;
    }

    public boolean isSolved()
    {
        this.checkSolved();
        return this.winner != null;
    }

    private void checkSolved()
    {
        for(int i = 0; i < ticTacToe.length; i++)
        {
            Character win = checkRow(i);
            if(win != null || (win = checkColumn(i)) != null)
            {
                this.winner = win;
                return;
            }
        }
        //Check diagonal top left to bottom right
        if(this.ticTacToe[0][0] != ' ')
        {
            if(this.ticTacToe[0][0] == this.ticTacToe[1][1] &&
               this.ticTacToe[1][1] == this.ticTacToe[2][2])
            {
                this.winner = this.ticTacToe[0][0];
            }
        }
        //Check diagonal top right to bottom left
        else if(this.ticTacToe[0][2] != ' ')
        {
            if(this.ticTacToe[0][2] == this.ticTacToe[1][1] &&
               this.ticTacToe[1][1] == this.ticTacToe[2][0])
            {
                this.winner = this.ticTacToe[0][2];
            }
        }
    }

    private Character checkRow(int row)
    {
        if(this.ticTacToe[row][0] == ' ')
        {
            return null;
        }
        if(this.ticTacToe[row][0] == this.ticTacToe[row][1] &&
           this.ticTacToe[row][1] == this.ticTacToe[row][2])
        {
            return this.ticTacToe[row][0];
        }
        return null;
    }

    private Character checkColumn(int column)
    {
        if(this.ticTacToe[0][column] == ' ')
        {
            return null;
        }
        if(this.ticTacToe[0][column] == this.ticTacToe[1][column] &&
           this.ticTacToe[1][column] == this.ticTacToe[2][column])
        {
            return this.ticTacToe[column][0];
        }
        return null;
    }

    public static void main(String[] args)
    {
        TicTacToe ttt = new TicTacToe();
        if(ttt.isSolved())
        {
            System.out.println(ttt.getWinner());  // X
        }
    }
}

回答by ???? ????

Just for fun, keep two numbers, starting as zeros, one for X, one for O. Update them by oring with the moves. To check for a winner, first and, then xorwith the mask.

只是为了好玩,保留两个数字,从零开始,一个是X,一个是O。通过or移动更新它们。要检查获胜者,首先and,然后xor使用面具。

277 & 273 ^ 273
0  ==> we have a winner.

276 & 273 ^ 273
1  ==> not.

277 == parseInt("100010101",2)
273 == parseInt("100010001",2)
276 == parseInt("100010100",2)

277 == parseInt("100010101",2)
273 == parseInt("100010001",2)
276 == parseInt("100010100",2)

For more fun, here's an example that plays Oin your favorite JavaScript console:

为了更有趣,这里有一个O在您最喜欢的 JavaScript 控制台中播放的示例:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
  </head>
  <body>
    <script>
    var x = 0, o = 0, count = 0, w = 0
        ws = [0007,0070,0700,0111,0222,0444,0124,0421]
    function t1(v){
        var w1 = 0
        for (var i in ws)
            w1 |= !(v & ws[i] ^ ws[i])
        return w1
    }
    function t(i){
        var ot = count % 2, m = 1 << (9 - i), bd = x | o
        if (!ot && (i > 9 || i < 1 || i != Math.floor(i)))
            return "Out of bounds."
        else if (m & bd)
            return "Position taken."
        if (ot){
            var n1 = 0, a1 = -2
            while (bd & (1 << n1))
                n1++
            var n = n1
            while (n1 < 9){
                var m1 = 1 << n1
                if (!(bd & m1)){
                    var bt = -mx(x,o | m1,count + 1)
                     if (bt > a1){
                         a1 = bt
                         n = n1
                     }
                }
                n1++
            }
            w = t1(o |= 1 << n)
        }
        else
            w = t1(x |= m)
        var b = "\n", p = 0400
        while (p > 0){
            if (p & x)
                b += "X"
            else if (p & o)
                b += "O"
            else b += "."
            if (p & 0110)
                b += "\n"
            p >>= 1
        }
        if (w)
            b += "\n\n" + (ot ? "O" : "X") + " wins!"
        else if (!(bd ^ 0777))
            b += "\n\nDraw."
        if (!ot){
            console.log(b + '\n\n"""')
            count++
            console.log(t(-1))
            count++
        }
        else
            return b + "\n"
        return '"'
    }
    function mx(x1,o1,c1){
        var ot1 = c1 % 2, w1 = ot1 ? t1(x1) : t1 (o1),
              b1 = x1 | o1, p = 0400
        if (w1)
            return -1
        if (!(b1 ^ 0777))
            return 0
        var a = -2
        while (p > 0){
            if (!(b1 & p))
                a = Math.max(a,-mx(ot1 ? x1 : x1 | p,ot1 ? o1 | p : o1,c1 + 1))
            p >>= 1
        }
        return a
    }
    console.log('              Plays O!'
            + '\nTo play, type t(MOVE); MOVE is from 1-9')
    </script>
  </body>
</html>

回答by Philipp

There are four different ways to win at tick-tack-toe:

有四种不同的方法可以在滴答声中获胜:

  1. form a horizontal line
  2. form a vertical line
  3. form a diagonal line from the upper-left to the lower-right corner
  4. form a diagonal line from the lower-left to the upper-right corner
  1. 形成一条水平线
  2. 形成一条垂直线
  3. 形成一条从左上角到右下角的对角线
  4. 形成一条从左下角到右上角的对角线

All of these four win-conditions can be solved with a for-loop. The advantage of this solution is that it can be applied to any matrix-size.

所有这四个获胜条件都可以通过 for 循环来解决。此解决方案的优点是它可以应用于任何矩阵大小。

回答by Yu-Han Lyu

For a player, say 'x', there are 8 ways to win and each corresponds to 3 'x' in a row/column/diagonal. Hence, you can create an array of length 8 and each item corresponds to the number of 'x' in that row/column/diagonal. When the player chooses a move, then you update the array and check whether there exists 3 in the array. Although it needs more space, it is easier to generalize to a large board.

对于玩家来说,比如说“x”,有 8 种获胜方式,每种方式对应于一行/列/对角线上的 3 个“x”。因此,您可以创建一个长度为 8 的数组,每个项目对应于该行/列/对角线中“x”的数量。当玩家选择移动时,然后更新数组并检查数组中是否存在 3。虽然它需要更多的空间,但更容易推广到大板。

回答by Marcin Szymczak

Mark board as 3x3 magicSquareand you have win when sum in line is 15.

将棋盘标记为 3x3 magicSquare,当在线总和为 15 时,您就赢了。

enter image description here

在此处输入图片说明