Giải pháp trang nhã cho màu cờ vua


19

Tôi đang phát triển lại một trò chơi cờ vua mà tôi đã viết bằng Java và đang tự hỏi liệu có một thuật toán tao nhã để tô màu các ô cờ trên một bàn cờ được đánh số không.

Ngay bây giờ giải pháp của tôi sử dụng nếu các câu lệnh khác để xác định xem gạch nằm trên một hàng chẵn hay lẻ, và dựa vào đó, nếu nó là một hình vuông sáng hoặc tối.


Tại sao bạn cần một thuật toán thanh lịch hơn để làm một cái gì đó rất cơ bản? Chỉ tò mò hay ...?
ssb

5
Thú thật tôi chỉ tò mò thôi.
Amir Afghani

Câu trả lời:


40

Cách thanh lịch nhất mà tôi có thể nghĩ ra, cho rằng bạn có rowcolumnchỉ số, là:

bool isLight = (row % 2) == (column % 2);

hoặc ngược lại:

bool isDark = (row % 2) != (column % 2);

Về cơ bản, một ô trên bàn cờ là ánh sáng ở bất cứ nơi nào cả cột và hàng đều lẻ hoặc chẵn, và tối khác.


4
Giải pháp rất hay. Mặc dù nhận xét của bạn là sai lệch: "một ô trên bàn cờ là ánh sáng ở bất cứ nơi nào cả cột và hàng đều nhau". Điều đó không đúng .. giả sử hàng là 3 và cột là 5 (cả hai đều không đồng đều ) 3 % 2 == 15 % 2 == 1.. vì vậy cả hai đều không đồng đều nhưng sẽ có màu "sáng". Không nói rằng giải pháp của bạn là sai (nó tốt, vì nó sẽ thay thế mô hình) nhưng nhận xét / giải thích của bạn có vẻ sai.
bummzack

Rất tiếc, cảm ơn vì đã phát hiện ra rằng @bummzack. Cập nhật câu trả lời.
kevintodisco

Một cách hay để đặt nó có thể nói rằng một ô vuông nhẹ miễn là tọa độ của nó có cùng một chẵn lẻ.
ver

34
bool isLight = ((row ^ column) & 1) == 0;

XOR cùng các chỉ số hàng và cột và xem xét bit có ý nghĩa nhỏ nhất. Thay đổi chỉ số hàng hoặc cột theo một sẽ đảo ngược kết quả, do đó nó tạo ra một mẫu kiểm tra.


5
^là tốt, nhưng +hoạt động tốt như nhau. :)
Chris Burt-Brown

2
Đối với vấn đề đó, -công trình, quá. :)
Trevor Powell

2
Hoạt động của bit ftw :)
Mike Cluck

3
thích những cái khác, vì đây là "không thể đọc được" (tôi biết các hoạt động bit, không có nghĩa là nó có thể duy trì được)
Matsemann

22

Một đề nghị khác, rất đơn giản:

isLight = (row + column) % 2 == 0;

Thêm hàng và cột sẽ cho số bước ngang và dọc cách xa ô trên cùng bên trái.

Số bước chẵn cho màu sắc nhẹ.
Số lẻ của các bước cho màu tối.


Về cơ bản giống như câu trả lời của Nathan chỉ được viết khác nhau.
API-Beast

@ Mr.Beast: & 1sẽ hiệu quả hơn rất nhiều % 2, trừ khi cái sau được tối ưu hóa đặc biệt. Nhưng nói chung tôi đồng ý.
LarsH

1
@LarsH Trình biên dịch sẽ xử lý những thứ đó (hoặc ít nhất là vậy)
neeKo

@LarsH Tôi đã nhắm đến khả năng đọc, không phải tốc độ. Nhưng không có nhiều trong đó. Tôi không chắc rằng sự khác biệt về tốc độ giữa hai người có thể được coi là "rất nhiều" khi chúng ta biết rằng nó sẽ chỉ được gọi là 64 lần và tôi muốn nghĩ rằng một trình biên dịch hiện đại sẽ tạo ra các nhị phân giống hệt nhau.
Chris Burt-Brown

@Chris: Tôi đã nói về hiệu quả của hoạt động%, không bị ảnh hưởng bởi số lần nó được gọi. Nhưng tôi đồng ý, nó không có khả năng tạo ra sự khác biệt thực tế về tốc độ của chương trình và tôi cũng đồng ý về tầm quan trọng của khả năng đọc liên quan đến các cải tiến tốc độ tiềm năng.
LarsH

4

Điều này giả định rằng hình vuông của chúng tôi được đánh số trong phạm vi [0..63].

bool IsLight(int i)
{
    return 0!=(i>>3^i)&1;
}

Tìm hiểu tại sao nó hoạt động là một nửa niềm vui. :)


Cách tiếp cận thú vị. Nhưng bạn không phải làm gì đó với giá trị trả về để đưa nó vào bool, vd return (i>>3 ^ i) & 1 != 0? Java có cho phép chuyển đổi ngầm định số nguyên sang boolean không?
LarsH

À, bạn nói đúng; Tôi đọc thẳng qua bit "Java" và viết câu trả lời khi nghĩ về C ++. Chỉnh sửa câu trả lời của tôi.
Trevor Powell

Đây rõ ràng là bảng tốt nhất.
Marcks Thomas

1
Cách tiếp cận này hấp dẫn tôi giống như cách mà Perl hấp dẫn tôi. Loại khó hiểu ngắn gọn này luôn luôn vui vẻ để viết. Ít vui để gỡ lỗi.
Trevor Powell

2
  1. Đánh số gạch. Bạn có thể lấy thông tin này bằng cách tính cột * 8 + hoặc một cái gì đó tương tự.

  2. Lấy mô đun 16 của số lưới. (Có 16 vị trí trước khi gạch lặp lại.)

  3. Tô màu gạch dựa trên nếu nó có số chẵn hoặc số lẻ. Lật màu gạch nếu kết quả lớn hơn 7.

Mã cho các chỉ số dựa trên zero:

int cellNum = (row*8+column) % 16;
bool isSecondRow = cellNum > 7;
if(cellNum % 2 == 0 ^ isSecondRow){ //XOR operator
    setColor(Color.White);
}else{
    setColor(Color.Charcoal);
}

Tại sao bạn độc thân ra hàng thứ hai? Điều này sẽ hoạt động cho tất cả 8 hàng
Amir Afghani

1
Tôi không hiểu câu hỏi của bạn. Các modulus 16hoạt động giảm vấn đề xuống hai hàng. Hàng thứ hai theo một mẫu khác với hàng đầu tiên. Câu iflệnh chỉ đánh giá là đúng nếu nó là XOR số chẵn không nằm trong hàng thứ hai. Nếu cả hai đều đúng, nó đánh giá là sai. Xem lại toán tử XOR: msdn.microsoft.com/en-us/l Library / zkacc7k1.aspx
Jim

1
IsSecondRowthực sự nên đã được đặt tên IsEvenRow. Đây là một cách khá phức tạp để có được bit thấp của hàng: đầu tiên chuyển các bit của vị trí hàng 3 sang phải, sau đó loại bỏ tất cả trừ LSB của hàng, sau đó kiểm tra xem bit thứ 4 của ô có được đặt không.
MSalters

Tôi hiểu rồi. +1 cho câu trả lời.
Amir Afghani

Có lẽ một ví dụ tốt về lý do tại sao sự thanh lịch không phải luôn luôn là giải pháp tốt nhất. ;)
Jim

0

Mặc dù cách tiếp cận này không thực sự cần thiết cho một thứ đơn giản như bàn cờ vua, nhưng khi tôi nghĩ ra một cách thanh lịch để thể hiện một cái gì đó liên quan đến chế độ xem, tôi muốn làm cho nó dễ dàng nhất có thể để thay đổi chế độ xem được hiển thị nhất có thể. Ví dụ: giả sử bạn quyết định bạn muốn xen kẽ đen trắng trên mỗi hàng, nhưng không phải mỗi cột. Các lớp lót được sử dụng trong các câu trả lời cho đến nay sẽ phải được viết lại.

Nếu tôi đã đi xa hết mức có thể với điều này và làm cho nó dễ dàng thiết kế lại mẫu trên bàn cờ càng tốt, đây là những gì tôi sẽ làm:

1) Tôi sẽ tạo một tập tin cho biết mỗi ô vuông màu gì trong bàn cờ.

Ví dụ: tôi có thể tạo một tệp chess_board_pattern.configtrông giống như thế này:

bwbwbwbw
wbwbwbwb
bwbwbwbw
wbwbwbwb
bwbwbwbw
wbwbwbwb
bwbwbwbw
wbwbwbwb

2) Tôi sẽ viết một lớp / thành phần / bất cứ thứ gì có thể đọc tệp này và tạo một số loại đối tượng đại diện cho mẫu bảng:

public class BoardPattern {
    private Color[][] pattern;

    public BoardPattern(File patternFile)
    {
        pattern = new Color[8][8];
        //Parse the file and fill in the values of pattern
    }

    public Color[][] getPattern {
        return pattern;
    }
}

3) Sau đó tôi sẽ sử dụng lớp đó trong hàm thực sự vẽ bảng.

File patternFile = new File("chess_board_pattern.ini");
Color[][] pattern = new BoardPattern(patternFile).getPattern();
ChessBoardDrawable chessBoard = new ChessBoardDrawable();

for(int row = 0; row < 8; row++) {
    for(int column; column < 8; column++) {
        chessBoard.drawSquare(row, column, Color[row][column]);
    }
}

Một lần nữa, điều này khó hơn rất nhiều so với cần thiết cho một bàn cờ. Tuy nhiên, tôi nghĩ rằng nói chung, khi làm việc với các dự án phức tạp hơn, tốt nhất là đưa ra các giải pháp tổng quát như thế này thay vì viết mã khó thay đổi sau này.


8
Bạn nên đăng bài này lên thed Dailywtf.com . :)
avakar

11
Không đủ enterprisey, cần thêm XML.
Maximus Minimus

3
Xin chào Kevin. Bạn đã viết The one-liners used in answers so far would have to be re-written.nhưng cũng it's best to come up with generalized solutions like this instead of writing code that's difficult to change later.phải Nhưng bạn phải hiểu rằng mã này khó xé và viết lại hơn nhiều so với một dòng. Vì vậy, tôi đã đánh giá thấp bạn bởi vì nó không thanh lịch hoặc không nên làm điều này.
Chris Burt-Brown

1
+1 - Sự thanh lịch không chỉ trong sự ngắn gọn. Nếu có thể thay đổi cấu hình bảng là một trong những yêu cầu, đây là một cách tốt để đi. Tôi đã làm những điều tương tự trong một số chương trình câu đố. Tôi sẽ không mong đợi một chương trình cờ vua có yêu cầu này mặc dù. Và tôi sẽ không đồng ý rằng các giải pháp tổng quát luôn tốt nhất. KHÔNG CÓ KẾT THÚC để khái quát hóa có thể được thực hiện, như vậy bạn không thể viết Hello World mà không thực hiện trình phân tích cú pháp LALR và trình thông dịch OpenGL. Điều quan trọng là biết khi nào YAGNI.
LarsH

2
Tôi thích câu trả lời này. Đó là cách thanh lịch nhất để tối đa hóa lợi nhuận của bạn nếu bạn được thanh toán theo giờ!
Panda Pyjama
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.