Cờ vua ba chiều


26

Để bảo vệ quyết định khó hiểu của ai đó, mọi người thường nói rằng người đó đang vượt qua đầu mọi người và chơi cờ vua 3 chiều. Bây giờ là cơ hội của bạn để chơi cờ 3 chiều!

Quy tắc

Có nhiều biến thể của Cờ vua 3D , nhưng đối với thử thách này, tôi đã tự tạo ra. Phiên bản của tôi giống như cờ vua thông thường ngoại trừ các quân cờ nằm ​​trong các hình khối thay vì hình vuông, và bây giờ có thêm một chiều chuyển động. Để làm cho thử thách này đơn giản, không có con tốtkhông có lâu đài .

Phong trào mảnh

(Hướng la bàn đề cập đến chuyển động sẽ xảy ra trên bàn cờ tiêu chuẩn, Lên và Xuống đề cập đến việc di chuyển theo chiều dọc trên bàn cờ 3D).

  • King - có 26 ô vuông có thể đi vào một lượt cho trước: N, NE, E, SE, S, SW, W, NW; cũng như lên, xuống và lên / xuống + một trong các hướng la bàn.
  • Nữ hoàng - có thể di chuyển cùng hướng với Nhà vua, nhưng theo như những gì cô ấy muốn theo những hướng đó.
  • Rook - có thể di chuyển theo 6 hướng: N, E, S, W, Up và Down,
  • Giám mục - có 8 hướng đi ba chiều: NE + Lên / Xuống, SE + Lên / Xuống, SW + Lên / Xuống, Tây Bắc + Lên / Xuống
  • Hiệp sĩ - di chuyển 2 không gian một trục, sau đó 1 không gian trên một không gian khác. Cũng giống như cờ vua thông thường, hiệp sĩ là quân cờ duy nhất có thể nhảy qua các quân cờ khác.

Kiểm tra mảnh

Sử dụng đoạn mã này để xem cách các mảnh khác nhau di chuyển trên bảng 3D ( mẹo : kiểm tra các *Testchức năng trong JS để biết cách nhanh chóng để xác định xem hình vuông có phải là di chuyển hợp lệ hay không, chỉ đơn giản dựa trên khoảng cách tuyệt đối của nó so với mảnh.):

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>

Thử thách

Đưa ra một bảng n x n x n , xác định xem vua trắng có ở trong tướng không.

Đầu vào

  • (Tùy chọn) n 2 - kích thước của bảng
  • Ban trò chơi
    • Có thể ở dạng 1d- 2d- hoặc 3d- hoặc định dạng tương tự khác. Ký hiệu có thể ở bất kỳ định dạng đơn giản. Ví dụ: KQRBN (Trắng) và kqrbn (Đen) với # cho các hình khối trống. Hoặc, sử dụng số cho các giá trị khác nhau.
    • Hãy nghĩ về bàn cờ 3D khi nhiều bàn xếp chồng lên nhau và được liệt kê từ trên xuống dưới. Sau đó, mỗi bảng riêng lẻ được ký hiệu từ trái sang phải, trở lại mặt trước (Mặt đen sang Mặt trắng).
    • Hãy tưởng tượng trường hợp 2x2x2 này được đưa ra dưới dạng mảng 3D:
 [
[[bq] [##]]
[[bn] [KQ]]
]

Bảng "trên cùng": bảng nhập mô tả hình ảnh ở đây"dưới cùng":nhập mô tả hình ảnh ở đây

Đầu ra

  • boolean (giá trị trung thực / giả) - đúng nếu vua trắng ở trong checkmate, sai khác.

Chiếu tướng

Vua trắng đang kiểm tra xem một mảnh đen có đe dọa bắt nó trong lượt tiếp theo của Đen không. Để thoát khỏi tầm kiểm soát, White cần phải di chuyển vị vua của mình đến nơi an toàn, bảo vệ nó bằng một mảnh khác hoặc bắt giữ mảnh đe dọa. Nếu Trắng không có cách nào thoát khỏi kiểm tra, thì vua trắng đang ở trong . Hãy nhớ rằng, nếu Trắng không kiểm tra, nhưng không thể di chuyển mà không kiểm tra, thì đó là một sự bế tắc , không phải là một người kiểm tra.

Đặc điểm kỹ thuật

  • Bạn sẽ không được trao một bảng mà vua đen đang cố gắng "kiểm tra" vua trắng, hoặc một bảng nơi cả hai vị vua đang kiểm tra (kịch bản không thể).

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

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

    nhập mô tả hình ảnh ở đây(III) nhập mô tả hình ảnh ở đây(II) nhập mô tả hình ảnh ở đây(I)

    Đầu ra: đúng

    Giải thích: Nhà vua đang nhận được một tấm séc từ tân binh trên tầng cao nhất. Các tân binh trắng không thể chặn cuộc tấn công hoặc bắt giữ các tân binh đe dọa, vì vậy nhà vua phải cố gắng di chuyển ra khỏi đường. Hãy xem xét các lựa chọn di chuyển của nhà vua:

    1. c2 (I) - được giám mục bảo vệ tại b3 (II)
    2. b2 (I) - được bảo vệ bởi hiệp sĩ tại a2 (III)
    3. c1 (II) - được bảo vệ bởi tân binh tại c1 (III)
    4. b1 (II) - được bảo vệ bởi tân binh tại b1 (III)
    5. c2 (II) - được bảo vệ bởi hiệp sĩ tại a2 (III)
    6. b2 (II) - được giám mục bảo vệ tại a1 (I)

Vì nhà vua không thể thoát khỏi kiểm tra, đó là một người kiểm tra!

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

    nhập mô tả hình ảnh ở đây(III) nhập mô tả hình ảnh ở đây(II) nhập mô tả hình ảnh ở đây(I)

    Đầu ra: sai Giải thích: Nhà vua đang nhận được một tấm séc từ nữ hoàng, và không có động thái nào để trốn thoát hay chặn lại. Tuy nhiên, hiệp sĩ có thể bắt được nữ hoàng.

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

    nhập mô tả hình ảnh ở đây(III) nhập mô tả hình ảnh ở đây(II) nhập mô tả hình ảnh ở đây(I)

Đầu ra: sai Giải thích: White không có cách nào bắt được nữ hoàng đang đe dọa hoặc chuyển vị vua của mình đến nơi an toàn. Tuy nhiên, bằng cách chuyển giám mục của mình sang b2 (II), White có thể ngăn chặn mối đe dọa của nữ hoàng.

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

    nhập mô tả hình ảnh ở đây(IV) nhập mô tả hình ảnh ở đây(III) nhập mô tả hình ảnh ở đây(II)nhập mô tả hình ảnh ở đây (I)

    Đầu ra: đúng Giải thích: Trong trường hợp này, nhà vua đang nhận được một tấm séc từ một trong các hiệp sĩ và một nữ hoàng. Mặc dù Trắng có thể chụp / chặn một trong các mảnh kiểm tra, anh ta không thể chụp / chặn cả hai. Do đó, White phải cố gắng di chuyển vị vua của mình ra khỏi tầm kiểm soát, nhưng anh ta không có lựa chọn nào khác.

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

    nhập mô tả hình ảnh ở đây(III) nhập mô tả hình ảnh ở đây(II)nhập mô tả hình ảnh ở đây(I)

Đầu ra: sai Giải thích: Màu trắng không nằm trong kiểm tra, nhưng không có cách nào di chuyển mà không được kiểm tra. Do đó, nó là một bế tắc, nhưng không phải là một người kiểm tra.

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

    nhập mô tả hình ảnh ở đây(III) nhập mô tả hình ảnh ở đây(II)nhập mô tả hình ảnh ở đây(I)

Đầu ra: đúng Giải thích: White muốn tham gia cùng với nữ hoàng của mình để bảo vệ vị vua của mình, nhưng hiệp sĩ của anh ta đang chặn đường.

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

    nhập mô tả hình ảnh ở đây(III) nhập mô tả hình ảnh ở đây(II) nhập mô tả hình ảnh ở đây(I)

Kết quả: đúng Giải thích: Trắng không thể đưa nữ hoàng đi theo hiệp sĩ của mình, bởi vì sau đó, tân binh sẽ kiểm tra vua của White.

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

    nhập mô tả hình ảnh ở đây(II) nhập mô tả hình ảnh ở đây(I)

Kết quả: sai Giải thích: Trắng có thể bắt nữ hoàng cùng với vua của mình.

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

    nhập mô tả hình ảnh ở đây(II) nhập mô tả hình ảnh ở đây(I)

Đầu ra: đúng Giải thích: Lần này tân binh đang canh gác, nên nhà vua không thể bắt được nữ hoàng.

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

    nhập mô tả hình ảnh ở đây(III) nhập mô tả hình ảnh ở đây(II) nhập mô tả hình ảnh ở đây(I)

Đầu ra: sai Giải thích: Vua trắng có thể trốn thoát bằng cách bắt các hiệp sĩ.


Chỉ là một chi tiết, nhưng sẽ không cell.className = (i + j)%2 == 0 ? "black" : "white"tốt hơn trong đoạn trích?
Arnauld

@Arnauld lol, quên sửa điều rõ ràng nhất.
geokavel

Kích thước bảng lớn nhất chúng ta cần hỗ trợ là gì?
Weijun Zhou

1
@ WeijunZhou Về cơ bản, bạn sẽ có thể thực hiện các trường hợp thử nghiệm trong một khoảng thời gian hợp lý để xem mã của bạn có hoạt động không. Đối với số lượng lớn hơn, nó chỉ cần hoạt động trên lý thuyết với thời gian và bộ nhớ vô hạn.
geokavel

Câu trả lời:


5

Ruby , 412 413 byte

->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}

Hãy thử trực tuyến! Bây giờ kiểm tra trên tất cả các trường hợp thử nghiệm. Mã tăng thêm 1 byte để sửa lỗi trong trường hợp 5 (trường hợp bế tắc.)

Hàm Llambda yêu cầu đầu vào dưới dạng một chuỗi theo định dạng hiển thị bên dưới. Có thể đưa ra một tham số thứ hai tùy chọn, cho biết nhóm 32 mã ASCII nào sẽ được xem xét trong lần di chuyển tiếp theo (theo mặc định 2 này tương ứng với các ký tự in hoa / trắng, nhưng hàm gọi chính nó bằng cách sử dụng 3 ký tự chữ thường / đen. )

Đệ quy cấp 1: Thử tất cả các chuyển động có thể có đối với màu trắng (bất kỳ khối lập phương nào đến bất kỳ khối lập phương nào) và bước qua tất cả các khối hợp pháp. Đệ quy cấp 2: Trong mỗi trường hợp, sau đó nó tự gọi mình để bước qua tất cả các chuyển động có thể có cho màu đen. Điều này trở lại đúng nếu vua trắng đã sống sót sau tất cả các động thái đen có thể. Đệ quy cấp 1: Nếu tất cả các chuyển động trắng có thể dẫn đến tình huống vua trắng KHÔNG tồn tại tất cả các chuyển động đen có thể, thì trả về đúng (nếu không là sai.)

Nói chung, một mảnh không thể di chuyển đến một hình vuông chiếm bởi một mảnh thân thiện. Để xem xét trường hợp màu trắng hoàn toàn không di chuyển (do đó, người kiểm tra không bế tắc), trường hợp nhà vua "di chuyển" đến quảng trường mà anh ta đã ở cũng được cho phép. Vì lý do mã ngắn, các mảnh trắng khác cũng được phép di chuyển đến quảng trường bị vua trắng chiếm. Đây là một động thái vô nghĩa, nhưng cho phép nó không ảnh hưởng đến kết quả nên nó không phải là vấn đề.

Các thử nghiệm sau đây được sử dụng để kiểm tra xem một động thái có hợp lệ cho từng mảnh hay không. x,y,zlà bình phương của khoảng cách di chuyển trong mỗi trục. elà tổng của những cái này (do đó bình phương của khoảng cách euclide) và dlà cực đại. Loại mảnh được ANDed với 95 để chuyển đổi các giá trị ASCII chữ thường thành chữ hoa.

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

Mã nhận xét

->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}

Bạn không thể đánh gôn điều này bằng cách sử dụng các giá trị ascii 1 chữ số? Ngoài ra, ý của bạn là "bế tắc không phải là người kiểm tra" trong đoạn thứ ba?
geokavel

@geokavel Đại diện ngắn nhất của một giá trị ascii trong Ruby là ?A(có một ví dụ trong mã) vì vậy nó vẫn là 2 byte. Vẫn tốt hơn một số ngôn ngữ yêu cầu "A". Có một số thao tác nhất định phù hợp hơn với các giá trị ASCII thay vì các ký tự (đặc biệt là o^k>31đảm bảo rằng một mảnh có thể di chuyển đến một hình vuông không có người hoặc bị chiếm bởi một mảnh thân thiện nhưng không phải là một kẻ thù.)
Level River St

Ý tôi là checkmate không bế tắc. Bế tắc là tình huống nhà vua bị đe dọa nếu người chơi di chuyển. Checkmate là tình huống mà nhà vua bị đe dọa nếu người chơi di chuyển, và cả khi anh ta không.
Cấp sông St

Điều gì xảy ra nếu bạn sử dụng giá trị int thay vì giá trị ascii (tức là mảng int thay vì chuỗi)?
geokavel

@geokavel ints có thể sẽ ngắn hơn và tôi có thể sửa lại sau vì nó được đặc tả cho phép. Nhưng tôi đã đi với định dạng được chọn một phần vì nó dễ đọc hơn con người (do đó dễ phát triển hơn) và một phần vì tôi được truyền cảm hứng từ câu trả lời này của tôi đã ảnh hưởng lớn đến suy nghĩ của tôi: codegolf.stackexchange.com/a/45544/15599
Cấp độ Sông St
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.