체스 타일 채색을위한 우아한 솔루션


19

Java로 작성한 체스 게임을 다시 개발하고 있으며 번호가 매겨진 체스 판에 체스 타일을 색칠하는 우아한 알고리즘이 있는지 궁금합니다.

현재 내 솔루션은 if else 문을 사용하여 타일이 짝수 또는 홀수 행인지 여부를 결정하고 그에 따라 밝거나 어두운 사각형이어야합니다.


왜 그렇게 기본적인 것을하기 위해 더 우아한 알고리즘이 필요한가? 그냥 호기심이나 ...?
— ssb

5
솔직히 나는 궁금합니다.
— Amir Afghani

답변:


40

당신이 가지고 주어진 내가 생각할 수있는 가장 우아한 방법, row및 column, 인덱스는 다음과 같다 :

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

또는 반대로 :

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

기본적으로 체스 판의 타일은 열과 행이 서로 홀수 또는 짝수 인 곳에서는 가볍고 그렇지 않으면 어둡습니다.


4
아주 좋은 해결책. 귀하의 의견은 오해의 소지가 있지만 "체스 판의 타일은 열과 행이 모두 같은 곳이면 밝습니다." 사실이 아닙니다 .. 행이 3이고 열이 5 (둘 다 고르지 않음 ) 3 % 2 == 1이고 5 % 2 == 1.. 둘 다 고르지 않지만 "빛"으로 표시됩니다. 해결책이 잘못되었다고 말하지 않고 (패턴을 번갈아 가며 좋으므로) 주석 / 설명이 틀린 것 같습니다.
— bummzack

@bummzack을 찾아 주셔서 감사합니다. 답변을 업데이트했습니다.
— kevintodisco

좌표가 동일한 패리티를 갖는 한 타일이 가볍다 고 말하는 것이 좋습니다.
— ver

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

행과 열 인덱스를 함께 XOR하고 가장 중요하지 않은 비트를 봅니다. 행 또는 열 인덱스를 하나씩 변경하면 결과가 반전되어 검사기 패턴이 생성됩니다.


5
^괜찮지 만 +똑같이 잘 작동합니다. :)
— Chris Burt-Brown 10

2
그 문제에 -대해서도 마찬가지입니다. :)
— Trevor Powell

2
비트 작업 ftw :)
— Mike Cluck

3
이 "읽을 수"있는 그대로 (I는 비트 연산 알고, 그것의 유지 보수를 의미하지 않는다), 다른 사람을 선호
— Matsemann

22

또 다른 제안은 매우 간단합니다.

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

행과 열을 추가하면 왼쪽 상단 타일에서 수평 및 수직 단계 수가 줄어 듭니다.

단계 수조차도 밝은 색상을 제공합니다.
홀수 단계는 어두운 색을냅니다.


기본적으로 Nathan의 답변과 동일하게 다르게 작성되었습니다.
— API-Beast

@ Mr.Beast : 후자가 특별히 최적화되지 않는 한보다 & 1효율적 % 2입니다. 그러나 일반적으로 동의합니다.
— LarsH

1
@LarsH 컴파일러는 이런 종류의 것들을 처리합니다 (적어도 최소한)
— neeKo

@LarsH 나는 속도가 아니라 가독성을 목표로했다. 그러나 그다지 많지 않습니다. 두 번의 속도 차이가 64 번만 호출된다는 것을 알 때 둘 사이의 속도 차이를 "많이"고려할 수 있는지 확실하지 않으며 최신 컴파일러가 어쨌든 동일한 바이너리를 생성한다고 생각하고 싶습니다.
— Chris Burt-Brown

@Chris : % 작업의 효율성에 대해 이야기하고 있었는데, 호출 횟수에 영향을받지 않습니다. 그러나 나는 프로그램 속도에 실질적인 차이를 만들지 않을 것이며, 잠재적 인 속도 개선에 비해 가독성의 중요성에 동의한다.
— LarsH

4

이것은 우리의 제곱이 [0..63] 범위에서 번호가 매겨 졌다고 가정합니다.

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

그것이 왜 작동하는지 알아내는 것은 반 재미입니다. :)


재미있는 접근법. 그러나 부울로 가져 오기 위해 반환 값에 무언가를 할 필요는 없습니다. 예를 들어 return (i>>3 ^ i) & 1 != 0? Java에서 정수를 부울로 암시 적으로 변환 할 수 있습니까?
— LarsH

아, 맞아요. "자바"비트를 똑바로 읽고 C ++에 대한 해답을 썼습니다. 내 답변 수정
— Trevor Powell

이것은 분명히 최고의 보드입니다.
— Marcks Thomas

1
이 접근법은 Perl이 저에게 호소하는 것과 같은 방식으로 저에게 호소합니다. 간결한 이해할 수없는 이런 종류의 쓰기는 항상 재미 있습니다. 디버깅 재미가 적습니다.
— Trevor Powell

2
  1. 타일 ​​번호를 매기십시오. row * 8 + column 또는 이와 유사한 것을 계산하여이 정보를 얻을 수 있습니다.

  2. 그리드 번호의 계수 16을 가져옵니다. (타일이 반복되기 전에 16 개의 위치가 있습니다.)

  3. 짝수 또는 홀수인지에 따라 타일의 색상을 지정하십시오. 결과가 7보다 큰 경우 타일 색상을 뒤집습니다.

0부터 시작하는 인덱스 코드 :

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

왜 두 번째 줄을 골라 내나요? 이것은 8 행 모두에 대해 작동합니다
— Amir Afghani

1
귀하의 질문을 이해하지 못합니다. modulus 16동작은 두 개의 행에 문제를 감소시킨다. 두 번째 행은 첫 번째 행과 다른 패턴을 따릅니다. if중 하나가 아니라 두 번째 행의 짝수 타일 XOR 인 경우 문은 true로 평가합니다. 둘 다 참이면 거짓으로 평가됩니다. XOR 연산자를 검토하십시오. msdn.microsoft.com/en-us/library/zkacc7k1.aspx
— Jim

1
IsSecondRow정말 이름이 있어야합니다 IsEvenRow. 낮은 행의 비트를 얻는 것은 다소 복잡한 방법입니다. 먼저 행 3의 비트를 오른쪽으로 이동 한 다음 행의 LSB를 제외한 모든 행을 버린 다음 4 번째 비트의 셀 번호가 설정되어 있는지 확인하십시오.
— MSalters

내가 참조. 답변 +1
— Amir Afghani

왜 우아함이 항상 최고의 솔루션이 아닌지에 대한 좋은 예일 것입니다. ;)
— Jim

0

이 방법은 체스 보드처럼 단순한 것에 실제로는 필요하지 않지만 뷰와 관련된 것을 렌더링하는 우아한 방법을 생각할 때 가능한 한 렌더링 된 뷰를 변경하는 것이 가능하도록 만들고 싶습니다. 예를 들어, 각 행이 아니라 각 행에서 흑백을 교대로하기로 결정했다고 가정하십시오. 지금까지 답변에 사용 된 원 라이너는 다시 작성해야합니다.

내가 할 수있는 한 멀리 가서 체스 보드의 패턴을 가능한 한 쉽게 다시 디자인하려면 다음과 같이하십시오.

1) 체스 보드의 각 사각형이 어떤 색인지 나타내는 파일을 만들 것입니다.

예를 들어, chess_board_pattern.config다음과 같은 파일 을 만들 수 있습니다 .

bwbwbwbw
wbwbwbwb
bwbwbwbw
wbwbwbwb
bwbwbwbw
wbwbwbwb
bwbwbwbw
wbwbwbwb

2) 나는이 파일을 읽을 수있는 클래스 / 구성 요소 / 무엇이든 쓰고 보드 패턴을 나타내는 일종의 객체를 만들 것입니다.

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) 그런 다음 실제로 보드를 그리는 함수에서 해당 클래스를 사용합니다.

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]);
    }
}

다시 말하지만 이것은 체스 보드에 필요한 것보다 훨씬 어렵습니다. 그러나 일반적으로 복잡한 프로젝트를 수행 할 때는 나중에 변경하기 어려운 코드를 작성하는 대신 이와 같은 일반화 된 솔루션을 사용하는 것이 가장 좋습니다.


8
이것을 dailywtf.com에 게시해야합니다 . :)
— avakar December

11
충분히 기업화되지 않고 더 많은 XML이 필요합니다.
— Maximus Minimus

3
안녕 케빈 당신은 쓴 The one-liners used in answers so far would have to be re-written.뿐만 아니라, it's best to come up with generalized solutions like this instead of writing code that's difficult to change later.하지만 당신은이 코드는 해체하고 한 줄보다 재 작성 훨씬 어렵 것을 이해해야합니다. 우아하지 않거나 그렇게하는 것이 좋지 않기 때문에 나는 당신에게 하향 투표를했습니다.
— Chris Burt-Brown

1
+1-우아함이 간결한 것이 아닙니다. 보드 구성을 변경할 수있는 것이 요구 사항 중 하나라면 이것이 좋은 방법입니다. 일부 퍼즐 프로그램에서 비슷한 작업을 수행했습니다. 체스 프로그램 이이 요구 사항을 갖기를 기대하지 않습니다. 그리고 일반화 된 솔루션이 항상 최고라는 데 동의하지 않습니다. LALR 파서와 OpenGL 인터프리터를 구현하지 않고 Hello World를 작성할 수 없도록 일반화에는 끝이 없습니다. 열쇠는 언제 야 그니인지 아는 것입니다.
— LarsH

2
나는이 답변을 좋아한다. 시간 단위로 청구되는 경우 수익을 극대화하는 가장 우아한 방법입니다!
— Panda Pajama
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.