Điểm một trò chơi cờ vây


23

Ghi một Go trò chơi là một nhiệm vụ đó không phải là tất cả quá dễ dàng. Trong quá khứ đã có một vài cuộc tranh luận về cách thiết kế các quy tắc để bao quát tất cả các trường hợp góc lạ có thể xảy ra. May mắn thay, trong nhiệm vụ này, bạn không phải làm những việc phức tạp như sự sống và cái chết hoặc phát hiện seki. Trong nhiệm vụ này, bạn phải thực hiện một chương trình chấm điểm một trò chơi theo quy tắc Tromp-Taylor mà không có Komi.
Thủ tục tính điểm khá đơn giản:

một điểm P, không được tô màu C, được cho là đạt tới C, nếu có một đường dẫn (theo chiều dọc hoặc chiều ngang) các điểm liền kề của màu P từ P đến một điểm màu C.
Điểm của người chơi là số điểm màu của cô ta , cộng với số điểm trống chỉ đạt màu của cô ấy.

Ví dụ, hãy xem xét bảng sau. X, O-biểu thị màu đen, trắng và không bị nhuộm màu nút giao thông:

- - - X - O - - -
- - - X - O - - -
- - - X - O - - -
- - - X O - - O -
X X X O - O O - -
- - - X O - - O O
- - - X - O - - -
- - - X - O - X -
- - - - - O - - -

Áp dụng quy tắc tính điểm mang lại kết quả như sau. x, o-đại diện cho nút giao thông không bị nhuộm màu được tính là đen, trắng và điểm của ai cả.

x x x X - O o o o
x x x X - O o o o
x x x X - O o o o
x x x X O o o O o
X X X O o O O o o
- - - X O - - O O
- - - X - O - - -
- - - X - O - X -
- - - - - O - - -

Theo sơ đồ, màu đen có 23 điểm, màu trắng có 29 điểm lãnh thổ. Vì vậy, chương trình của bạn nên in W+6cho bảng này.

Tôi hy vọng nó là đủ rõ ràng theo cách này.

Đầu vào và đầu ra

Đầu vào là một chuỗi chứa chính xác n ² trong những nhân vật X, O, -nơi n là không biết đến lúc biên dịch. Chương trình của bạn sẽ bỏ qua tất cả các ký tự khác trong luồng đầu vào. Hành vi không được xác định nếu không có số nguyên n sao cho số lượng XO-ký tự bằng . Bạn có thể giả sử rằng n nằm trong [0, 255] .

Chuỗi các ký tự sẽ được hiểu là một bảng gồm n hàng và cột. Đầu ra là giá trị tuyệt đối của chênh lệch của tổng số điểm trắng và đen trong biểu diễn thập phân. Nếu màu trắng có nhiều điểm hơn, nó có tiền tố bởi W+, nếu màu đen có nhiều điểm hơn thì nó có tiền tố B+. Trong trường hợp cả hai người chơi có số điểm bằng nhau, đầu ra là Jigo.

Đầu vào là để được đọc theo cách thực hiện được xác định. Đầu vào có thể không phải là một phần của mã nguồn.

Điều kiện chiến thắng

Đây là mã golf. Quy ước golf-code thông thường được áp dụng. Việc gửi với số lượng ký tự ít nhất trong nguồn của nó sẽ thắng. Chỉ các chương trình thực hiện đầy đủ các đặc điểm kỹ thuật có thể giành chiến thắng.

Các trường hợp thử nghiệm

Đầu vào:

- - - X - O - - -
- - - X - O - - -
- - - X - O - - -
- - - X O - - O -
X X X O - O O - -
- - - X O - - O O
- - - X - O - - -
- - - X - O - X -
- - - - - O - - -

Đầu ra: W+6

Đầu vào:

Xavier is insane -- says Oliver

Đầu ra: Jigo

Đầu vào:

Code-Golf

Đầu ra: Jigo

Đầu vào:

-XXXXXXX-XOOOOOOOXXO-OXXXOXXXOX--XOXXOOX
-
XOOXXOX--XOXXXOXXXO-OXXOOOOOOOX-XXXXXXX-

Đầu ra: B+21

Đầu vào:

- - X O O O O X X - - - - - - X O O -
- X X O X O X X O X X X X X X - X O -
- X O O X X X - O O O X O O X X X O -
- X O O O X X O O O O O O X X X O - -
- - X X O X - X X X X O O O O O O O -
- - X O O X X X - X X X O O O X X O -
- - X O - O X O X O O O O O X X X O -
- X O O - O O O X X X X X O O X O - -
- X X X O - - - O X O X X X O X O - -
X O O O O - - O - O O O O X X X O O -
X X O - - - O - - O O X X - - X X O O
X O O O - - O - O O X - - - - X O O X
- X X X O O X O O X X - - - - X X X X
X - X X X O X X O O X - - X X O X O O
X X O O X O X O X X - - - X O O O O -
X O - O X X X O X - - - - - X O - - -
O O - O X O O O O X X - X X X X O - -
O O - O O O X O X X - - X - X X O - -
- - O - - O X X X - - - - X O O O - -

Đầu ra: B+6

Nhiều thử nghiệm sẽ đến sớm.

Thực hiện tham khảo

Tôi đã tạo một triển khai tham chiếu được viết bằng ANSI C. Việc triển khai này đọc đầu vào từ đầu vào tiêu chuẩn và ghi đầu ra vào đầu ra tiêu chuẩn.

/* http://codegolf.stackexchange.com/q/6693/134
 * reference implementation
 * by user FUZxxl
 */

#include <stdio.h>
#include <stdlib.h>

#define MAXBOARD 256

/* bit 0x01: black colour
 * bit 0x02: white colour
 * bit 0x04: there is a stone on the intersection
 */

enum colour {
    UNCOLOURED    = 0x0,
    BLACK_REACHED = 0x1,
    WHITE_REACHED = 0x2,
    BOTH_REACHED  = 0x3,
    HAS_STONE     = 0x4,
    BLACK         = 0x5,
    WHITE         = 0x6
};

static enum colour board[MAXBOARD * MAXBOARD] = { 0 };

static int bsize = 0;

static void read_input(void);
static void fill_board(void);
static void show_score(void);

int main()
{
    read_input();
    fill_board();
    show_score();
    return EXIT_SUCCESS;
}

static void read_input(void)
{
    int n = 0;
    int invalue;

    while ((invalue = getchar()) != EOF) {
        switch (invalue) {
            case '-': board[n++] = UNCOLOURED; break;
            case 'X': board[n++] = BLACK; break;
            case 'O': board[n++] = WHITE; break;
        }
    }

    while (bsize * bsize < n) bsize++;

    /* your program may exhibit undefined behaviour if this is true */
    if (bsize * bsize != n) exit(EXIT_FAILURE);
}

static void fill_board(void)
{
    int i,j;
    int changes;
    enum colour here, top, bottom, left, right, accum;

    do {
        changes = 0;

        for (i = 0; i < bsize; ++i) {
            for (j = 0; j < bsize; ++j) {

                here   = board[i * bsize + j];
                if (here >= BOTH_REACHED) continue;

                top    = i == 0 ? UNCOLOURED : board[(i - 1) * bsize + j];
                left   = j == 0 ? UNCOLOURED : board[i * bsize + j - 1];
                bottom = i == bsize-1 ? UNCOLOURED : board[(i + 1) * bsize + j];
                right  = j == bsize-1 ? UNCOLOURED : board[i * bsize + j + 1];

                accum = here | top | bottom | left | right;
                accum &= ~HAS_STONE;

                changes |= board[i * bsize + j] != accum;

                board[i * bsize + j] = accum;

            }
        }

    } while (changes);
}

static void show_score(void) {
    int w = 0, b = 0, n;

    for (n = 0; n < bsize*bsize; ++n) switch (board[n] & ~HAS_STONE) {
        case BLACK_REACHED: ++b; break;
        case WHITE_REACHED: ++w; break;
    }

    if (b != w)
        printf("%s%i\n",b>w?"B+":"W+",abs(b-w));
    else
        printf("Jigo\n");
}

Có lẽ bạn có nghĩa là đầu ra cuối cùng được W+7?
dmckee

Không ... Làm thế nào để bạn đi đến kết luận này?
FUZxxl

Er ... Tôi cho rằng S+là một lỗi đánh máy (vì bạn sớm niêm yết có thể sản lượng là một trong hai W+, B+hoặc Jigo) và tôi nhìn vào bàn phím của tôi và thấy Slà gần W... Hay bạn sử dụng Dvorak?
dmckee

@dmckee Tôi cho rằng "S" xuất phát từ tiếng Đức "Schwarz" thay vì "Black".
Howard

Oh bạn nói đúng. Xin lỗi vì điều đó
FUZxxl

Câu trả lời:


2

GolfScript (105 byte)

{'-XO'?}/]-1-.{2*3%}%{.,:N),{.*N=}?/{{[{.2$+1={+.}*}*]}%zip}N*[]*.1--,\}2*-.{.0>'W+B+'2/=\abs}{;'Jigo'}if

Bản demo trực tuyến .

Lũ lụt thích nghi với câu trả lời trước đó của tôi .

Giải pháp lấp đầy một bản sao của bảng gốc bằng X và một bản khác với O. Do đó, các ô trống có thể tiếp cận được bằng cả hai màu được ghi cho cả hai, nhưng hủy bỏ trong phép trừ.


Đủ công bằng. Bạn có thể giành chiến thắng trong vòng này.
FUZxxl

6

C ( 438 434 413 382 364 336 322 298 294 292 290 ký tự)

#define I b[d*g+e
a;b[65536];c;d;e;f;g;main(){for(;d=getchar()+1;f++)b[f]=d-80?d-89?d-46&&
f--:5:6,g+=g*g<f;while(!c--)for(d=g;d--;)for(e=g;e--;)I]<3?a=3&(I]|!!d*I
-g]|!!e*I-1]|(d<g-1)*I+g]|(e<g-1)*I+1]),c&=I]==a,I]=a:0;while(f--)c+=b[f
]%2-b[f]/2%2;printf(c?"%c+%i":"Jigo",c>0?66:87,abs(c));}

Tất cả các dòng mới ngoại trừ cái đầu tiên được chèn để tăng tính dễ đọc. Một phiên bản bình luận và dễ đọc hơn một chút có thể được tìm thấy ở đây .

Câu trả lời này về cơ bản là giải pháp tham chiếu nhưng với tất cả những thứ vô dụng đó (chẳng hạn như các loại [ai cần một cái gì đó khác với intdù sao?] Và tuân thủ tiêu chuẩn [giá trị trả về của chính? Xin vui lòng!])

Sửa chữa và cải tiến

438 → 434

Bỏ việc khởi tạo rõ ràng các biến sau khi tôi tự thuyết phục rằng chúng được tự động khởi tạo 0theo tiêu chuẩn.

434 → 413

Xóa câu lệnh trường hợp: Nếu có thể tiếp cận giao lộ không được tô màu từ cả đen và trắng, chúng ta có thể tính nó là một điểm cho cả hai để đơn giản hóa chương trình. Chuyển các nhánh logic để tránh phủ định.

413 → 382

Chỉ định dđể getchar()+1lưu một cặp dấu ngoặc đơn. Theo giả định bđược khởi tạo thành số 0, sắp xếp lại các casecâu lệnh, loại bỏ tất cả các breakcâu lệnh. (a>b?c:0)dài hơn (a>b)*c. (d+1)*g+edài hơn d*g+e+g.

382 → 364

Cải thiện vòng lặp, không có dòng mới trong đầu ra, thói quen đầu ra ngắn hơn.

364 → 336

Đã thoát khỏi switchtuyên bố đó . (Cảm ơn, Howard!), Theo dõi sự khác biệt về điểm cho hai nhân vật. Phủ cđịnh cho một nhân vật. bốn ký tự trong mệnh đề lớn hoặc mệnh đề.

336 → 323

Thay thế &bằng cách %cho phép loại bỏ niềng răng cho bốn ký tự. Hợp nhất căn bậc hai với vòng lặp đầu vào cho chín ký tự (vâng!), Đã xóa một ký tự if.

323 → 298

Giới thiệu macro Hđể thay thế các cấu trúc thường xuyên xảy ra và cồng kềnh b[d*g+e].

298 → 294

Thay đổi a&=~4thành a&=3vì chúng tôi chỉ quan sát ba byte thấp nhất a. Cũng thay đổi để thân vòng lặp từ ((a=I])<3)?a|=...để I]<3?a=I]|...đó là hai nhân vật ngắn hơn. Ngoài ra, giới thiệu hthay vì sử dụng lại c, đó là một ký tự ngắn hơn.

294 → 292

Loại bỏ hbiến. Nếu chúng tôi thử nghiệm cvới !c--thay !c++, cbằng 0 ở phần cuối của vòng lặp lũ điền và do đó có thể được sử dụng cho mục đích này hđã được sử dụng trước đó (ví dụ: điểm số giữ).

292 → 290

Thay thế các cấu trúc d-46?f--:0với d-46&&f--đó là ngắn hơn bởi một nhân vật và kết hợp hai công việc để atrong các vòng trong.


1
Bạn có thể thay thế câu lệnh chuyển đổi bằng một cái gì đó như {b[f]=d-80?d-89?d-46?f--:0:5:6;f++;}để lưu một vài ký tự.
Howard

@Howard: Vâng. Điều đó đã làm việc rất tốt! Cảm ơn bạn
FUZxxl

"Để tăng tính dễ đọc" - như thể.
tomsmeding

@tomsmeding Vâng, cuộn một dòng ít dễ đọc hơn nhiều. Ngoài ra, một phiên bản nhận xét được liên kết đến.
FUZxxl

@FUZxxl Điều đó có nghĩa là đùa. :) Ngoài ra, bạn đúng khi nói nó tốt hơn trên 1 dòng.
tomsmeding

6

J ( 140 136 131 129 119 117 116 ký tự)

Sau khi tăng cường các kỹ năng J của mình, cuối cùng tôi cũng có thể cung cấp một bài nộp trong J. Mặc dù vậy, nó hơi lâu một chút.

exit echo>(*{'Jigo';('B+',":);'W+',":@|)+/,-/1 2=/(]OR(0=[)*[:OR((,.|.)0,i:1)|.!.0])^:_~($~,~@%:@#)3-.~'-XO'i:1!:1]3

Thuật toán được thực hiện bởi đệ trình này rất giống với triển khai tham chiếu nhưng khác nhau về cách xử lý các trường chiếm dụng.

Đây là giải pháp được chia thành nhiều phần để dễ hiểu hơn. Giải pháp chơi gôn hơi khác so với giải pháp đó, nhưng sự khác biệt không quá lớn.

input =. 3 -.~ '-XO' i: 1!:1 ] 3
board =. ($~ ,~@%:@#) input
NB. shift up, down, left, right
rotm =. (,. |.) 0 , i: 1
fill =. ] OR (0 = [) * [: OR rotm |.!.0 ]
filledboard =. fill^:_~ board
score =. +/ , -/ 1 2 =/ filledboard
echo > (* { 'Jigo' ; ('B+' , ":) ; ('W+', ":@|)) score
exit 0

5

GolfScript, 190 ký tự

{"XO-"?)},:v,.),\{\.*=}+,~:s.*:`0\,{s%!\2*+}/:r;88{0v@{=\2*+}+/}:%~79%1${{:<.r|r^2*|<2/r|r^|<2s?:h/|<h*|1$|1$^2`?(&}`*}:a~@@a\;.2$|2${^2*)2base{+}*}:m~@2$|@m-.{"BW"1/1$0>="+"@abs}{;"Jigo"}if

Kịch bản trở nên dài hơn nhiều so với tôi nghĩ lúc đầu. Vượt qua bất kỳ đầu vào nào trên STDIN và đầu ra sau đó sẽ được in khi chương trình kết thúc.


2

Hồng ngọc (314)

có thể được thực hiện ngắn hơn với một số thời gian hơn:

q={?-=>0,?X=>5,?O=>6};b=[];$<.chars{|c|(t=q[c])&&b<<t}
z=Math.sqrt b.size
loop{c=b.each_with_index.map{|h,i|
next h if h>2
x=i%z
y=i/z
u=y<1?0:b[i-z]
l=x<1?0:b[i-1]
d=y>z-2?0:b[i+z]
r=x>z-2?0:b[i+1]
~4&(h|u|d|l|r)}
break if c==b
b=c}
b.map!{|h|h&~4}
s=b.count(1)-b.count(2)
puts s==0?"Jigo":s>0?"B+#{s}":"W+#{-s}"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.