3 차원 체스


26

사람들의 당혹스러운 결정을 방어하기 위해 사람들은 종종 그 사람이 모든 사람의 머리 위로 가서“3 차원 체스”를하고 있다고 말합니다. 이제 3 차원 체스를 즐길 수 있습니다!

규칙

3D Chess 에는 많은 변형 이 있지만이 도전을 위해 나는 내 자신을 구성했습니다. 내 버전은 정사각형 대신 큐브 안에 조각이 있고 추가 차원의 움직임이 있다는 점을 제외하고는 일반 체스와 같습니다. 이 도전을 간단하게하기 위해 캐스터 링없습니다 .

조각 운동

(나침반 방향은 표준 체스 판에서 발생하는 움직임을 말하고 위와 아래는 3D 체스 판에서 수직으로 움직이는 것을 나타냅니다).

  • -주어진 차례에 갈 수있는 26 개의 사각형이 있습니다 : N, NE, E, SE, S, SW, W, NW; 위, 아래, 위 / 아래 + 나침반 방향 중 하나입니다.
  • 여왕 -왕과 같은 방향으로 움직일 수 있지만 원하는 방향으로 움직일 수 있습니다.
  • 루크 -6 방향으로 이동할 수 있습니다 : N, E, S, W, 위, 아래,
  • 주교 -8 개의 삼각 이동 방향이 있습니다 : NE + 위 / 아래, SE + 위 / 아래, SW + 위 / 아래, NW + 위 / 아래
  • 기사 -한 축씩 2 칸 이동 한 다음 다른 축에서는 1 칸 이동합니다. 일반 체스와 마찬가지로 기사는 다른 조각을 뛰어 넘을 수있는 유일한 조각입니다.

피스 테스터

이 스 니펫을 사용하여 3D 보드에서 다른 조각이 어떻게 움직이는 지 확인하십시오 ( : *Test조각과의 절대 거리를 기준으로 사각형이 유효한 이동인지 확인하는 빠른 방법은 JS 의 기능을 확인하십시오 ).

const color = "Black";
const pieces = ["N","B","R","Q","K"];
const urls = ["https://image.ibb.co/gyS9Cx/Black_N.png","https://image.ibb.co/dknnzc/Black_B.png","https://image.ibb.co/kb3hXx/Black_R.png","https://image.ibb.co/hGO5kH/Black_Q.png","https://image.ibb.co/jApd5H/Black_K.png"];
var dragPiece;
var size = 3;
var index = 0;
function start() {
Array.prototype.add = function(a) {return [this[0]+a[0],this[1]+a[1],this[2]+a[2]]};

document.getElementById("n").onchange=function() {
	size = parseInt(this.value);
	var s = document.getElementsByClassName("selected");
	var pos;
	if(s.length > 0) {
		pos = s[0].pos;
	}
	document.body.removeChild(document.body.firstChild);
	createBoards();
	if(pos != null && valid(...pos)) {
	cellAt(...pos).click();
	}
};
createBoards();
}

function createBoards() {
var boards = document.createElement("div");
boards.style.counterReset = "board-count "+(size+1);
boards.name=size;
for(var x = 0;x<size;x++) {
var t = document.createElement("table");
for(var i = 0;i<size;i++) {
  var row = document.createElement("tr");
  row.className="row";
  for(var j = 0;j<size;j++) {
  	var cell = document.createElement("td");
    cell.className = (size+i+j)%2 == 1 ? "black" : "white";
    var im = document.createElement("img");
    im.draggable = true;
    im.ondragstart = function(e) {dragPiece = this;e.dataTransfer.setData("piece",this.parentElement.name);
    this.parentElement.classList.add("start");
    this.classList.add("dragged");
    };
    im.ondragend = function(e) {this.parentElement.classList.remove("start");this.classList.remove("dragged");};
    im.hidden = true;
    cell.appendChild(im);
    cell.pos = [j,i,x];
    cell.ondragover = function(e) {e.preventDefault();};
    cell.ondragenter = function(e) {this.classList.add("drag");};
    cell.ondragleave = function(e) {this.classList.remove("drag");};
    cell.ondrop = function(e) { e.preventDefault();this.classList.remove("drag");
    if(this != dragPiece.parentElement && this.firstChild.hidden ){
    dragPiece.hidden=true;
    setPiece(this,e.dataTransfer.getData("piece"));
    }
    
    };
    cell.onclick = function() {
    if(this.firstChild.hidden == false && this.classList.contains("selected")) {
		index++;
    	if(index == pieces.length) index = 0;
    }
     	setPiece(this,pieces[index]);
    };
  
    
    row.appendChild(cell);
  }
  t.appendChild(row);
  }
  boards.appendChild(t);
  }
  document.body.insertBefore(boards,document.body.firstChild);
}



function clearHighlighted() {
	var sel =  document.getElementsByClassName("highlighted");
     while(sel.length > 0) {
     	sel[0].classList.remove("highlighted");
     }
}

function setPiece(cell,piece) {
var s=document.getElementsByClassName("selected");
if(s.length > 0){ s[0].firstChild.hidden=true;s[0].classList.remove("selected");}
cell.classList.add("selected");
cell.firstChild.hidden = false;
cell.name = piece;
     	cell.firstChild.src = urls[index];
     clearHighlighted();
     	showMoves(cell,piece);
}

function showMoves(cell,piece) {
	if(piece=="K") selector(cell,kingTest)
	else if(piece=="N") selector(cell,knightTest);
	else if(piece=="Q") selector(cell,queenTest);
	else if(piece=="R") selector(cell,rookTest);
	else if(piece=="B") selector(cell,bishopTest);
}

function cellAt(col,row,board) {
	return document.body.firstChild.children[board].children[row].children[col];
}

function valid(col,row,board) {
	return 0<=col && col<size && 0<=row && row<size && 0<=board && board<size;
}

function select(cell) {
if(cell != null && cell.firstChild.hidden) cell.classList.add("highlighted");
}



function rookTest(dist) {
	var d = [].concat(dist).sort();
	return d[0] == 0 && d[1] == 0;
}

function knightTest(dist) {
	var d = [].concat(dist).sort();
	return d[0] == 0 && d[1] == 1 && d[2] == 2;
}

function kingTest(dist) {
	return dist[0] <= 1 && dist[1] <= 1 && dist[2] <= 1;
}

function bishopTest(dist) {
	return dist[0]==dist[1] && dist[1]==dist[2];
}

function queenTest(dist) {
	var d = [].concat(dist).sort();
	return rookTest(dist) || bishopTest(dist) || (d[0]==0 && d[1]==d[2]) ;
}

function dist(cell,x,y,z) {
	return [Math.abs(cell.pos[0]-x),Math.abs(cell.pos[1]-y),Math.abs(cell.pos[2]-z)];
}

function selector(cell,test) {
	for(var i = 0;i<size;i++) {
		for(var j = 0;j<size;j++) {
			for(var k = 0;k<size;k++) {
			if(test(dist(cell,k,j,i))) {
				var c = cellAt(k,j,i);
				if(c != cell) select(c);
			}
			}
			}
			}
	
}
table
{
	padding: 10px;
  display:inline-block;
}

table:after
{
  counter-increment: board-count -1;
  content: "("counter(board-count,upper-roman)")";
  float:right;
}

td
{
  width:28px;
  height:28px;
  border: 1px solid;
  cursor: pointer;
}

.black
{
  background-color: rgba(127,127,127,0.6);
}

.white
{
  background-color: white;
}


.start {
background-color: rgba(0,204,0,0.6);
}

.highlighted {
background-color: rgba(0,255,0,0.6);
}

.drag
{
background-color: rgba(0,204,255,0.6);
}


.selected {
background-color: green;
cursor: grab;
}

.selected img
{
  display:block;
}

.dragged {
  cursor: grabbing;
}
<body data-size=3 onload="start()"
<label for="n">Size: </label><select id="n">
<option>2</option>
<option selected>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
<option>9</option>
<option>10</option>
</select>
<div>Click or drag to place the piece. Click on the piece to change its type.</div>
</body>

도전

n x n x n 보드가 주어지면 백인 왕이 장군인지 확인하십시오.

입력

  • (선택 사항) n ≥ 2-보드 크기
  • 게임 보드
    • 1d-2d 또는 3d- 배열의 형태이거나 다른 유사한 형식 일 수 있습니다. 표기법은 간단한 형식 일 수 있습니다. 예를 들어, 빈 큐브의 경우 KQRBN (흰색) 및 kqrbn (검은 색)이 #입니다. 또는 다른 값에 숫자를 사용하십시오.
    • 3D 체스 보드는 여러 개의 보드가 서로 쌓여 있고 위에서 아래로 나열되는 것으로 생각하십시오. 그런 다음 각 개별 보드는 왼쪽에서 오른쪽으로, 뒤로 (전면에서 검은 색에서 흰색으로) 표시됩니다.
    • 이 2x2x2 사례가 3D 배열로 주어진다고 상상해보십시오.
 [
[[bq] [##]]
[[bn] [KQ]]
]

"상단"보드 : 여기에 이미지 설명을 입력하십시오"하단"보드 :여기에 이미지 설명을 입력하십시오

산출

  • 부울 (거짓 / 거짓 값)-흰색 왕이 장군 인 경우 true, 그렇지 않으면 false

장군

다음 왕은 블랙 피스가 블랙의 다음 턴에서 블랙 피스를 포획하겠다고 위협 하는지 점검 합니다. 점검에서 벗어나기 위해서는 White가 그의 왕을 안전으로 옮기거나 다른 조각으로 방어하거나 위협하는 조각을 포착해야합니다. White가 점검에서 벗어날 수 없다면, White king은 checkmate에 있습니다. White가 체크 되지 않았지만 체크하지 않고 움직일 수 없다면, 그것은 교착 상태 가 아니며, 체크 메이트가 아닙니다.

사양

  • 당신은 흑 왕이 백인 왕을 "체크"하려고하는 보드 나 두 왕이 모두 점검하는 보드를받을 수 없습니다 (불가능한 시나리오).

테스트 사례

  1. n = 3, [###,n##,#rr],[#b#,###,###],[###,###,bRK]

    여기에 이미지 설명을 입력하십시오(III) 여기에 이미지 설명을 입력하십시오(II) 여기에 이미지 설명을 입력하십시오(I)

    출력 : true

    설명 : 왕이 최상층의 사기꾼에게 수표를 받고 있습니다. 흰 사기꾼은 공격을 막거나 위협하는 사기꾼을 붙잡을 수 없으므로 왕은 길을 벗어나려고 노력해야합니다. 왕의 이동 옵션을 고려해 봅시다.

    1. c2 (I)-b3 (II)에서 감독에 의해 보호
    2. b2 (I)-기사 a2 (III)에 의해 보호
    3. c1 (II)-c1 (III)에서 루크에 의해 보호
    4. b1 (II)-b1 (III)에서 루크에 의해 보호
    5. c2 (II)-기사 a2 (III)에 의해 보호
    6. b2 (II)-감독 a1 (I)에 의해 감시

왕은 수표를 피할 수 없기 때문에 수표입니다!

  1. n = 3, [b#b,###,###],[###,###,RNR],[#q#,###,#K#]

    여기에 이미지 설명을 입력하십시오(III) 여기에 이미지 설명을 입력하십시오(II) 여기에 이미지 설명을 입력하십시오(I)

    출력 : false 설명 : 왕이 여왕으로부터 수표를 받고 있으며 탈출하거나 막을 움직임이 없습니다. 그러나 기사는 여왕을 붙잡을 수 있습니다.

  2. n = 3, [#q#,#b#,###],[n##,###,###],[#k#,###,#KB]

    여기에 이미지 설명을 입력하십시오(III) 여기에 이미지 설명을 입력하십시오(II) 여기에 이미지 설명을 입력하십시오(I)

출력 : false 설명 : 화이트는 위협하는 여왕을 사로 잡거나 왕을 안전으로 옮기는 방법이 없습니다. 그러나 그의 감독을 b2 (II)로 옮기면 White는 여왕의 위협을 차단할 수 있습니다.

  1. n = 4, [####,####,r###,####],[####,#q##,####,####],[##r#,###b,####,BRnn],[####,####,#N##,#KQ#]

    여기에 이미지 설명을 입력하십시오(IV) 여기에 이미지 설명을 입력하십시오(III) 여기에 이미지 설명을 입력하십시오(II) 여기에 이미지 설명을 입력하십시오(I)

    출력 : true 설명 :이 경우 왕은 기사 중 하나와 여왕으로부터 점검을 받고 있습니다. White는 점검 항목 중 하나를 캡처 / 차단할 수 있지만 둘 다 캡처 / 차단할 수는 없습니다. 따라서 화잇은 왕을 체크 아웃하지 말아야하지만 선택의 여지가 없다.

  2. n = 3, [###,##b,r#r],[###,###,###],[#k#,###,#K#]

    여기에 이미지 설명을 입력하십시오(III) 여기에 이미지 설명을 입력하십시오(II) 여기에 이미지 설명을 입력하십시오(I)

출력 : false 설명 : 흰색이 점검되지 않지만 점검하지 않고 이동하는 방법이 없습니다. 따라서 교묘 한 사람이지만 검열 관은 아닙니다.

  1. n = 3, [##k,###,r#K],[###,n##,#N#],[###,###,#Q#]

    여기에 이미지 설명을 입력하십시오(III) 여기에 이미지 설명을 입력하십시오(II) 여기에 이미지 설명을 입력하십시오(I)

출력 : true 설명 : 백인이 왕을 방어하기 위해 여왕과 대결하고 싶지만 기사가 길을 막고 있습니다.

  1. n = 3, [###,###,##q],[###,###,###],[#k#,###,rNK]

    여기에 이미지 설명을 입력하십시오(III) 여기에 이미지 설명을 입력하십시오(II) 여기에 이미지 설명을 입력하십시오(I)

출력 : true 설명 : 화이트는 기사와 함께 여왕을 데려 갈 수 없습니다. 루크가 화이트의 왕을 확인하기 때문입니다.

  1. n = 2, [#q,##],[##,K#]

    여기에 이미지 설명을 입력하십시오(II) 여기에 이미지 설명을 입력하십시오(I)

출력 : false 설명 : 흰색은 왕과 함께 여왕을 붙잡을 수 있습니다.

  1. n = 2, [rq,##],[##,K#]

    여기에 이미지 설명을 입력하십시오(II) 여기에 이미지 설명을 입력하십시오(I)

출력 : true 설명 : 이번에는 사기꾼이 지키고 있기 때문에 왕이 여왕을 붙잡을 수 없습니다.

  1. n = 3, [###,###,#q#],[###,###,###],[#k#,###,BKn]

    여기에 이미지 설명을 입력하십시오(III) 여기에 이미지 설명을 입력하십시오(II) 여기에 이미지 설명을 입력하십시오(I)

출력 : false 설명 : 기사를 사로 잡으면 백인 왕이 탈출 할 수 있습니다.


세부 사항이지만 cell.className = (i + j)%2 == 0 ? "black" : "white"스 니펫에서 더 좋지 않을까요?
Arnauld

@ Arnauld lol, 가장 분명한 것을 고치는 것을 잊었습니다.
geokavel

지원해야하는 최대 보드 크기는 얼마입니까?
Weijun Zhou

1
@WeijunZhou 기본적으로 코드가 작동하는지 확인하기 위해 적절한 시간 내에 테스트 사례를 수행 할 수 있어야합니다. 더 큰 숫자의 경우 이론적으로 무한한 시간과 메모리가 필요합니다.
geokavel

답변:


5

루비 , 412 413 바이트

->b,w=2{n=b=~/\n/
g=->h{h[0]-~n*(h[1]-~n*h[2])} 
r=1
(n**6).times{|i|a=b*1     
m=[]
9.times{|j|m<<(j<6?i/n**j%n:m[j-6]-m[j-3])}
x,y,z=v=m[6,3].map{|j|j*j}
d=v.max
e=x+y+z
q=95&o=(t=a[p=g[m[3,3]]]).ord
k=a[s=g[m]].ord
o/32==w&&(o^k>31||k==75)&&((q%8==2&&q%9*d==e||q==81&&x%d+y%d+z%d<1)&&((1...c=d**0.5).map{|j|a[p+g[m[6,3]]/c*j]}+[?#]).max<?A||q==78&&e==5||q==75&&e<4)&&(a[p]=?0;a[s]=t;r&&=w>2?a=~/K/:!f[a,3])}
r}

온라인으로 사용해보십시오! 이제 모든 테스트 사례를 확인했습니다. 사례 5 (stalemate case)의 버그를 수정하기 위해 코드가 1 바이트 증가했습니다.

아래에 표시된 형식으로 문자열로 입력해야하는 Llambda 함수 다음 이동시 고려할 32 개의 ASCII 코드 그룹을 나타내는 선택적 두 번째 매개 변수를 지정할 수 있습니다 (기본적으로이 2 개는 대문자 / 백색 문자에 해당하지만이 함수는 소문자 / 검정색 문자에 해당하는 3을 사용하여 재귀 적으로 호출됩니다. )

재귀 수준 1 : 흰색 (모든 큐브에서 모든 큐브로)에 대해 가능한 모든 이동을 시도하고 모든 합법적 인 단계를 밟습니다. 재귀 수준 2 : 각 경우에 검은 색으로 가능한 모든 움직임을 단계별로 실행합니다. 만약 하얀 왕이 모든 가능한 검은 움직임에서 살아남 았다면 이것은 참이됩니다. 재귀 수준 1 : 가능한 모든 하얀 움직임으로 인해 하얀 왕이 가능한 모든 검은 움직임에서 살아남지 못하는 경우 true를 반환합니다 (그렇지 않으면 false).

일반적으로 조각은 친숙한 조각이 차지하는 사각형으로 이동할 수 없습니다. 흰색이 전혀 움직이지 않는 경우 (체크 메이트가 교착 상태가 아님)를 고려하기 위해 왕이 이미있는 광장으로 "이동"하는 경우도 허용됩니다. 코드가 짧기 때문에 다른 흰색 조각도 흰색 왕이 차지하는 사각형으로 이동할 수 있습니다. 이것은 말도 안되는 움직임이지만 허용해도 결과에 영향을 미치지 않으므로 문제가되지 않습니다.

다음 테스트는 각 조각에 대해 이동이 유효한지 확인하는 데 사용됩니다. x,y,z각 축에서 이동 한 거리의 제곱입니다. e이것들의 합 (따라서 유클리드 거리의 제곱)이며 d최대 값입니다. 피스 유형은 소문자 ASCII 값을 대문자로 변환하기 위해 95로 AND됩니다.

Bishop and Rook (ASCII 66 and 82) For the rook e=1*d. For the bishop e=3*d. 
The same code is used for both with q%9 giving 1 and 3 respectively.

Queen (ASCII 81) x%d+y%d+z%d<1 Each axis must be 0 or d, so this sum must be 0.

For the above pieces, any cubes crossed must be checked to ensure they are empty.

Knight (ASCII 78) e=5

King (ASCII 75) e<4

주석이 달린 코드

->b,w=2{                                                        #board, colour to move (default upcase/white)
  n=b=~/\n/                                                     #n=board size (index of first newline.)
  g=->h{h[0]-~n*(h[1]-~n*h[2])}                                 #Function to calculate position in string based on array of 3d coordinates.
  r=1                                                           #Return value = truthy.
  (n**6).times{|i|                                              #Iterate through n**6 moves (n**3 start cubes and n**3 end cubes.)
    a=b*1      
    m=[]                                                        #Make an empty array for coordinates.                                             
    9.times{|j|m<<(j<6?i/n**j%n:m[j-6]-m[j-3])}                 #Split i into six base n digits for the start and end coordinates. also derive 3 relative move distances.
    x,y,z=v=m[6,3].map{|j|j*j}                                  #v=array of relative distances squared. x,y,z are the 3 individual relative distances squared.
    d=v.max                                                     #Max of x,y,z                                     
    e=x+y+z                                                     #Square of euclidean distance
    q=95&o=(t=a[p=g[m[3,3]]]).ord                               #t=contents of cube to move from. o=ascii value, q=uppercase of o.
    k=a[s=g[m]].ord                                             #k=ascii value of contents of cube to move to.
    o/32==w&&(o^k>31||k==75)&&                                  #If o is in the right 32 byte range (uppercase or lowercase) AND the destination contains the white king or a character not in the same 32 byte range AND...
      ((q%8==2&&q%9*d==e||q==81&&x%d+y%d+z%d<1)&&               #the piece is a rook, bishop or queen with a valid move (as described in the text) AND..
      ((1...c=d**0.5).map{|j|a[p+g[m[6,3]]/c*j]}+[?#]).max<?A|| #the intervening squares are all empty, OR..
      q==78&&e==5||                                             #the piece is a knight and the move has euclidean distance sqrt(5) OR..
      q==75&&e<4)&&                                             #the piece is a king and the move has euclidean distance <4 THEN
      (a[p]=?0;a[s]=t;r&&=w>2?a=~/K/:!f[a,3])                   #put a 0 in the start cube and put the piece in the end cube. If moved piece is black, is the white king still there? AND with return value.
  }                                                             #If moved piece is white, recursively call the f to carry out the black moves. Does the white king NOT survive some black moves? AND with return value.
r}

1 자리 아스키 값을 사용하여 골프를 칠 수 없습니까? 또한 세 번째 단락에서 "체크 메이트가 아닌 혐의자"를 의미 했습니까?
geokavel

@geokavel 루비에서 단일 아스키 값의 가장 짧은 표현은 ?A(코드에 예제가 있습니다) 여전히 2 바이트입니다. 여전히 일부 언어보다 낫습니다 "A". 문자가 아닌 ASCII 값으로 더 잘 작동하는 특정 조작이있었습니다 (특히 o^k>31조각이 비어있는 사각형 또는 친숙한 조각이 있지만 적대적인 조각이 아닌 점으로 이동할 수 있음).
Level River St

장군이 교착 상태가 아니라는 뜻입니다. 교착 상태는 플레이어가 움직일 때 왕이 위협받는 상황입니다. 장군은 플레이어가 움직일 때와 그렇지 않은 경우 왕이 위협받는 상황입니다.
Level River St

ASCII 값 대신 int 값을 사용하면 (예 : 문자열 대신 int 배열) 어떻게됩니까?
geokavel

@geokavel ints는 아마도 더 짧을 것입니다. 스펙에서 특별히 허용하기 때문에 나중에 수정할 수 있습니다. 그러나 나는 더 읽기 쉬운 (따라서 개발하기 쉽기 때문에) 선택한 형식으로 부분적으로 나갔으며 부분적으로 내 생각에 큰 영향을 미친 내 대답에 영감을 얻었 기 때문에 codegolf.stackexchange.com/a/45544/15599
수준 강 St
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.