简体   繁体   English

来自C,我需要一些帮助来弄清楚如何从输入字符串中最佳生成Chess-Bitmaps

[英]Coming from C, I need some help figuring out, how to best generate Chess-Bitmaps from an input-string

I'm attempting to generate some Bitmaps from an input-string for the chess-variant "Anti-King Chess". 我正在尝试从象棋变体“反王象棋”的输入字符串中生成一些位图。 Unfortunately I have to do it in Java, which I'm not super familiar with. 不幸的是,我必须用Java来做,但我并不十分熟悉。 In the few lines of code i wrote so far I already found that a few things are thought about very differently in Java than in C and it's derivatives. 到目前为止,在我写的几行代码中,我已经发现,在Java和C及其派生类中,对某些事情的看法大不相同。

Like you see in the except below, I have a constructor, that takes the board as string. 就像您在下面的例外中看到的那样,我有一个构造函数,它将木板作为字符串。 I iterate over it and call the function placePiece with the corresponding bitmap-long, so that that might get updated correctly. 我对其进行迭代,并使用相应的位图长调用函数placePiece,以便可以正确更新它。

Now I come to my first question : Since you can't make a "call-by-reference" in Java I decided to return the updated long. 现在,我要问的第一个问题是 :由于您无法用Java进行“按引用调用”,因此我决定返回更新的long。 That feels pretty "hacky". 感觉很“ hacky”。 What would be a better way of updating the bitmaps without writing a function for every type of piece? 在不为每种类型的片段编写函数的情况下,更新位图的更好方法是什么?

Second Question: What does Java do, when I assign the return value of a function to a variable? 第二个问题:将函数的返回值分配给变量时,Java会做什么? Is it as run-time efficient as just changing a global variable, like I do with "pieces", "whitePieces" and "blackPieces"? 是否像我对“ pieces”,“ whitePieces”和“ blackPieces”所做的那样,像更改全局变量一样具有运行时效率?

    /*
 * Parse the starting board state and build the corresponding bitmaps 
 */
public Board(String[] board) {

    //Go through all lines
    for(int i = 0; i < board.length; i++) {
        //Go through all positions
        for(int j = 0; j < board[i].length(); j++) {
            switch(board[i].charAt(j)) {
                //Pawns
                case 'P': pawns = placePiece(pawns, i, j, true); break;
                case 'p': pawns = placePiece(pawns, i, j, false); break;

                //Bishop
                case 'B': bishops = placePiece(bishops, i, j, true); break;
                case 'b': bishops = placePiece(bishops, i, j, false); break;

                //Rook
                case 'R': rooks = placePiece(rooks, i, j, true); break;
                case 'r': rooks = placePiece(rooks, i, j, false); break;

                //Knight
                case 'N': knights = placePiece(knights, i, j, true); break;
                case 'n': knights = placePiece(knights, i, j, false); break;

                //Queen
                case 'Q': queens = placePiece(queens, i, j, true); break;
                case 'q': queens = placePiece(queens, i, j, false); break;

                //King
                case 'K': kings = placePiece(kings, i, j, true); break;
                case 'k': kings = placePiece(kings, i, j, false); break;

                //Anti-King
                case 'A': antikings = placePiece(antikings, i, j, true); break;
                case 'a': antikings = placePiece(antikings, i, j, true); break;

            }
        }
    }

}

/*
 * Function to place a Piece at the appropriate place in the bitmaps
 */
private long placePiece(long map, int row, int column, boolean white) {

    //Place a 1 in the right position of the pieces long
    pieces |= 1L << (row*COLUMN_NUM + column);

    //Place a 1 at the right position in either the black or white pieces
    if(white == true) {
        whitePieces |= 1L << (row*COLUMN_NUM + column);
    }else {
        blackPieces |= 1L << (row*COLUMN_NUM + column);
    }

    //Place a 1 at the right position in the pawn long and return the changed set
    return map | 1L << (row*COLUMN_NUM + column);
}

Edit: Changed (long)1 to 1L as suggested by RaceYouAnytime. 编辑:根据RaceYouAnytime的建议,将(long)1更改为1L

In java all primitive types are immutable, so there is no way of updating a long . 在Java中,所有基本类型都是不可变的,因此无法更新long

What you did is right. 你做的是对的。

You are asking questions about performance that are much above the pay grade of the typical developer. 您在问有关性能的问题,这些问题远远超出了典型开发人员的薪水等级。

To have true answers to your question one should look at the bytecode generated after compilation. 为了对您的问题有真实的答案,应该查看编译后生成的字节码。

For example you can ask yourself if your placePiece function would be inlined or not (which possibly has a much higher impact then updating a global varible or not). 例如,您可以问自己是否将内联placePiece函数(这可能比更新全局变量有更大的影响)。

Java programmers are not really much obsessed by performance, not when dealing with in-memory operation, since we mostly deal with IO (DB, HTTP, Files) which are order of magnitude slower then memory. Java程序员对性能的关注不是很大,而不是在处理内存操作时,因为我们主要处理的是IO(DB,HTTP,Files),它们的速度要比内存慢几个数量级。

So, in general we try to optimize IO, but we care much less about in memory ops. 因此,总的来说,我们尝试优化IO,但对内存操作的关心却少得多。

I think you can scrape some microseconds by checking if your methods gets inlined, if not so you may use static final methods, which are essentially faster. 我认为您可以通过检查方法是否内联来节省几微秒的时间,否则,可以使用static final方法,该方法本质上更快。

Methods in java are all virtual apart from final methods which cannot be overridden. Java中的方法都是虚拟的 ,而final方法则不能被覆盖。

Use primitive when you can (but often the compiler would do that for you). 可以使用原始类型(但编译器通常会为您执行此操作)。

That being said, concerning coding style ... you almost never use final method, an try not to use primitives, which goes against my performance tips, but fits into the java mentality of abstracting as much as you can even at the expense of performance (up to a point). 话虽这么说,关于编码风格...您几乎从不使用final方法,一种不使用原语的尝试,这违背了我的性能提示,但即使您以牺牲性能为代价,也尽可能地适应Java抽象思想(在一定程度上)。

All primitive types have wrapper classes in Java that can be used to avoid the problem you're talking about 所有原始类型在Java中都有包装器类,可用于避免您正在谈论的问题

Should I just pass a one-element Array with it then? 那我应该只传递一个元素数组吗?

Just use Long. 只需使用Long。 (the wrapper class) (包装器类)

private void placePiece(Long map, int row, int column, boolean white) {

documentation can be found here: https://docs.oracle.com/javase/7/docs/api/java/lang/Long.html 文档可以在这里找到: https : //docs.oracle.com/javase/7/docs/api/java/lang/Long.html

Note that instantiating a Long value is more efficient if you use the "valueOf()" method. 请注意,如果使用“ valueOf()”方法,则实例化Long值会更有效。

https://docs.oracle.com/javase/7/docs/api/java/lang/Long.html#valueOf(long) https://docs.oracle.com/javase/7/docs/api/java/lang/Long.html#valueOf(long)

Long pawns = Long.valueOf(14L);
...
placePiece(pawns, i, j, true); break;

Also, since you're concerned about efficiency, you may want to stick with primitive types. 另外,由于您担心效率,因此您可能希望坚持使用原始类型。 In that case, though, it would be more efficient to type 1L rather than (long)1 so that you aren't recasting one primitive type to another every time you instantiate. 但是,在那种情况下,键入1L而不是(long)1会更有效,这样您就不必在每次实例化时都将一种原始类型重铸为另一种原始类型。

I found a great solution for my problem here: https://chessprogramming.wikispaces.com/Bitboard+Board-Definition 我在这里找到了解决我的问题的好方法: https : //chessprogramming.wikispaces.com/Bitboard+Board-Definition

Basically, you define an array, that contains all the bitmaps, then you define constants, in the given example an Enum, which doesn't work in Java, but there are ways to define constants. 基本上,您定义一个包含所有位图的数组,然后定义常量,在给定的示例中为Enum,它在Java中不起作用,但是有定义常量的方法。 Then you just have to pass the constant and can have the array, that contains all the bitmaps globally. 然后,您只需要传递常量就可以拥有数组,该数组包含全局所有位图。

You then call it by invoking something like board[PAWN] . 然后,您可以通过调用诸如board[PAWN]类的名称来调用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM