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


19

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

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


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

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

답변:


40

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

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.