Câu đố lập trình viên: Mã hóa trạng thái bàn cờ trong suốt trò chơi


95

Không hẳn là một câu hỏi, nhiều hơn một câu đố ...

Trong những năm qua, tôi đã tham gia vào một số cuộc phỏng vấn kỹ thuật của nhân viên mới. Ngoài việc hỏi những câu hỏi tiêu chuẩn "bạn có biết công nghệ X", tôi cũng cố gắng tìm hiểu cách họ tiếp cận vấn đề. Thông thường, tôi sẽ gửi câu hỏi cho họ qua email một ngày trước cuộc phỏng vấn và mong họ đưa ra giải pháp vào ngày hôm sau.

Thường thì kết quả sẽ khá thú vị - sai, nhưng thú vị - và người đó sẽ vẫn nhận được đề xuất của tôi nếu họ có thể giải thích lý do tại sao họ thực hiện một cách tiếp cận cụ thể.

Vì vậy, tôi nghĩ rằng tôi sẽ đưa ra một trong những câu hỏi của mình cho khán giả của Stack Overflow.

Câu hỏi: Cách tiết kiệm không gian nhất mà bạn có thể nghĩ ra để mã hóa trạng thái của một trò chơi cờ vua (hoặc tập hợp con của chúng) là gì? Tức là, đưa ra một bàn cờ với các quân cờ được sắp xếp hợp pháp, mã hóa cả trạng thái ban đầu này và tất cả các nước đi hợp pháp tiếp theo được thực hiện bởi người chơi trong trò chơi.

Không cần mã cho câu trả lời, chỉ cần mô tả thuật toán bạn sẽ sử dụng.

CHỈNH SỬA: Như một trong những áp phích đã chỉ ra, tôi đã không xem xét khoảng thời gian giữa các lần di chuyển. Vui lòng tính toán cho điều đó như một phần bổ sung tùy chọn :)

EDIT2: Chỉ để làm rõ thêm ... Hãy nhớ rằng, bộ mã hóa / giải mã nhận biết quy tắc. Những thứ duy nhất thực sự cần được lưu trữ là lựa chọn của người chơi - bất kỳ thứ gì khác có thể được giả định là do bộ mã hóa / giải mã biết.

EDIT3: Sẽ rất khó để chọn ra người chiến thắng ở đây :) Rất nhiều câu trả lời tuyệt vời!


4
Trạng thái ban đầu của một ván cờ không được xác định rõ sao? Tại sao nó phải được mã hóa? Tôi nghĩ chỉ cần mã hóa sự khác biệt giữa mỗi lượt (= di chuyển) là đủ.
tanascius

1
Anh ta giả định rằng trò chơi có thể bắt đầu với bất kỳ thiết lập ban đầu hợp pháp nào (giống như trong các câu đố trong trò chơi cờ vua bạn có thể tìm thấy trên báo).
Aaron Digulla

6
được chặt chẽ, bạn cũng sẽ phải để mã hóa tất cả các vị trí trong quá khứ, bởi vì nếu các vị trí tương tự xuất hiện ba lần đó là một trận hòa en.wikipedia.org/wiki/Threefold_repetition
các hệ thống kiểm soát bay

4
Gợi ý: hãy biến đây thành một cuộc thi thực sự, nơi mọi người gửi bài dự thi của họ dưới dạng chương trình. Một chương trình sẽ lấy một trò chơi cờ vua làm đầu vào (bạn có thể xác định một số định dạng cơ bản, có thể đọc được, không được tối ưu hóa cho điều này) và sẽ xuất ra trò chơi được nén. Sau đó, với một tham số, nó sẽ lấy trò chơi được nén và tạo lại đầu vào ban đầu mà sẽ phải khớp.
Vilx-

2
Thêm vào đó, nó sẽ chứng minh rằng bạn không thể làm theo hướng dẫn ... Ngay cả người ubercoder nhất cũng cần làm theo hướng dẫn tại một số thời điểm. Tôi đã gặp phải những tình huống mà tôi được yêu cầu thực hiện một cái gì đó theo một cách nhất định, mặc dù tôi đã nghĩ (và đã nói) đó là một cách triển khai ngu ngốc, chỉ để lại quả trứng trên mặt khi hóa ra có một lý do rất chính đáng (mà tôi không biết hoặc không hiểu) để nó được triển khai theo cách đó.
Andrew Rollings

Câu trả lời:


132

Cập nhật: Tôi thích chủ đề này rất nhiều, tôi đã viết Câu đố lập trình, Vị trí cờ vua và Mã hóa Huffman . Nếu bạn đọc qua phần này, tôi đã xác định rằng cách duy nhất để lưu trữ trạng thái trò chơi hoàn chỉnh là lưu trữ một danh sách đầy đủ các bước di chuyển. Đọc tiếp để biết lý do tại sao. Vì vậy, tôi sử dụng một phiên bản đơn giản hóa của vấn đề cho bố cục mảnh.

Vấn đề

Hình ảnh này minh họa vị trí Cờ vua bắt đầu. Cờ vua diễn ra trên bàn cờ 8x8 với mỗi người chơi bắt đầu với một bộ 16 quân giống hệt nhau bao gồm 8 quân tốt, 2 quân, 2 kỵ sĩ, 2 quân, 1 quân hậu và 1 quân vương như minh họa ở đây:

bắt đầu vị trí cờ vua

Vị trí thường được ghi lại dưới dạng một chữ cái cho cột theo sau là số cho hàng để quân hậu của Trắng ở d1. Các chuyển động thường được lưu trữ dưới dạng ký hiệu đại số , không rõ ràng và thường chỉ xác định thông tin tối thiểu cần thiết. Hãy xem xét phần mở đầu này:

  1. e4 e5
  2. Nf3 Nc6

dịch thành:

  1. Trắng di chuyển con tốt của vua từ e2 sang e4 (nó là quân duy nhất có thể đến e4 do đó “e4”);
  2. Đen chuyển quân của vua từ e7 sang e5;
  3. Trắng di chuyển quân (N) đến f3;
  4. Màu đen di chuyển kỵ sĩ đến c6.

Bảng trông như thế này:

mở đầu

Một khả năng quan trọng đối với bất kỳ lập trình viên nào là có thể chỉ định vấn đề một cách chính xác và rõ ràng .

Vậy có gì thiếu sót hoặc mơ hồ? Rất nhiều như nó bật ra.

Bang hội đồng vs Bang trò chơi

Điều đầu tiên bạn cần xác định là bạn đang lưu trữ trạng thái của trò chơi hay vị trí của các quân cờ trên bàn cờ. Mã hóa đơn giản vị trí của các mảnh là một chuyện nhưng vấn đề nói lên “tất cả các động thái pháp lý tiếp theo”. Vấn đề cũng không nói gì về việc biết các động thái cho đến thời điểm này. Đó thực sự là một vấn đề như tôi sẽ giải thích.

Castling

Trò chơi đã diễn ra như sau:

  1. e4 e5
  2. Nf3 Nc6
  3. Bb5 a6
  4. Ba4 Bc5

Bảng trông như sau:

mở sau

Màu trắng có tùy chọn nhập thành . Một phần của các yêu cầu đối với việc này là vua và quân có liên quan không bao giờ được di chuyển, vì vậy dù vua hay một trong hai quân của mỗi bên đã di chuyển đều cần được lưu trữ. Rõ ràng là nếu họ không ở vị trí xuất phát của họ, họ đã di chuyển nếu không thì cần phải xác định rõ.

Có một số chiến lược có thể được sử dụng để giải quyết vấn đề này.

Đầu tiên, chúng ta có thể lưu trữ thêm 6 bit thông tin (1 cho mỗi quân và quân) để cho biết quân đó đã di chuyển hay chưa. Chúng ta có thể sắp xếp hợp lý điều này bằng cách chỉ lưu trữ một chút cho một trong sáu hình vuông này nếu mảnh đúng nằm trong đó. Ngoài ra, chúng ta có thể coi mỗi quân không di chuyển như một loại quân khác, vì vậy thay vì 6 loại quân ở mỗi bên (quân tốt, quân, kỵ sĩ, giám mục, nữ hoàng và vua) thì có 8 (thêm quân không di chuyển và vua không di chuyển).

En Passant

Một quy tắc đặc biệt khác và thường bị bỏ qua trong Cờ vua là En Passant .

en passant

Trò chơi đã tiến triển.

  1. e4 e5
  2. Nf3 Nc6
  3. Bb5 a6
  4. Ba4 Bc5
  5. OO b5
  6. Bb3 b4
  7. c4

Con tốt của Đen ở b4 bây giờ có tùy chọn di chuyển con của mình ở b4 đến c3 và cầm quân của Trắng ở c4. Điều này chỉ xảy ra ở cơ hội đầu tiên có nghĩa là nếu Đen bỏ qua lựa chọn bây giờ anh ta không thể thực hiện bước tiếp theo. Vì vậy, chúng ta cần lưu trữ cái này.

Nếu chúng ta biết động thái trước đó, chúng ta chắc chắn có thể trả lời nếu En Passant có thể thực hiện được. Ngoài ra, chúng tôi có thể lưu trữ xem mỗi con tốt ở hạng 4 của nó có vừa di chuyển đến đó hay không với một lần di chuyển kép về phía trước. Hoặc chúng ta có thể xem xét từng vị trí En Passant có thể có trên bảng và có một lá cờ để chỉ ra liệu nó có thể có hay không.

Khuyến mại

khuyến mãi cầm đồ

Đó là nước đi của White. Nếu Trắng di chuyển quân của mình ở h7 đến h8, quân đó có thể được thăng lên bất kỳ quân nào khác (nhưng không phải quân vua). 99% trường hợp nó được thăng lên thành Nữ hoàng nhưng đôi khi không phải vậy, thường là vì điều đó có thể gây ra bế tắc khi nếu không thì bạn sẽ thắng. Điều này được viết là:

  1. h8 = Q

Điều này rất quan trọng trong vấn đề của chúng ta bởi vì nó có nghĩa là chúng ta không thể tin rằng có một số lượng cố định ở mỗi bên. Hoàn toàn có thể xảy ra (nhưng cực kỳ khó xảy ra) cho một bên kết thúc với 9 quân hậu, 10 quân, 10 giám mục hoặc 10 hiệp sĩ nếu cả 8 con tốt đều được thăng cấp.

Bế tắc

Khi ở một vị trí mà bạn không thể giành chiến thắng, chiến thuật tốt nhất của mình là cố gắng khai thông thế bế tắc . Biến thể có khả năng xảy ra nhất là bạn không thể thực hiện một nước đi hợp pháp (thường là vì bất kỳ nước đi nào khi đưa vua của bạn vào vòng kiểm soát). Trong trường hợp này, bạn có thể yêu cầu một trận hòa. Điều này là dễ dàng để phục vụ cho.

Biến thể thứ hai là lặp lại ba lần . Nếu cùng một vị trí bàn cờ xảy ra ba lần trong một trò chơi (hoặc sẽ xảy ra lần thứ ba ở nước đi tiếp theo), một trận hòa có thể được xác nhận. Các vị trí không cần phải xảy ra theo bất kỳ thứ tự cụ thể nào (có nghĩa là nó không phải lặp lại cùng một chuỗi các bước di chuyển ba lần). Điều này làm phức tạp vấn đề vì bạn phải nhớ mọi vị trí bảng trước đó. Nếu đây là một yêu cầu của vấn đề, giải pháp khả thi duy nhất cho vấn đề là lưu trữ mọi động thái trước đó.

Cuối cùng, có quy tắc di chuyển năm mươi . Một người chơi có thể yêu cầu hòa nếu không có con tốt nào di chuyển và không có quân cờ nào được lấy trong năm mươi nước đi liên tiếp trước đó, vì vậy chúng tôi sẽ cần lưu trữ bao nhiêu nước đi kể từ khi một con tốt được di chuyển hoặc một quân cờ bị 6 bit (0-63).

Đến lượt của ai?

Tất nhiên chúng ta cũng cần biết đó là lượt của ai và đây là một chút thông tin.

Hai vấn đề

Vì trường hợp bế tắc, cách duy nhất khả thi hoặc hợp lý để lưu trữ trạng thái trò chơi là lưu trữ tất cả các nước đi đã dẫn đến vị trí này. Tôi sẽ giải quyết một vấn đề đó. Bài toán trạng thái bàn cờ sẽ được đơn giản hóa thành: lưu trữ vị trí hiện tại của tất cả các quân cờ trên bàn cờ bỏ qua các điều kiện nhập thành, bị động, bế tắc và đến lượt của ai .

Bố cục mảnh có thể được xử lý rộng rãi theo một trong hai cách: bằng cách lưu trữ nội dung của mỗi ô vuông hoặc bằng cách lưu trữ vị trí của mỗi mảnh.

Nội dung đơn giản

Có sáu loại quân cờ (cầm đồ, quân xe, hiệp sĩ, giám mục, nữ hoàng và vua). Mỗi mảnh có thể là Trắng hoặc Đen nên một hình vuông có thể chứa một trong 12 mảnh có thể hoặc nó có thể trống để có 13 khả năng. 13 có thể được lưu trữ trong 4 bit (0-15) Vì vậy giải pháp đơn giản nhất là lưu trữ 4 bit cho mỗi hình vuông nhân với 64 hình vuông hoặc 256 bit thông tin.

Ưu điểm của phương pháp này là thao tác cực kỳ dễ dàng và nhanh chóng. Điều này thậm chí có thể được mở rộng bằng cách thêm 3 khả năng khác mà không cần tăng yêu cầu lưu trữ: một con tốt đã di chuyển 2 khoảng trống ở lượt cuối cùng, một quân vua không di chuyển và một quân xe chưa di chuyển, sẽ phục vụ cho rất nhiều của các vấn đề đã đề cập trước đó.

Nhưng chúng ta có thể làm tốt hơn.

Mã hóa cơ sở 13

Thường sẽ hữu ích khi nghĩ về vị trí hội đồng quản trị là một con số rất lớn. Điều này thường được thực hiện trong khoa học máy tính. Ví dụ: vấn đề tạm dừng coi một chương trình máy tính (đúng ra) là một số lớn.

Giải pháp đầu tiên coi vị trí là một số cơ số 16 gồm 64 chữ số nhưng như đã chứng minh là có sự dư thừa trong thông tin này (là 3 khả năng không sử dụng cho mỗi “chữ số”) nên chúng ta có thể giảm không gian số xuống còn 64 chữ số cơ số 13. Tất nhiên điều này không thể được thực hiện hiệu quả như cơ sở 16 nhưng nó sẽ tiết kiệm yêu cầu lưu trữ (và giảm thiểu không gian lưu trữ là mục tiêu của chúng tôi).

Trong cơ số 10, số 234 tương đương với 2 x 10 2 + 3 x 10 1 + 4 x 10 0 .

Trong cơ số 16, số 0xA50 tương đương với 10 x 16 2 + 5 x 16 1 + 0 x 16 0 = 2640 (thập phân).

Vì vậy, chúng ta có thể mã hóa vị trí của chúng ta là p 0 x 13 63 + p 1 x 13 62 + ... + p 63 x 13 0 trong đó p i đại diện cho nội dung của hình vuông i .

2 256 bằng khoảng 1,16e77. 13 64 bằng khoảng 1,96e71, yêu cầu không gian lưu trữ 237 bit. Tiết kiệm chỉ 7,5% đi kèm với chi phí chế tác tăng lên đáng kể .

Mã hóa cơ sở biến

Trong bảng luật nhất định các quân cờ không thể xuất hiện trong các ô vuông nhất định. Ví dụ: các con tốt không thể xảy ra ở hàng thứ nhất hoặc thứ tám, làm giảm khả năng cho các ô vuông đó xuống còn 11. Điều đó làm giảm các bảng có thể có xuống 11 16 x 13 48 = 1,35e70 (xấp xỉ), yêu cầu 233 bit không gian lưu trữ.

Trên thực tế, mã hóa và giải mã các giá trị như vậy sang và từ thập phân (hoặc nhị phân) phức tạp hơn một chút nhưng nó có thể được thực hiện một cách đáng tin cậy và được để lại như một bài tập cho người đọc.

Bảng chữ cái có chiều rộng biến đổi

Cả hai phương pháp trước đều có thể được mô tả là mã hóa chữ cái có độ rộng cố định . Mỗi thành viên trong số 11, 13 hoặc 16 của bảng chữ cái được thay thế cho một giá trị khác. Mỗi "ký tự" có cùng chiều rộng nhưng hiệu quả có thể được cải thiện khi bạn xem xét rằng mỗi ký tự không có khả năng như nhau.

mã Morse

Hãy xem xét mã Morse (hình trên). Các ký tự trong tin nhắn được mã hóa dưới dạng một chuỗi dấu gạch ngang và dấu chấm. Những dấu gạch ngang và dấu chấm đó được chuyển qua radio (thông thường) với một khoảng dừng giữa chúng để phân tách chúng.

Lưu ý rằng chữ E ( chữ cái phổ biến nhất trong tiếng Anh ) là một dấu chấm đơn, chuỗi ngắn nhất có thể, trong khi chữ Z (ít thường xuyên nhất) là hai dấu gạch ngang và hai tiếng bíp.

Một sơ đồ như vậy có thể làm giảm đáng kể kích thước của một thông báo mong đợi nhưng phải trả giá bằng việc tăng kích thước của một chuỗi ký tự ngẫu nhiên.

Cần lưu ý rằng mã Morse có một tính năng sẵn có khác: dấu gạch ngang dài bằng dấu ba chấm vì vậy đoạn mã trên được tạo ra nhằm mục đích giảm thiểu việc sử dụng dấu gạch ngang. Vì 1s và 0s (khối xây dựng của chúng tôi) không có vấn đề này, nó không phải là một tính năng mà chúng tôi cần tái tạo.

Cuối cùng, có hai loại phần còn lại trong mã Morse. Phần còn lại ngắn (độ dài của dấu chấm) được dùng để phân biệt giữa dấu chấm và dấu gạch ngang. Khoảng cách dài hơn (độ dài của dấu gạch ngang) được sử dụng để phân cách các ký tự.

Vậy điều này áp dụng cho vấn đề của chúng ta như thế nào?

Mã hóa Huffman

Có một thuật toán để xử lý các mã có độ dài thay đổi được gọi là mã hóa Huffman . Mã hóa Huffman tạo ra sự thay thế mã có độ dài thay đổi, thường sử dụng tần suất dự kiến ​​của các ký hiệu để gán các giá trị ngắn hơn cho các ký hiệu phổ biến hơn.

Cây mã Huffman

Trong cây trên, chữ E được mã hóa là 000 (hoặc trái-trái-trái) và S là 1011. Cần rõ rằng lược đồ mã hóa này là rõ ràng .

Đây là một điểm khác biệt quan trọng với mã Morse. Mã Morse có dấu phân tách ký tự để nó có thể thay thế không rõ ràng (ví dụ: 4 dấu chấm có thể là H hoặc 2 Is) nhưng chúng ta chỉ có 1s và 0 nên chúng ta chọn một sự thay thế rõ ràng để thay thế.

Dưới đây là một cách thực hiện đơn giản:

private static class Node {
  private final Node left;
  private final Node right;
  private final String label;
  private final int weight;

  private Node(String label, int weight) {
    this.left = null;
    this.right = null;
    this.label = label;
    this.weight = weight;
  }

  public Node(Node left, Node right) {
    this.left = left;
    this.right = right;
    label = "";
    weight = left.weight + right.weight;
  }

  public boolean isLeaf() { return left == null && right == null; }

  public Node getLeft() { return left; }

  public Node getRight() { return right; }

  public String getLabel() { return label; }

  public int getWeight() { return weight; }
}

với dữ liệu tĩnh:

private final static List<string> COLOURS;
private final static Map<string, integer> WEIGHTS;

static {
  List<string> list = new ArrayList<string>();
  list.add("White");
  list.add("Black");
  COLOURS = Collections.unmodifiableList(list);
  Map<string, integer> map = new HashMap<string, integer>();
  for (String colour : COLOURS) {
    map.put(colour + " " + "King", 1);
    map.put(colour + " " + "Queen";, 1);
    map.put(colour + " " + "Rook", 2);
    map.put(colour + " " + "Knight", 2);
    map.put(colour + " " + "Bishop";, 2);
    map.put(colour + " " + "Pawn", 8);
  }
  map.put("Empty", 32);
  WEIGHTS = Collections.unmodifiableMap(map);
}

và:

private static class WeightComparator implements Comparator<node> {
  @Override
  public int compare(Node o1, Node o2) {
    if (o1.getWeight() == o2.getWeight()) {
      return 0;
    } else {
      return o1.getWeight() < o2.getWeight() ? -1 : 1;
    }
  }
}

private static class PathComparator implements Comparator<string> {
  @Override
  public int compare(String o1, String o2) {
    if (o1 == null) {
      return o2 == null ? 0 : -1;
    } else if (o2 == null) {
      return 1;
    } else {
      int length1 = o1.length();
      int length2 = o2.length();
      if (length1 == length2) {
        return o1.compareTo(o2);
      } else {
        return length1 < length2 ? -1 : 1;
      }
    }
  }
}

public static void main(String args[]) {
  PriorityQueue<node> queue = new PriorityQueue<node>(WEIGHTS.size(),
      new WeightComparator());
  for (Map.Entry<string, integer> entry : WEIGHTS.entrySet()) {
    queue.add(new Node(entry.getKey(), entry.getValue()));
  }
  while (queue.size() > 1) {
    Node first = queue.poll();
    Node second = queue.poll();
    queue.add(new Node(first, second));
  }
  Map<string, node> nodes = new TreeMap<string, node>(new PathComparator());
  addLeaves(nodes, queue.peek(), &quot;&quot;);
  for (Map.Entry<string, node> entry : nodes.entrySet()) {
    System.out.printf("%s %s%n", entry.getKey(), entry.getValue().getLabel());
  }
}

public static void addLeaves(Map<string, node> nodes, Node node, String prefix) {
  if (node != null) {
    addLeaves(nodes, node.getLeft(), prefix + "0");
    addLeaves(nodes, node.getRight(), prefix + "1");
    if (node.isLeaf()) {
      nodes.put(prefix, node);
    }
  }
}

Một đầu ra có thể là:

         White    Black
Empty          0 
Pawn       110      100
Rook     11111    11110
Knight   10110    10101
Bishop   10100    11100
Queen   111010   111011
King    101110   101111

Đối với vị trí bắt đầu, điều này tương đương với 32 x 1 + 16 x 3 + 12 x 5 + 4 x 6 = 164 bit.

Sự khác biệt của trạng thái

Một cách tiếp cận khả thi khác là kết hợp cách tiếp cận đầu tiên với mã hóa Huffman. Điều này dựa trên giả định rằng các Bàn cờ được mong đợi nhất (chứ không phải là những bàn cờ được tạo ngẫu nhiên) có nhiều khả năng không giống như vị trí ban đầu.

Vì vậy, những gì bạn làm là XOR vị trí bảng hiện tại 256 bit với vị trí bắt đầu 256 bit và sau đó mã hóa vị trí đó (sử dụng mã hóa Huffman hoặc, giả sử, một số phương pháp mã hóa độ dài chạy ). Rõ ràng điều này sẽ rất hiệu quả khi bắt đầu (64 0 có thể tương ứng với 64 bit) nhưng tăng dung lượng lưu trữ cần thiết khi trò chơi tiến triển.

Vị trí mảnh

Như đã đề cập, một cách khác để tấn công vấn đề này là thay vào đó lưu trữ vị trí của từng quân cờ mà người chơi có. Điều này đặc biệt hiệu quả với các vị trí cuối trò chơi nơi hầu hết các ô vuông sẽ trống (nhưng trong phương pháp mã hóa Huffman, các ô trống chỉ sử dụng 1 bit dù sao).

Mỗi bên sẽ có một quân vua và 0-15 quân cờ khác. Do quảng cáo, cấu tạo chính xác của những mảnh đó có thể khác nhau đến mức bạn không thể giả định các con số dựa trên vị trí bắt đầu là cực đại.

Cách hợp lý để phân chia điều này là lưu trữ một Vị trí bao gồm hai Mặt (Trắng và Đen). Mỗi bên có:

  • A vua: 6 bit cho vị trí;
  • Có các con tốt: 1 (có), 0 (không);
  • Nếu có, số con tốt: 3 bit (0-7 + 1 = 1-8);
  • Nếu có, vị trí của mỗi con tốt được mã hóa: 45 bit (xem bên dưới);
  • Số lượng không phải con tốt: 4 bit (0-15);
  • Đối với mỗi phần: nhập (2 bit cho quân hậu, quân, kỵ sĩ, giám mục) và vị trí (6 bit)

Đối với vị trí cầm đồ, các con tốt chỉ có thể nằm trên 48 ô vuông khả thi (không phải 64 ô như những ô khác). Do đó, tốt hơn là không nên lãng phí 16 giá trị bổ sung mà việc sử dụng 6 bit cho mỗi con tốt sẽ sử dụng. Vì vậy, nếu bạn có 8 con tốt, thì có 48 8 khả năng, bằng 28.179.280.429.056. Bạn cần 45 bit để mã hóa nhiều giá trị đó.

Đó là 105 bit mỗi bên hoặc tổng số 210 bit. Tuy nhiên, vị trí bắt đầu là trường hợp xấu nhất đối với phương pháp này và nó sẽ tốt hơn đáng kể khi bạn loại bỏ các mảnh.

Cần chỉ ra rằng có ít hơn 48 8 khả năng bởi vì tất cả các con tốt không thể nằm trong cùng một hình vuông. Đầu tiên có 48 khả năng, thứ hai 47, v.v. 48 x 47 x… x 41 = 1,52e13 = 44 bit lưu trữ.

Bạn có thể cải thiện điều này hơn nữa bằng cách loại bỏ các ô vuông bị chiếm bởi các quân khác (bao gồm cả mặt còn lại) để trước tiên bạn có thể đặt các con tốt không trắng rồi đến các con không đen, sau đó là các con trắng và cuối cùng là các con đen. Ở vị trí bắt đầu, điều này làm giảm yêu cầu lưu trữ xuống 44 bit cho Trắng và 42 bit cho Đen.

Các phương pháp kết hợp

Một cách tối ưu khác có thể xảy ra là mỗi cách tiếp cận này đều có điểm mạnh và điểm yếu. Chẳng hạn, bạn có thể chọn 4 tốt nhất và sau đó mã hóa bộ chọn lược đồ trong hai bit đầu tiên và sau đó là bộ lưu trữ dành riêng cho lược đồ sau đó.

Với chi phí nhỏ như vậy, đây sẽ là cách tiếp cận tốt nhất.

Trạng thái trò chơi

Tôi quay lại vấn đề lưu trữ trò chơi hơn là vị trí . Bởi vì sự lặp lại ba lần, chúng tôi phải lưu trữ danh sách các nước đi đã xảy ra cho đến thời điểm này.

Chú thích

Một điều bạn phải xác định là bạn đang lưu trữ một danh sách các nước đi hay bạn đang chú thích trò chơi? Các trò chơi cờ vua thường được chú thích, ví dụ:

  1. Bb5 !! Nc4?

Nước đi của Trắng được đánh dấu bằng hai dấu chấm than là tuyệt vời trong khi của Đen được coi là một sai lầm. Xem Dấu câu cờ vua .

Ngoài ra, bạn cũng có thể cần lưu trữ văn bản miễn phí khi các bước di chuyển được mô tả.

Tôi giả định rằng các bước di chuyển là đủ nên sẽ không có chú thích.

Ký hiệu đại số

Chúng tôi chỉ cần lưu trữ văn bản của việc di chuyển ở đây (“e4”, “Bxb5”, v.v.). Bao gồm một byte kết thúc mà bạn đang nhìn vào khoảng 6 byte (48 bit) mỗi lần di chuyển (trường hợp xấu nhất). Điều đó không đặc biệt hiệu quả.

Điều thứ hai cần thử là lưu trữ vị trí bắt đầu (6 bit) và vị trí kết thúc (6 bit) sao cho 12 bit mỗi lần di chuyển. Điều đó tốt hơn đáng kể.

Ngoài ra, chúng tôi có thể xác định tất cả các động thái hợp pháp từ vị trí hiện tại theo cách và trạng thái có thể dự đoán và xác định được mà chúng tôi đã chọn. Điều này sau đó quay trở lại mã hóa cơ sở biến được đề cập ở trên. Trắng và Đen có 20 nước đi có thể có ở mỗi nước đi đầu tiên, nhiều hơn ở nước đi thứ hai, v.v.

Phần kết luận

Không có câu trả lời hoàn toàn đúng cho câu hỏi này. Có nhiều cách tiếp cận khả thi, trong đó những cách trên chỉ là một số.

Điều tôi thích về vấn đề này và các vấn đề tương tự là nó đòi hỏi những khả năng quan trọng đối với bất kỳ lập trình viên nào như xem xét kiểu sử dụng, xác định chính xác các yêu cầu và suy nghĩ về các trường hợp góc.

Vị trí cờ vua được chụp dưới dạng ảnh chụp màn hình từ Nhà huấn luyện vị trí cờ vua .


3
và gzip kết quả sau đó (nếu tiêu đề không làm tăng kết quả); ^)
Toad

Bạn sẽ không cần phải tăng gấp đôi khoảng trắng để biểu thị Đen hoặc Trắng?
Daniel Elliott

5
Bài tốt. Chỉnh sửa nhỏ: nhập thành yêu cầu 4 bit, một bit cho mỗi cách nhập thành (trắng và đen, mặt vua và mặt nữ), vì các con ngựa có thể đã di chuyển và sau đó cũng di chuyển trở lại. Quan trọng hơn một chút: bạn có thể nên bao gồm nước đi của ai. =)
A. Rex

9
Đối với việc thăng cấp lên một hiệp sĩ, tôi đã làm điều đó một lần. Tình hình thực sự hoang dã - anh ấy đã di chuyển một trong những động thái từ việc giao phối với tôi, tôi không thể ngăn chặn nó. Anh ta đã bỏ qua con tốt của tôi bởi vì trong khi nó sẽ phát huy, nó sẽ chậm một bước. Thay vào đó, tôi ước mình có máy ảnh của mình khi thăng cấp thành hiệp sĩ và giao phối với anh ta!
Loren Pechtel

2
Tôi rất ngạc nhiên khi bài viết của bạn không đề cập đến [FEN] [1], xử lý quá trình nhập thành, tính khả dụng của người qua đường, v.v. [1] en.wikipedia.org/wiki/FEN
Ross

48

Tốt nhất chỉ nên lưu trữ các trò chơi cờ vua ở định dạng chuẩn, có thể đọc được.

Các Máy game Notation giả định một vị trí bắt đầu tiêu chuẩn (mặc dù nó không phải ) và chỉ cần liệt kê các di chuyển, bật bởi sự thay đổi. Một định dạng tiêu chuẩn, nhỏ gọn, có thể đọc được.

Ví dụ

[Event "F/S Return Match"]
[Site "Belgrade, Serbia Yugoslavia|JUG"]
[Date "1992.11.04"]
[Round "29"]
[White "Fischer, Robert J."]
[Black "Spassky, Boris V."]
[Result "1/2-1/2"]

1. e4 e5 2. Nf3 Nc6 3. Bb5 {This opening is called the Ruy Lopez.} 3... a6
4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. c3 O-O 9. h3 Nb8  10. d4 Nbd7
11. c4 c6 12. cxb5 axb5 13. Nc3 Bb7 14. Bg5 b4 15. Nb1 h6 16. Bh4 c5 17. dxe5
Nxe4 18. Bxe7 Qxe7 19. exd6 Qf6 20. Nbd2 Nxd6 21. Nc4 Nxc4 22. Bxc4 Nb6
23. Ne5 Rae8 24. Bxf7+ Rxf7 25. Nxf7 Rxe1+ 26. Qxe1 Kxf7 27. Qe3 Qg5 28. Qxg5
hxg5 29. b3 Ke6 30. a3 Kd6 31. axb4 cxb4 32. Ra5 Nd5 33. f3 Bc8 34. Kf2 Bf5
35. Ra7 g6 36. Ra6+ Kc5 37. Ke1 Nf4 38. g3 Nxh3 39. Kd2 Kb5 40. Rd6 Kc5 41. Ra6
Nf2 42. g4 Bd3 43. Re6 1/2-1/2

Nếu bạn muốn làm cho nó nhỏ hơn, thì chỉ cần nén nó lại . Công việc hoàn thành!


23
Để bảo vệ tôi trước 2 phiếu phản đối mà điều này nhận được: 1) Nó làm những gì bạn muốn 2) Nó vượt qua bài kiểm tra thedailywtf.com/articles/riddle-me-an-interview.aspx : "... một số người có thể giải quyết những câu đố này chính xác là kiểu người mà bạn không muốn làm lập trình viên. Bạn có muốn làm việc với anh chàng chế tạo chiếc cân / sà lan có độ dịch chuyển trên mặt nước, taxi chiếc 747 đến bến tàu, rồi cân chiếc máy bay phản lực jumbo bằng cách sử dụng nó, thay vì chỉ gọi Boeing ngay từ đầu? " Bạn không thuê ai đó phát minh cho bạn một bảng mã ngẫu nhiên trong cuộc phỏng vấn, bởi vì họ cũng sẽ làm điều đó trong mã của họ.
Rob Grant

1
Vâng, nếu Tôi đặc biệt yêu cầu họ giải quyết một vấn đề để có được kỹ thuật giải quyết vấn đề của họ, sau đó bạn có thể giả định tôi sẽ giới thiệu các công cụ khác với câu hỏi khác ...
Andrew Rollings

7
@reinier: Tôi không nói rằng tôi hoàn toàn không biết gì về các vấn đề mật độ thông tin (bạn đã chẩn đoán nhầm câu trả lời của tôi là thừa nhận sự kém cỏi). Chắc chắn bạn muốn thuê người viết mã cho một tiêu chuẩn lưu trữ dữ liệu hiện có và người nhận ra rằng việc sử dụng các công cụ hiện có phù hợp thay vì tự mình thực hiện có thể là một ý tưởng hay - "Chúng tôi đã phát minh ra The Wheel 2.0! Giờ đây nó thậm chí còn tròn trịa hơn!" Bạn chắc chắn không muốn thuê một người nghĩ rằng - một cách kỳ lạ - rằng việc sử dụng các chức năng thư viện là một dấu hiệu của sự yếu kém.
Rob Grant

18
Đây hoàn toàn sẽ là câu trả lời đầu tiên của tôi cho câu hỏi này trong một cuộc phỏng vấn. Bạn muốn thể hiện rằng bản năng đầu tiên của bạn là tìm kiếm một giải pháp sẵn sàng. Nếu người phỏng vấn nói với bạn rằng họ muốn nghe những gì bạn có thể tự mình đưa ra, thì bạn có thể chuyển sang giải pháp đóng gói một chút.
Bill the Lizard

2
Tôi đồng hành cùng Robert về vấn đề này - giải pháp hiện có là thực tế, con người có thể đọc được và đủ nhỏ gọn. Tất cả đều là những kỳ công CHÍNH so với giải pháp siêu đóng gói tùy chỉnh với các thuật toán phức tạp để giải mã chúng. Nếu đó là về cuộc phỏng vấn, tôi chắc chắn cũng sẽ xem xét khía cạnh thực tế! Bạn sẽ ngạc nhiên khi biết bao nhiêu lần những người thực sự thông minh nghĩ ra những giải pháp phi thực tế quá phức tạp. Nó thường được cho là do họ có thể xử lý sự phức tạp trong đầu, nhưng sau đó - còn phần còn lại của chúng ta thì sao ...
MaR

15

Câu đố tuyệt vời!

Tôi thấy rằng hầu hết mọi người đang lưu trữ vị trí của mỗi mảnh. Làm thế nào về việc thực hiện một cách tiếp cận đơn giản hơn và lưu trữ nội dung của mỗi ô vuông ? Điều đó sẽ chăm sóc quảng cáo và các quân cờ bắt được tự động.

Và nó cho phép mã hóa Huffman . Trên thực tế, tần suất ban đầu của các quân cờ trên bảng là gần như hoàn hảo cho điều này: một nửa số ô vuông là trống, một nửa số ô vuông còn lại là con tốt, vân vân.

Xem xét tần suất xuất hiện của mỗi phần, tôi đã xây dựng một cây Huffman trên giấy, điều này tôi sẽ không nhắc lại ở đây. Kết quả, trong đó cđại diện cho màu (trắng = 0, đen = 1):

  • 0 cho các ô trống
  • 1c0 để cầm đồ
  • 1c100 cho rook
  • 1c101 cho hiệp sĩ
  • 1c110 cho giám mục
  • 1c1110 cho nữ hoàng
  • 1c1111 cho vua

Đối với toàn bộ hội đồng quản trị trong tình huống ban đầu, chúng tôi có

  • hình vuông trống: 32 * 1 bit = 32 bit
  • con tốt: 16 * 3 bit = 48 bit
  • rooks / knights / bishops: 12 * 5 bit = 60 bit
  • nữ hoàng / vua: 4 * 6 bit = 24 bit

Tổng cộng: 164 bit cho trạng thái ban đầu . Ít hơn đáng kể so với 235 bit của câu trả lời được bình chọn cao nhất hiện nay. Và nó sẽ chỉ nhỏ hơn khi trò chơi tiến triển (ngoại trừ sau khi được khuyến mại).

Tôi chỉ nhìn vào vị trí của các quân cờ trên bảng; trạng thái bổ sung (người đến lượt, người đã nhập thành, người vượt qua, di chuyển lặp lại, v.v.) sẽ phải được mã hóa riêng. Có thể nhiều nhất là 16 bit khác, vì vậy 180 bit cho toàn bộ trạng thái trò chơi. Các tối ưu hóa có thể có:

  • Bỏ những mảnh ít thường xuyên hơn và cất giữ vị trí của chúng riêng biệt. Nhưng điều đó sẽ không giúp ích gì ... việc thay thế vua và hoàng hậu bằng một hình vuông trống sẽ tiết kiệm được 5 bit, đó chính xác là 5 bit bạn cần để mã hóa vị trí của chúng theo một cách khác.
  • "Không có con tốt ở hàng sau" có thể dễ dàng được mã hóa bằng cách sử dụng một bảng Huffman khác cho các hàng phía sau, nhưng tôi nghi ngờ nó sẽ giúp ích nhiều. Bạn có thể vẫn sẽ kết thúc với cùng một cây Huffman.
  • "Một giám mục trắng, một giám mục đen" có thể được mã hóa bằng cách giới thiệu các ký hiệu phụ không có cbit, sau đó có thể được suy ra từ hình vuông mà giám mục trên đó. (Những con tốt được thăng chức làm giám mục phá vỡ kế hoạch này ...)
  • Sự lặp lại của các ô trống có thể được mã hóa theo thời gian dài bằng cách giới thiệu các ký hiệu bổ sung, chẳng hạn như "2 ô trống liên tiếp" và "4 ô trống liên tiếp". Nhưng không dễ để ước tính tần suất của chúng, và nếu bạn làm sai, nó sẽ gây tổn thương hơn là giúp ích.

Không có con tốt nào trong xếp hạng ngân hàng tiết kiệm được một chút - bạn có thể cắt bit # 3 trong số tất cả các mẫu khác. Vì vậy, bạn sẽ tiết kiệm được một bit trên mỗi mảnh thực tế trên xếp hạng ngân hàng.
Loren Pechtel

2
Bạn có thể tạo một cây Huffman riêng biệt cho từng ô trong số 64 ô vuông, vì một số có thể có một số mảnh thường xuyên hơn những ô khác.
Claudiu

9

Phương pháp tiếp cận bảng tra cứu thực sự lớn

Vị trí - 18 byte
Số lượng vị trí hợp pháp ước tính là 10 43
Chỉ cần liệt kê tất cả chúng và vị trí có thể được lưu trữ chỉ trong 143 bit. Cần thêm 1 bit để cho biết bên nào sẽ chơi tiếp theo

Tất nhiên, việc liệt kê là không thực tế, nhưng điều này cho thấy rằng cần ít nhất 144 bit.

Di chuyển - 1 byte
Thường có khoảng 30-40 nước đi hợp pháp cho mỗi vị trí nhưng con số có thể cao đến 218 Hãy liệt kê tất cả các nước đi hợp pháp cho mỗi vị trí. Giờ đây, mỗi bước di chuyển có thể được mã hóa thành một byte.

Chúng tôi vẫn còn nhiều chỗ cho các động thái đặc biệt như 0xFF để đại diện cho việc từ chức.


3
Đi thẳng vào trọng tâm của yêu cầu "cách tiết kiệm không gian nhất mà bạn có thể nghĩ ra để mã hóa trạng thái của một trò chơi cờ vua" - Không gì tốt hơn để lấy thứ gì đó ngoài một cuốn từ điển, và trong đó bao gồm cả một con ruồi.
Andrew

1
Tôi đã tìm thấy một liên kết thú vị về việc mất bao lâu để tạo một từ điển như vậy :) ioannis.virtualcomposer2000.com/math/EveryChess.html
Andrew Rollings

Ước tính của Shannons hơi lỗi thời :-) Anh ấy không bao gồm các chương trình khuyến mãi hay chụp ảnh, điều này đã thổi bay con số lên một khoản kha khá. Giới hạn trên của 5x10 ^ 52 được đưa ra bởi Victor Allis 1994.
Gunther Piez

Chắc chắn với một mã hóa độ dài thay đổi chỉ có giá trị trung bình ít nhất là 10 ^ 43? Một mã hóa thiên về nhiều vị trí hơn phải giảm điều này, đặc biệt là nhiều vị trí là không thể.
Phil H

Các liên kết EveryChess tại là 'để bán', liên kết archive.org: web.archive.org/web/20120303094654/http://...
oPless

4

Nó sẽ thêm sự quan tâm để tối ưu hóa kích thước trường hợp trung bình cho các trò chơi điển hình do con người chơi, thay vì trường hợp xấu nhất. (Tuyên bố vấn đề không nói rõ điều gì; hầu hết các câu trả lời đều giả định trường hợp xấu nhất.)

Đối với trình tự di chuyển, có một bộ máy cờ vua tốt tạo ra các nước đi từ mỗi vị trí; nó sẽ tạo ra một danh sách k có thể di chuyển, được sắp xếp theo thứ hạng về chất lượng của chúng. Mọi người thường chọn nước đi tốt thường xuyên hơn nước đi ngẫu nhiên, vì vậy chúng ta cần tìm hiểu ánh xạ từ mỗi vị trí trong danh sách đến xác suất mọi người chọn nước đi 'tốt'. Sử dụng các xác suất này (dựa trên kho các trò chơi từ một số cơ sở dữ liệu cờ vua trên internet), mã hóa các nước đi bằng mã số học . (Bộ giải mã phải sử dụng cùng một công cụ cờ vua và ánh xạ.)

Đối với vị trí xuất phát, cách tiếp cận của ralu sẽ hiệu quả. Chúng tôi cũng có thể tinh chỉnh nó bằng mã số học ở đó, nếu chúng tôi có một số cách để cân các lựa chọn theo xác suất - ví dụ: các mảnh thường xuất hiện trong các cấu hình bảo vệ nhau, không phải ngẫu nhiên. Thật khó để thấy một cách dễ dàng để kết hợp kiến ​​thức đó. Một ý tưởng: hãy quay lại mã hóa di chuyển ở trên, bắt đầu từ vị trí mở tiêu chuẩn và tìm một chuỗi kết thúc trong bảng mong muốn. (Bạn có thể thử tìm kiếm A * với khoảng cách heuristic bằng tổng khoảng cách của các quân từ vị trí cuối cùng của chúng hoặc một cái gì đó dọc theo các đường đó.) hiểu biết.

Cũng rất khó để ước tính số tiền tiết kiệm được mà điều này sẽ mua cho bạn trong trường hợp phức tạp trung bình mà không thu thập một số thống kê từ một kho dữ liệu thực tế. Nhưng điểm bắt đầu với tất cả các bước di chuyển đều có thể xảy ra như nhau, tôi nghĩ rằng sẽ đánh bại hầu hết các đề xuất ở đây: mã hóa số học không cần số nguyên bit cho mỗi lần di chuyển.


Độ linh hoạt để lưu trữ thông tin này vào nhóm là O (n), hãy kiểm tra câu trả lời đã chỉnh sửa của tôi.
Luka Rahne

ralu, tôi không chắc bạn đang nói gì, nhưng nếu bạn muốn biểu diễn một chuỗi các bước di chuyển sử dụng không gian tối ưu trong trường hợp xấu nhất, thì tôi không mâu thuẫn với điều đó. Ý tưởng ở đây là tận dụng lợi thế của một số động thái có khả năng xảy ra hơn những động thái khác.
Darius Bacon

Tất cả những gì bạn cần để tìm các vị trí có nhiều điểm thích hợp hơn là sử dụng công cụ cờ vua xác định (và mạnh) để sắp xếp nước đi có thể sử dụng theo cách xác định vị trí nhất định.
Luka Rahne

4

Tấn công một vấn đề con về mã hóa các bước sau khi vị trí ban đầu đã được mã hóa. Cách tiếp cận là tạo một "danh sách liên kết" các bước.

Mỗi bước trong trò chơi được mã hóa thành cặp "vị trí cũ-> vị trí mới". Bạn biết vị trí ban đầu khi bắt đầu ván cờ; bằng cách lướt qua danh sách các bước được liên kết, bạn có thể đến trạng thái sau khi X di chuyển.

Để mã hóa từng bước, bạn cần 64 giá trị để mã hóa vị trí bắt đầu (6 bit cho 64 ô vuông trên bảng - 8x8 ô vuông) và 6 bit cho vị trí kết thúc. 16 bit cho 1 lần di chuyển của mỗi bên.

Khi đó, lượng không gian mã hóa một trò chơi nhất định sẽ tương ứng với số lần di chuyển:

10 x (số lần đi trắng + số lần di chuyển màu đen) bit.

CẬP NHẬT: phức tạp tiềm ẩn với những con tốt được thăng cấp. Cần có khả năng nêu rõ những gì mà cầm đồ được quảng cáo - có thể cần các bit đặc biệt (sẽ sử dụng mã màu xám cho việc này để tiết kiệm dung lượng, vì quảng cáo cầm đồ là cực kỳ hiếm).

CẬP NHẬT 2: Bạn không phải mã hóa toàn bộ tọa độ của vị trí cuối. Trong hầu hết các trường hợp, mảnh được di chuyển có thể di chuyển đến không quá X vị trí. Ví dụ, một con tốt có thể có tối đa 3 lựa chọn di chuyển tại bất kỳ điểm nào đã cho. Bằng cách nhận ra rằng số lần di chuyển tối đa cho mỗi loại mảnh, chúng ta có thể tiết kiệm các bit trên mã hóa của "đích".

Pawn: 
   - 2 options for movement (e2e3 or e2e4) + 2 options for taking = 4 options to encode
   - 12 options for promotions - 4 promotions (knight, biship, rook, queen) times 3 squares (because you can take a piece on the last row and promote the pawn at the same time)
   - Total of 16 options, 4 bits
Knight: 8 options, 3 bits
Bishop: 4 bits
Rook: 4 bits
King: 3 bits
Queen: 5 bits

Vì vậy, sự phức tạp về không gian cho mỗi lần di chuyển của màu đen hoặc trắng trở thành

6 bit cho vị trí ban đầu + (số lượng bit thay đổi dựa trên loại vật được di chuyển).


Vừa được cập nhật, ý tôi là 128 kết hợp - rõ ràng là ít hơn 128 bit :) :)
Alex Weinstein

1
Một trạng thái trò chơi không giống như một nước đi. Bất kỳ vị trí nhất định nào cũng có thể được coi là đỉnh hoặc nút, và một nước đi hợp pháp có thể được coi là một cạnh hoặc mũi tên có hướng, tạo thành một đồ thị (xoay chiều có hướng).
Shaggy Frog

Tôi không chắc tại sao lại bỏ phiếu tiêu cực - Tôi muốn nghe ý kiến ​​của mọi người về ý tưởng được cập nhật.
Alex Weinstein

1
Điều này không ảnh hưởng đến suy luận của bạn, nhưng có một sự điều chỉnh nhỏ: một con tốt có thể có 4 nước đi không bao gồm thăng hạng hoặc 12 nước đi bao gồm cả thăng hạng. Ví dụ cầm đồ tại e2: e3, e4, exd3, exf3. Ví dụ cầm đồ tại e7: e8Q, e8N, e8R, e8B, exd8Q, exd8N, exd8R, exd8B, exf8Q, exf8N, exf8R, exf8B.
A. Rex

1
Một vấn đề nhỏ - 5 bit chỉ mã hóa 32 giá trị. Để chỉ định bất kỳ ô vuông nào trên bảng, bạn cần 6 bit.
Chris Dodd

4

Tôi đã nhìn thấy câu hỏi này đêm qua và nó khiến tôi tò mò nên tôi ngồi trên giường để nghĩ ra giải pháp. Câu trả lời cuối cùng của tôi khá giống với int3 thực sự.

Giải pháp cơ bản

Giả sử một trò chơi cờ tiêu chuẩn và bạn không mã hóa các quy tắc (như Trắng luôn đi trước), thì bạn có thể tiết kiệm rất nhiều bằng cách mã hóa các nước đi mà mỗi quân cờ thực hiện.

Tổng cộng có 32 quân cờ nhưng ở mỗi nước đi bạn biết màu gì đang di chuyển nên chỉ cần lo lắng về 16 ô vuông, đó là 4 bit cho quân cờ nào di chuyển trong lượt này.

Mỗi quân cờ chỉ có một bộ di chuyển giới hạn, bạn sẽ liệt kê theo một cách nào đó.

  • Cầm đồ: 4 tùy chọn, 2 bit (1 bước tiến, 2 bước tiến, 1 đường chéo)
  • Rook: 14 tùy chọn, 4 bit (tối đa 7 ở mỗi hướng)
  • Bishop: 13 tùy chọn, 4 bit (nếu bạn có 7 trong một đường chéo, bạn chỉ có 6 trong đường chéo kia)
  • Hiệp sĩ: 8 tùy chọn, 3 bit
  • Nữ hoàng: 27 tùy chọn, 5 bit (Rook + Bishop)
  • Vua: 9 tùy chọn, 4 bit (8 bước di chuyển một bước, cộng với tùy chọn nhập thành)

Để thăng hạng, có 4 quân cờ để lựa chọn (Rook, Bishop, Knight, Queen) vì vậy ở bước di chuyển đó, chúng tôi sẽ thêm 2 bit để chỉ định điều đó. Tôi nghĩ rằng tất cả các quy tắc khác được bao phủ tự động (ví dụ: en passant).

Tối ưu hóa hơn nữa

Đầu tiên, sau khi 8 mảnh một màu đã được bắt, bạn có thể giảm mã hóa mảnh xuống 3 bit, sau đó 2 bit cho 4 mảnh, v.v.

Tuy nhiên, tối ưu hóa chính là chỉ liệt kê các bước di chuyển có thể có tại mỗi điểm trong trò chơi. Giả sử chúng ta lưu trữ các nước đi của quân Tốt như {00, 01, 10, 11}tiến 1 bước, tiến 2 bước, chéo trái và chéo phải tương ứng. Nếu không thể thực hiện một số bước di chuyển, chúng tôi có thể xóa chúng khỏi bảng mã cho lượt này.

Chúng tôi biết trạng thái trò chơi ở mọi giai đoạn (từ việc theo dõi tất cả các bước di chuyển), vì vậy sau khi đọc quân cờ nào sẽ di chuyển, chúng tôi luôn có thể xác định xem mình cần đọc bao nhiêu bit. Nếu chúng ta nhận ra các bước di chuyển duy nhất của một con tốt tại thời điểm này là bắt chéo phải hoặc di chuyển về phía trước, chúng ta biết chỉ đọc 1 bit.

Tóm lại, lưu trữ bit được liệt kê ở trên cho mỗi phần chỉ là tối đa . Gần như mọi động thái sẽ có ít lựa chọn hơn và thường ít bit hơn.


4

Tại mỗi vị trí nhận được số tất cả các bước di chuyển có thể.

động thái tiếp theo được tạo như

index_current_move =n % num_of_moves //this is best space efficiency
n=n/num_of_moves

Hiệu quả không gian tốt nhất cho phép để lưu trữ trò chơi được tạo ngẫu nhiên và cần trung bình khoảng 5 bit / lần di chuyển vì bạn có thể có 30-40 lần di chuyển. Việc lắp ráp lưu trữ chỉ tạo ra n theo thứ tự ngược lại.

Vị trí lưu trữ khó bị phá vỡ hơn, vì dư thừa lớn. (Có thể có tối đa 9 quân hậu trên bảng cho một trang web nhưng trong trường hợp đó không có quân tốt và quân hậu nếu trên bàn cờ nằm ​​trên các ô vuông có màu đối lập nhau) nhưng nói chung giống như lưu trữ kết hợp các quân cờ giống nhau trên các ô vuông còn lại.)

BIÊN TẬP:

Điểm trong việc lưu nước đi là chỉ lưu trữ chỉ số của nước đi. Thay vì lưu trữ Kc1-c2 và cố gắng giảm bớt thông tin này, chúng ta chỉ nên thêm chỉ mục di chuyển được tạo từ bộ phát di chuyển xác định (vị trí)

Ở mỗi lần di chuyển, chúng tôi thêm thông tin về kích thước

num_of_moves = get_number_of_possible_moves(postion) ;

trong nhóm và con số này không thể giảm

tạo ra nguồn thông tin là

n=n*num_of_moves+ index_current_move

thêm

Nếu chỉ có một nước đi ở vị trí cuối cùng, hãy lưu thành số nước đi bắt buộc đã thực hiện trước đó. Ví dụ: nếu vị trí bắt đầu có 1 nước đi bắt buộc cho mỗi bên (2 nước đi) và chúng ta muốn lưu nó dưới dạng một trò chơi di chuyển, hãy lưu trữ 1 trong nhóm n.

ví dụ về lưu trữ vào nhóm thông tin

Giả sử rằng chúng ta đã biết vị trí xuất phát và chúng ta thực hiện 3 bước di chuyển.

Ở nước đi đầu tiên có 5 nước đi và chúng ta lấy chỉ số nước đi 4. Ở nước đi thứ hai có 6 nước đi và chúng ta lấy chỉ số vị trí 3 và ở nước đi thứ 3, có 7 nước đi cho bên đó và anh ta chọn chỉ số di chuyển. 2.

Dạng vectơ; index = [4,3,2] n_moves = [5,6,7]

Chúng tôi đang mã hóa thông tin này ngược lại, vì vậy n = 4 + 5 * (3 + 6 * (2)) = 79 (không cần nhân với 7)

Làm thế nào để mở khóa này? Đầu tiên, chúng tôi có vị trí và chúng tôi phát hiện ra rằng có 5 nước đi. Vì thế

index=79%5=4
n=79/5=15; //no remainder

Chúng tôi lấy chỉ số di chuyển 4 và kiểm tra lại vị trí và từ thời điểm này, chúng tôi phát hiện ra rằng có 6 chuyển động có thể xảy ra.

index=15%6=3
n=15/6=2

Và chúng tôi lấy chỉ số di chuyển 3 đưa chúng tôi đến vị trí có 7 nước đi có thể.

index=2%7=2
n=2/7=0

Chúng tôi thực hiện bước cuối cùng chỉ số 2 và chúng tôi đạt được vị trí cuối cùng.

Như bạn có thể thấy độ phức tạp về thời gian là O (n), độ phức tạp của không gian là O (n). Chỉnh sửa: độ phức tạp thời gian thực sự là O (n ^ 2) vì số bạn nhân lên tăng lên, nhưng sẽ không có vấn đề gì khi lưu trữ trò chơi lên đến 10.000 lần di chuyển.


tiết kiệm vị trí

Có thể được thực hiện gần với mức tối ưu.

Khi chúng tôi tìm hiểu về thông tin và lưu trữ thông tin, hãy để tôi nói thêm về nó. Ý tưởng chung là giảm dư thừa (tôi sẽ nói về điều đó sau). Giả sử rằng không có thăng cấp và không có lấy để có 8 quân tốt, 2 xe, 2 kỵ sĩ, 2 giám mục 1 vua và 1 nữ hoàng mỗi bên.

Chúng ta phải tiết kiệm những gì: 1. vị trí của mỗi hòa bình 2. vị trí của việc nhập thành 3. khả năng của kẻ xâm nhập 4. bên đã di chuyển sẵn sàng

Giả sử rằng mọi mảnh có thể đứng ở bất cứ đâu nhưng không thể có 2 mảnh ở cùng một vị trí. Số cách sắp xếp 8 con tốt cùng màu trên bàn cờ là C (64/8) (nhị thức) là 32 bit, sau đó là 2 ô rô 2R-> C (56/2), 2B -> C (54/2) , 2N-> C (52/2), 1Q-> C (50/1), 1K -> C (49/1) và tương tự cho trang web khác nhưng bắt đầu bằng 8P -> C (48/8), v.v. .

Nhân số này với nhau cho cả hai trang web sẽ cho chúng tôi số 4634726695587809641192045982323285670400000 xấp xỉ 142 bit, chúng tôi phải thêm 8 cho một en-passant có thể có (con tốt en-passant có thể ở một trong 8 vị trí), 16 (4 bit) cho các hạn chế nhập và một bit cho trang web đã di chuyển. Chúng tôi kết thúc với 142 + 3 + 4 + 1 = 150bits

Nhưng bây giờ chúng ta hãy tiếp tục tìm kiếm dư thừa trên bàn cờ với 32 mảnh và không lấy.

  1. cả hai con tốt đen và trắng đều nằm trên cùng một cột và đối mặt với nhau. Mỗi con tốt đối mặt với con tốt khác có nghĩa là con tốt nhất có thể đứng ở hạng 6. Điều này mang lại cho chúng ta 8 * C (6/2) thay vì C (64/8) * C (48/8) làm giảm thông tin đi 56 bit.

  2. khả năng nhập thành cũng là thừa. Nếu xe không ở vị trí bắt đầu thì không có khả năng nhập thành xe đó. Vì vậy, chúng ta có thể tưởng tượng thêm 4 ô vuông trên tàu để có thêm thông tin nếu có thể nhập thành chiếc xe này và loại bỏ 4 bit nhập thành. Vì vậy, thay vì C (56/2) * C (40/2) * 16, chúng tôi có C (58/2) * C (42/2) và chúng tôi mất 3,76 bit (gần như tất cả 4 bit)

  3. en-passant: Khi chúng ta lưu trữ một trong 8 en passant Possibilite, chúng ta biết vị trí của con tốt đen và giảm khả năng chuyển hướng thông tin (nếu đó là nước đi trắng và có con tốt thứ 3 có nghĩa là con tốt màu đen ở c5 và con tốt màu trắng là c2, c3 hoặc c4) như vậy thêm vào C (6/2), chúng tôi có 3 và chúng tôi mất 2,3 bit. Chúng tôi giảm bớt một số dư thừa nếu chúng tôi lưu trữ số en-passant bất kỳ mà từ đó có thể thực hiện được (3 khả năng-> trái, phải, cả hai) và chúng tôi biết khả năng cầm đồ có thể lấy en passant. (ví dụ: từ ví dụ trước en passant màu đen trên c5, những gì có thể ở bên trái, bên phải hoặc cả hai. Nếu nó ở trên một trang web, chúng tôi có 2 * 3 (3 để lưu trữ psissibilite và 2 di chuyển có thể cho quân đen ở hạng 7 hoặc 6 ) được thêm vào C (6/2) và chúng tôi giảm 1,3 bit và nếu ở cả hai phía, chúng tôi giảm 4,2 bit. Bằng cách đó chúng tôi có thể giảm 2,3 + 1,3 = 3.

  4. giám mục: bisops chỉ có thể ở trên ô vuông opostite, điều này làm giảm độ dư thừa đi 1 bit cho mỗi trang web.

Nếu tính tổng, chúng ta cần 150-56-4-3.6-2 = 85bits để lưu giữ vị trí cờ vua nếu không có số điểm

Và có lẽ không nhiều hơn nữa nếu có các khoản thu và khuyến mãi được tính đến (nhưng tôi sẽ viết về điều đó sau nếu ai đó sẽ thấy bài đăng dài này hữu ích)


Cách tiếp cận thú vị. Thêm một số chi tiết :)
Andrew Rollings

Tôi cũng đã thêm aproach để lưu vị trí. Tôi đã giảm xuống 85bits trên các vị trí mà không cần lấy và là một sự phấn khích tốt cho biết có thể đi bao xa. Tôi nghĩ rằng ý tưởng tốt nhất là tiết kiệm khả năng nhập thành nơi hầu như tất cả 4 bit tắt là dư thừa.
Luka Rahne

3

Hầu hết mọi người đã mã hóa trạng thái hội đồng quản trị, nhưng liên quan đến bản thân các động thái .. Đây là mô tả mã hóa bit.

Số bit trên mỗi mảnh:

  • Piece-ID: Tối đa 4 bit để xác định 16 mảnh mỗi bên. Trắng / đen có thể được suy ra. Có một thứ tự được xác định trên các mảnh. Khi số lượng mảnh giảm xuống dưới lũy thừa tương ứng của hai, hãy sử dụng ít bit hơn để mô tả các mảnh còn lại.
  • Tốt: 3 khả năng ở nước đi đầu tiên, vì vậy +2 bit (chuyển tiếp một hoặc hai ô vuông, vi phạm.) Các nước đi tiếp theo không cho phép di chuyển tiếp hai, vì vậy bit +1 là đủ. Sự thăng hạng có thể được suy ra trong quá trình giải mã bằng cách lưu ý khi nào con tốt đạt thứ hạng cuối cùng. Nếu con tốt được biết là được thăng hạng, bộ giải mã sẽ mong đợi 2 bit khác cho biết quân cờ chính nào trong số 4 quân cờ đã được thăng hạng.
  • Bishop: +1 bit cho đường chéo được sử dụng, Tối đa +4 bit cho khoảng cách dọc theo đường chéo (16 khả năng). Bộ giải mã có thể suy ra khoảng cách tối đa có thể mà mảnh có thể di chuyển dọc theo đường chéo đó, vì vậy nếu đó là đường chéo ngắn hơn, hãy sử dụng ít bit hơn.
  • Hiệp sĩ: 8 bước di chuyển có thể, +3 bit
  • Rook: +1 bit cho ngang / dọc, +4 bit cho khoảng cách dọc theo đường.
  • Vua: 8 bước đi có thể, +3 bit. Chỉ ra việc nhập thành với một nước đi 'không thể' - vì việc nhập thành chỉ có thể thực hiện được khi vua đang ở hạng nhất, hãy mã hóa nước đi này bằng một chỉ dẫn để di chuyển vua 'lùi' - tức là ra khỏi bàn cờ.
  • Queen: 8 hướng có thể, + 3bits. Thêm tối đa +4 bit cho khoảng cách dọc theo đường thẳng / đường chéo (ít hơn nếu đường chéo ngắn hơn, như trong trường hợp của giám mục)

Giả sử tất cả các quân cờ đều nằm trên bàn cờ, đây là các bit cho mỗi nước đi: Cầm đồ - 6 bit ở nước đi đầu tiên, 5 bit sau đó. 7 nếu được thăng chức. Bishop: 9 bit (tối đa), Knight: 7, Rook: 9, King: 7, Queen: 11 (tối đa).


32 bit để xác định mảnh ??? Tôi nghĩ bạn có nghĩa là 5 (32 miếng). Hoặc 6 nếu bạn cần mã hóa trạng thái 'kết thúc',
Toad

Một con tốt cũng có thể được thăng cấp thành rook, kỵ sĩ hoặc giám mục. Điều này là phổ biến để tránh Bế tắc, hoặc tránh đối đầu.
Kobi

Điều này không ảnh hưởng đến suy luận của bạn, nhưng có một sự điều chỉnh nhỏ: một con tốt có thể có 4 nước đi không bao gồm thăng hạng hoặc 12 nước đi bao gồm cả thăng hạng. Ví dụ cầm đồ tại e2: e3, e4, exd3, exf3. Ví dụ cầm đồ tại e7: e8Q, e8N, e8R, e8B, exd8Q, exd8N, exd8R, exd8B, exf8Q, exf8N, exf8R, exf8B.
A. Rex

Có lẽ tôi đang đọc sai, nhưng một con tốt không thể thực hiện bước đi đầu tiên của nó. Trên thực tế, bạn không cần ký hiệu "en passant" đặc biệt vì đó là quy tắc của trò chơi - nó sẽ chỉ là một bước di chuyển theo đường chéo. Nước đi đầu tiên là một trong 4 lựa chọn và các nước đi tiếp theo là 3 lựa chọn.
DisgruntledGoat

3

Vấn đề là đưa ra một mã hóa hiệu quả nhất cho các trò chơi cờ vua điển hình hay một mã hóa có mã hóa trường hợp xấu nhất ngắn nhất?

Đối với cách sau, cách hiệu quả nhất cũng không rõ ràng nhất: tạo bảng liệt kê tất cả các cặp có thể có (bàn ban đầu, chuỗi nước đi hợp pháp), với vị trí hòa-ba-lần-lặp lại và không nhiều hơn -fifty-move kể từ quy tắc cầm đồ-di chuyển hoặc bắt lần cuối, là đệ quy. Sau đó, chỉ mục của một vị trí trong chuỗi hữu hạn này cung cấp mã hóa trường hợp xấu nhất ngắn nhất, nhưng cũng và mã hóa dài như nhau cho các trường hợp điển hình, và theo tôi, rất tốn kém để tính toán. Trò chơi cờ vua dài nhất có thể được cho là hơn 5000 nước đi, với mỗi người chơi thường có 20-30 nước đi ở mỗi vị trí (mặc dù ít hơn khi chỉ còn ít quân cờ) - điều này mang lại khoảng 40000 bit cần thiết cho mã hóa này.

Ý tưởng liệt kê có thể được áp dụng để đưa ra một giải pháp dễ hiểu hơn, như được mô tả trong gợi ý của Henk Holterman về các bước mã hóa ở trên. Đề xuất của tôi: không tối thiểu, nhưng ngắn hơn các ví dụ ở trên mà tôi đã xem xét và có thể điều chỉnh hợp lý:

  1. 64 bit để biểu thị những ô vuông nào bị chiếm dụng (ma trận chiếm dụng), cộng với danh sách các quân cờ nằm ​​trong mỗi ô vuông bị chiếm đóng (có thể có 3 bit cho các con tốt và 4 bit cho các quân cờ khác): điều này cho 190 bit cho vị trí bắt đầu. Vì không thể có nhiều hơn 32 miếng trên bo mạch, nên việc mã hóa ma trận sử dụng là dư thừa & vì vậy có thể mã hóa một số thứ như các vị trí bảng thông thường, chẳng hạn như 33 bit bộ cộng với chỉ số của bảng từ danh sách bảng thông thường.

  2. 1 chút để nói ai là người đi trước

  3. Các bước di chuyển mã theo gợi ý của Henk: thường là 10 bit cho mỗi cặp nước đi trắng / đen, mặc dù một số nước đi sẽ mất 0 bit, khi người chơi không có nước đi thay thế.

Điều này gợi ý 490 bit để viết mã một trò chơi 30 nước đi điển hình và sẽ là một đại diện hợp lý hiệu quả cho các trò chơi điển hình.

Abouth mã hóa vị trí rút-trên-ba lần-lặp lại và không quá năm mươi lần di chuyển kể từ quy tắc cầm đồ cuối cùng-di chuyển hoặc nắm bắt: nếu bạn mã hóa cột cuối cùng di chuyển trở lại lần di chuyển hoặc bắt giữ cuối cùng, thì bạn có đủ thông tin để quyết định xem các quy tắc này có áp dụng hay không: không cần toàn bộ lịch sử trò chơi.


Giả sử rằng tôi sẽ có nhiều lựa chọn trò chơi và lấy trung bình các kết quả.
Andrew Rollings

3

Vị trí trên bảng có thể được xác định bằng 7 bit (0-63 và 1 giá trị xác định nó không còn trên bảng nữa). Vì vậy, đối với mỗi mảnh trên bảng chỉ định vị trí của nó.

32 miếng * 7 bit = 224 bit

CHỈNH SỬA: như Cadrian đã chỉ ra ... chúng ta cũng có trường hợp 'con tốt được thăng chức thành nữ hoàng'. Tôi đề nghị chúng tôi thêm các bit bổ sung vào cuối để cho biết con tốt nào đã được thăng hạng.

Vì vậy, đối với mỗi con tốt đã được thăng hạng, chúng tôi theo dõi 224 bit với 5 bit cho biết chỉ số của con tốt đã được thăng hạng và 11111 nếu nó là cuối danh sách.

Vì vậy, trường hợp tối thiểu (không có khuyến mại) là 224 bit + 5 (không có khuyến mại). Đối với mỗi cầm đồ được thăng cấp, thêm 5 bit.

CHỈNH SỬA: Như con ếch xù xì đã chỉ ra, chúng tôi cần thêm một bit ở cuối để cho biết đó là lượt của ai; ^)


và gzip kết quả sau đó (nếu tiêu đề không làm tăng kết quả); ^)
Toad

Bạn có thể cải thiện điều đó bằng cách tính đến một số mảnh sẽ không bao giờ được tìm thấy trên một số màu hình vuông nhất định không?
Andrew Rollings

andrew: thực sự thì tôi không thể. Tôi đã quên tính đến một con tốt được thăng cấp thành nữ hoàng (như câu trả lời của cadrian gợi ý). Vì vậy, có vẻ như tôi sẽ thực sự cần thêm một chút nữa
Toad

Tôi có thể thấy cách định nghĩa các giám mục da đen và da trắng cùng nhau. Mặc dù vậy, tôi thắc mắc về các hiệp sĩ ..
int3

1
Bạn đang bỏ lỡ các quảng cáo không dành cho nữ hoàng.
Loren Pechtel

2

Tôi sẽ sử dụng mã hóa thời lượng chạy. Một số mảnh là duy nhất (hoặc chỉ tồn tại hai lần), vì vậy tôi có thể bỏ qua độ dài sau chúng. Giống như cletus, tôi cần 13 trạng thái duy nhất, vì vậy tôi có thể sử dụng một nibble (4 bit) để mã hóa mảnh. Ban đầu sau đó sẽ trông như thế này:

White Rook, W. Knight, W. Bishop, W. Queen, W. King, W. Bishop, W. Knight, W. Rook,
W. Pawn, 8,
Empty, 16, Empty, 16
B. Pawn, 8,
B. Rook, B. Knight, B. Bishop, B. Queen, B. King, B. Bishop, B. Knight, B. Rook

mà để lại cho tôi 8 + 2 + 4 + 2 + 8 nibbles = 24 nibbles = 96 bit. Tôi không thể mã hóa 16 bằng nibble nhưng vì "Empty, 0" không hợp lý nên tôi có thể coi "0" là "16".

Nếu bảng trống nhưng đối với một con tốt ở góc trên bên trái, tôi nhận được "Pawn, 1, Empty, 16, Empty, 16, Empty 16, Empty, 15" = 10 nibbles = 40 bit.

Trường hợp xấu nhất là khi tôi có một hình vuông trống giữa mỗi mảnh. Nhưng đối với mã hóa của mảnh, tôi chỉ cần 13 trong số 16 giá trị, vì vậy có thể tôi có thể sử dụng một giá trị khác để nói "Empty1". Sau đó, tôi cần 64 nibbles == 128bits.

Đối với các chuyển động, tôi cần 3 bit cho mảnh (màu được đưa ra bởi thực tế là màu trắng luôn di chuyển trước) cộng với 5 bit (0..63) cho vị trí mới = một byte cho mỗi chuyển động. Hầu hết thời gian, tôi không cần vị trí cũ vì chỉ có một mảnh duy nhất sẽ nằm trong phạm vi. Đối với trường hợp lẻ, tôi phải sử dụng mã chưa sử dụng duy nhất (tôi chỉ cần 7 mã để mã hóa mảnh) và sau đó là 5 bit cho vị trí cũ và 5 bit cho vị trí mới.

Điều này cho phép tôi mã hóa việc nhập thành trong 13 lần cắn (tôi có thể di chuyển Vua về phía Xe, điều này đủ để nói lên ý định của tôi).

[CHỈNH SỬA] Nếu bạn cho phép một bộ mã hóa thông minh, thì tôi cần 0 bit cho thiết lập ban đầu (vì nó không phải được mã hóa theo bất kỳ cách nào: Nó tĩnh) cộng với một byte cho mỗi lần di chuyển.

[EDIT2] Mà rời khỏi chuyển đổi cầm đồ. Nếu một con tốt đến hàng cuối cùng, tôi có thể di chuyển nó vào vị trí để nói "chuyển đổi" và sau đó thêm 3 bit cho quân cờ mà nó được thay thế (bạn không cần phải sử dụng quân hậu; bạn có thể thay thế con tốt bằng bất cứ thứ gì but the King).


Bộ mã hóa thông minh không thể cho rằng đó là toàn bộ trò chơi. Nó có thể là một phần của một trò chơi. Tôi nghĩ bạn vẫn cần mã hóa các vị trí bắt đầu.
Andrew Rollings

Chà, trong trường hợp xấu nhất, tôi cần 128 bit hoặc, nếu trò chơi vẫn còn ở giai đoạn đầu, tôi có thể sử dụng tối đa 15 bước di chuyển để đưa nó về vị trí bắt đầu = 120 bit.
Aaron Digulla

Vì BẤT KỲ trạng thái nào phải được mã hóa, và không chỉ là trạng thái ban đầu, bạn cũng phải mã hóa chính các phần đó. Vì vậy, bạn sẽ cần ít nhất 5 bit trên mỗi mảnh. Vì vậy, điều này sẽ cung cấp cho bạn thêm ít nhất 32 * 5 bit
Toad

@reiner: Bạn nhầm rồi. Tôi chỉ cần bốn bit cho mỗi mảnh / hình vuông trống. Và tôi đã đề cập điều này trong phần đầu tiên của câu trả lời của mình, vì vậy không có "32 * 5 bit bổ sung". Đối với trạng thái ban đầu, tôi cần 96 bit và đối với bất kỳ trạng thái bắt đầu nào khác, tôi cần tối đa 128 bit.
Aaron Digulla

Aaron: vẫn như bạn nói trường hợp xấu nhất thực sự là trường hợp xấu nhất trong bảng mã này. Sau 3 hoặc 4 lần di chuyển từ bảng bắt đầu, mã hóa của bạn sẽ yêu cầu nhiều bit hơn đáng kể vì bạn đang thêm ngày càng nhiều sản phẩm trống
Toad

2

Cũng giống như họ mã hóa trò chơi trên sách và giấy tờ: mỗi phần có một ký hiệu; Vì đây là một trò chơi "hợp pháp", quân trắng đi trước - không cần mã hóa trắng hoặc đen riêng lẻ, chỉ cần đếm số nước đi để xác định ai đã di chuyển. Ngoài ra, mọi nước đi được mã hóa dưới dạng (đoạn, vị trí kết thúc) trong đó 'vị trí kết thúc' được giảm xuống ít ký hiệu nhất cho phép phân biệt sự không rõ ràng (có thể bằng 0). Độ dài của trò chơi quyết định số lần di chuyển. Người ta cũng có thể mã hóa thời gian bằng phút (kể từ lần di chuyển cuối cùng) ở mỗi bước.

Việc mã hóa mảnh có thể được thực hiện bằng cách gán một ký hiệu cho mỗi (tổng số 32) hoặc bằng cách gán một ký hiệu cho lớp và sử dụng vị trí kết thúc để hiểu mảnh nào đã được di chuyển. Ví dụ, một con tốt có 6 vị trí kết thúc có thể có; nhưng trung bình chỉ có một vài người có sẵn cho nó ở mỗi lượt. Vì vậy, về mặt thống kê, mã hóa theo vị trí kết thúc có thể là tốt nhất cho trường hợp này.

Các mã hóa tương tự được sử dụng cho các chuyến tàu tăng đột biến trong khoa học thần kinh tính toán (AER).

Hạn chế: bạn cần chơi lại toàn bộ trò chơi để có được trạng thái hiện tại và tạo một tập hợp con, giống như duyệt qua một danh sách được liên kết.


Nó có thể chỉ là một mảnh trò chơi. Bạn không thể cho rằng nước đi trắng.
Andrew Rollings

2

Có thể có 64 vị trí bảng, vì vậy bạn cần 6 bit cho mỗi vị trí. Có 32 mảnh ban đầu, vì vậy chúng tôi có tổng số 192 bit cho đến nay, trong đó cứ 6 bit cho biết vị trí của mảnh đã cho. Chúng tôi có thể xác định trước thứ tự các phần xuất hiện, vì vậy chúng tôi không cần phải nói cái nào là cái nào.

Điều gì sẽ xảy ra nếu một mảnh nằm ngoài bảng? Chà, chúng ta có thể đặt một quân cờ vào cùng một vị trí với một quân cờ khác để cho biết rằng nó nằm ngoài bảng, vì nếu không thì điều đó là bất hợp pháp. Nhưng chúng tôi cũng không biết liệu quân cờ đầu tiên có nằm trên bảng hay không. Vì vậy, chúng tôi thêm 5 bit cho biết mảnh nào là mảnh đầu tiên (32 khả năng = 5 bit để đại diện cho mảnh đầu tiên). Sau đó, chúng ta có thể sử dụng vị trí đó cho các phần tiếp theo nằm ngoài bảng. Điều đó đưa chúng tôi đến tổng số 197 bit. Phải có ít nhất một mảnh trên bảng, như vậy mới có hiệu quả.

Sau đó, chúng ta cần một bit để đến lượt nó - đưa chúng ta đến 198 bit .

Còn về khuyến mãi cầm đồ? Chúng ta có thể làm điều đó một cách tồi tệ bằng cách thêm 3 bit cho mỗi con tốt, thêm vào 42 bit. Nhưng sau đó chúng ta có thể nhận thấy rằng hầu hết thời gian, các con tốt không được quảng bá.

Vì vậy, đối với mỗi con tốt trên bàn cờ, bit '0' cho biết nó không được thăng hạng. Nếu một con tốt không có trên bàn cờ thì chúng ta không cần một chút nào cả. Sau đó, chúng ta có thể sử dụng các chuỗi bit có độ dài thay đổi mà anh ta có quảng cáo. Thông thường nó sẽ là nữ hoàng, vì vậy "10" có thể có nghĩa là QUEEN. Sau đó "110" có nghĩa là xe ngựa, "1110" có nghĩa là giám mục, và "1111" có nghĩa là hiệp sĩ.

Trạng thái ban đầu sẽ có 198 + 16 = 214 bit , vì tất cả 16 con tốt đều nằm trên bảng và được giải phóng. Một trò chơi kết thúc với hai con tốt được thăng hạng có thể lấy một thứ gì đó giống như 198 + 4 + 4, nghĩa là 4 con tốt còn sống và không được thăng hạng và 2 con tốt, tổng cộng là 206 bit . Có vẻ khá mạnh mẽ!

===

Mã hóa Huffman, như những người khác đã chỉ ra, sẽ là bước tiếp theo. Nếu bạn quan sát một vài triệu trò chơi, bạn sẽ nhận thấy mỗi phần có nhiều khả năng nằm trên một số hình vuông nhất định. Ví dụ, hầu hết thời gian, các con tốt nằm trên một đường thẳng hoặc một bên trái / một bên phải. Vua thường sẽ bám xung quanh căn cứ nhà.

Do đó, hãy nghĩ ra một lược đồ mã hóa Huffman cho từng vị trí riêng biệt. Các con tốt có thể sẽ chỉ lấy trung bình 3-4 bit thay vì 6. Vua cũng nên lấy ít bit.

Cũng trong lược đồ này, bao gồm "lấy" làm vị trí có thể. Điều này cũng có thể xử lý rất tốt việc nhập thành - mỗi quân và vua sẽ có thêm một trạng thái "vị trí ban đầu, đã di chuyển". Bạn cũng có thể mã hóa en passant trong các chốt theo cách này - "vị trí ban đầu, có thể en passant".

Với đủ dữ liệu, cách tiếp cận này sẽ mang lại kết quả thực sự tốt.


2
Chỉ cần gán các mảnh đã loại bỏ vào cùng một ô vuông với hình vua. Kể từ khi nhà vua không bao giờ có thể được gỡ bỏ nó sẽ không được mơ hồ
John La Rooy

Đó là một nhận xét tốt :) Các khía cạnh tốt cho giải pháp này. Tôi không nhận ra rằng sẽ rất khó để chọn ra một người chiến thắng.
Andrew Rollings

2

Tôi muốn sử dụng mã hóa Huffman . Lý thuyết đằng sau điều này là - trong mỗi ván cờ sẽ có một số quân cờ di chuyển nhiều và một số quân cờ không di chuyển nhiều hoặc bị loại sớm. Nếu vị trí bắt đầu đã được loại bỏ một số mảnh - thì càng tốt. Tương tự đối với hình vuông - một số hình vuông có thể xem tất cả các hành động, trong khi một số hình vuông không bị chạm nhiều.

Vì vậy, tôi có hai bảng Huffman - một cho các mảnh, một cho các hình vuông. Chúng sẽ được tạo ra bằng cách nhìn vào trò chơi thực tế. Tôi có thể có một cái bàn lớn cho mỗi cặp hình vuông, nhưng tôi nghĩ rằng điều đó sẽ khá kém hiệu quả vì không có nhiều trường hợp của cùng một mảnh lại di chuyển trên cùng một hình vuông.

Mỗi phần sẽ có một ID được chỉ định. Vì có 32 mảnh khác nhau, tôi sẽ chỉ cần 5 bit cho ID mảnh. Các ID mảnh không thay đổi từ trò chơi này sang trò chơi khác. Tương tự đối với ID hình vuông, tôi sẽ cần 6 bit.

Các cây Huffman sẽ được mã hóa bằng cách viết ra từng nút khi chúng được duyệt trong inorder (nghĩa là, đầu tiên nút được xuất, sau đó là nút con của nó từ trái sang phải). Đối với mỗi nút sẽ có một bit xác định xem đó là nút lá hay nút nhánh. Nếu đó là một nút lá, nó sẽ được theo sau bởi các bit cung cấp ID.

Vị trí bắt đầu sẽ đơn giản được đưa ra bởi một loạt các cặp vị trí mảnh. Sau đó, sẽ có một cặp vị trí cho mỗi lần di chuyển. Bạn có thể tìm thấy phần cuối của bộ mô tả vị trí bắt đầu (và phần bắt đầu của bộ mô tả di chuyển) đơn giản bằng cách tìm phần đầu tiên được đề cập hai lần. Trong trường hợp một con tốt được thăng hạng, sẽ có thêm 2 bit chỉ định nó trở thành gì, nhưng ID mảnh sẽ không thay đổi.

Để tính đến khả năng một con tốt được thăng hạng khi bắt đầu trò chơi, cũng sẽ có một "bảng thăng hạng" giữa các cây huffman và dữ liệu. Lúc đầu sẽ có 4 bit chỉ định có bao nhiêu con tốt được nâng cấp. Sau đó, đối với mỗi con tốt sẽ có ID được mã hóa huffman của nó và 2 bit chỉ định những gì nó đã trở thành.

Cây huffman sẽ được tạo ra bằng cách tính đến tất cả dữ liệu (cả vị trí xuất phát và các bước di chuyển) và bảng thăng hạng. Mặc dù thông thường bảng khuyến mãi sẽ trống hoặc chỉ có một vài mục nhập.

Để tóm tắt nó trong các thuật ngữ đồ họa:

<Game> := <Pieces huffman tree> <squares huffman tree> <promotion table> <initial position> (<moves> | <1 bit for next move - see Added 2 below>)

<Pieces huffman tree> := <pieces entry 1> <pieces entry 2> ... <pieces entry N>
<pieces entry> := "0" | "1" <5 bits with piece ID>

<squares huffman tree> := <squares entry 1> <squares entry 2> ... <squares entry N>
<Squares entry> := "0" | "1" <6 bits with square ID>

<promotion table> := <4 bits with count of promotions> <promotion 1> <promotion 2> ... <promotion N>
<promotion> := <huffman-encoded piece ID> <2 bits with what it becomes>

<initial position> := <position entry 1> <position entry 2> ... <position entry N>
<moves> := <position entry 1> <position entry 2> ... <position entry N>
<position entry> := <huffman-encoded piece ID> <huffman-encoded squre ID> (<2 bits specifying the upgrade - optional>)

Thêm: Điều này vẫn có thể được tối ưu hóa. Mỗi quân cờ chỉ có một vài chiêu thức hợp pháp. Thay vì chỉ mã hóa ô vuông mục tiêu, người ta có thể cung cấp các ID dựa trên 0 cho các bước di chuyển có thể có của mọi quân cờ. Các ID giống nhau sẽ được sử dụng lại cho mọi quân cờ, vì vậy tổng cộng sẽ có không quá 21 ID khác nhau (quân hậu có thể có nhiều nhất 21 tùy chọn di chuyển có thể khác nhau). Đặt cái này vào bảng huffman thay vì các trường.

Tuy nhiên, điều này sẽ gây khó khăn trong việc thể hiện trạng thái ban đầu. Người ta có thể tạo ra một loạt các bước di chuyển để đặt từng mảnh vào vị trí của nó. Trong trường hợp này, cần phải đánh dấu bằng cách nào đó kết thúc trạng thái ban đầu và bắt đầu các bước di chuyển.

Ngoài ra, chúng có thể được đặt bằng cách sử dụng ID vuông 6 bit không nén.

Liệu điều này có làm giảm kích thước tổng thể hay không - tôi không biết. Có thể, nhưng nên thử nghiệm một chút.

Thêm 2: Thêm một trường hợp đặc biệt. Nếu trạng thái trò chơi KHÔNG có nước đi, điều quan trọng là phải phân biệt ai đi tiếp. Thêm một chút nữa vào cuối cho điều đó. :)


2

[đã chỉnh sửa sau khi đọc đúng câu hỏi] Nếu bạn cho rằng mọi vị trí hợp pháp đều có thể đạt được từ vị trí ban đầu (đó là định nghĩa có thể có của "pháp lý"), thì bất kỳ vị trí nào cũng có thể được biểu thị dưới dạng chuỗi các bước di chuyển ngay từ đầu. Một đoạn chơi bắt đầu từ một vị trí không chuẩn có thể được biểu thị bằng chuỗi các bước di chuyển cần thiết để đến điểm bắt đầu, một công tắc để bật máy ảnh, tiếp theo là các bước di chuyển tiếp theo.

Vì vậy, chúng ta hãy gọi trạng thái bảng ban đầu là bit đơn "0".

Các chuyển động từ bất kỳ vị trí nào có thể được liệt kê bằng cách đánh số các ô vuông và sắp xếp các di chuyển theo (bắt đầu, kết thúc), với bước nhảy 2 ô vuông thông thường cho biết nhập thành. Không cần phải mã hóa các nước đi bất hợp pháp, vì vị trí bàn cờ và các quy tắc luôn được biết trước. Cờ để bật máy ảnh có thể được biểu thị như một số di chuyển trong dải đặc biệt hoặc hợp lý hơn là một số di chuyển ngoài dải.

Có 24 bước mở cho mỗi bên, mỗi bên có thể vừa với 5 bit. Các bước di chuyển tiếp theo có thể yêu cầu nhiều hơn hoặc ít hơn các bit, nhưng các bước di chuyển hợp pháp luôn có thể đếm được, vì vậy chiều rộng của mỗi bước đi có thể tăng lên hoặc mở rộng một cách vui vẻ. Tôi chưa tính toán, nhưng tôi tưởng tượng vị trí 7 bit sẽ rất hiếm.

Sử dụng hệ thống này, một trò chơi 100 hiệp có thể được mã hóa trong khoảng 500 bit. Tuy nhiên, có thể là khôn ngoan nếu sử dụng một cuốn sách mở đầu. Giả sử nó chứa một triệu chuỗi. Khi đó, số 0 đầu tiên cho biết bắt đầu từ bảng tiêu chuẩn và số 1 theo sau là số 20 bit cho biết bắt đầu từ chuỗi mở đầu đó. Các trò chơi có cách mở hơi thông thường có thể được rút ngắn bằng 20 hiệp, hoặc 100 bit.

Đây không phải là cách nén lớn nhất có thể, nhưng (không có sách mở đầu) sẽ rất dễ thực hiện nếu bạn đã có một mô hình cờ vua, mà câu hỏi giả định.

Để nén thêm, bạn muốn sắp xếp các bước di chuyển theo khả năng xảy ra hơn là theo thứ tự tùy ý và mã hóa các trình tự có thể xảy ra trong ít bit hơn (ví dụ: sử dụng mã thông báo Huffman như mọi người đã đề cập).


Vị trí ban đầu không nhất thiết phải biết. Nó có thể là một mảnh trò chơi.
Andrew Rollings

@Andrew: vâng. lỗi của tôi. Tôi đã chỉnh sửa để cho phép các mảnh trò chơi.
Douglas Bagnall

2

Nếu thời gian tính toán không phải là vấn đề thì bạn có thể sử dụng trình tạo vị trí có thể xác định để gán các id duy nhất cho một vị trí nhất định.

Từ một vị trí nhất định, đầu tiên tạo ra một số vị trí có thể có trong một trang viên xác định, ví dụ như bắt đầu từ dưới bên trái chuyển sang trên cùng bên phải. Điều đó xác định bạn sẽ cần bao nhiêu bit cho lần di chuyển tiếp theo, một số trường hợp có thể chỉ là một. Sau đó, khi di chuyển được thực hiện, chỉ cần lưu trữ id duy nhất cho di chuyển đó.

Khuyến mãi và các quy tắc khác chỉ đơn giản được tính là nước đi hợp lệ miễn là chúng được xử lý theo cách xác định, ví dụ như đi hậu, đi ô, về quân từng được tính là một nước đi riêng biệt.

Vị trí ban đầu là khó nhất và có thể tạo ra khoảng 250 triệu vị trí có thể (tôi nghĩ), điều này sẽ yêu cầu khoảng 28 bit cộng thêm một bit để xác định nước đi của ai.

Giả sử chúng ta biết ai đến lượt (mỗi lượt chuyển từ trắng sang đen), trình tạo xác định sẽ trông giống như sau:

for each row
    for each column
        add to list ( get list of possible moves( current piece, players turn) )

'lấy danh sách các động thái khả thi' sẽ làm một cái gì đó như:

if current piece is not null 
    if current piece color is the same as the players turn
        switch( current piece type )
            king - return list of possible king moves( current piece )
            queen - return list of possible queen moves( current piece )
            rook - return list of possible rook moves( current piece )
            etc.

Nếu nhà vua đang bị kiểm tra thì mỗi 'danh sách các nước đi xxx có thể xảy ra' chỉ trả về các nước đi hợp lệ làm thay đổi tình hình séc.


Đó là một giải pháp lén lút ... vì vậy ... trong trường hợp này, hãy mô tả thuật toán của bạn để tạo ra số xác định.
Andrew Rollings

Tôi đã tìm thấy một liên kết thú vị về việc mất bao lâu để tạo mọi vị trí trên bàn cờ :) ioannis.virtualcomposer2000.com/math/EveryChess.html
Andrew Rollings

2

Hầu hết các câu trả lời đều bỏ qua việc lặp lại 3 lần. Thật không may cho việc lặp lại 3 lần, bạn phải lưu trữ tất cả các vị trí đã chơi cho đến nay ...

Câu hỏi yêu cầu chúng tôi lưu trữ theo cách hiệu quả về không gian, vì vậy chúng tôi thực sự không cần lưu trữ vị trí miễn là chúng tôi có thể xây dựng nó từ danh sách di chuyển (miễn là chúng tôi có vị trí bắt đầu tiêu chuẩn). Chúng tôi có thể tối ưu hóa PGN và thế là xong. Dưới đây là một chương trình đơn giản.

Có 64 hình vuông trên bàn cờ, 64 = 2 ^ 6. Nếu chúng ta chỉ lưu trữ hình vuông đầu tiên và cuối cùng của mỗi nước đi sẽ mất 12 bit (Khuyến mãi sẽ được giải quyết sau). Lưu ý rằng chương trình này đã bao gồm người chơi di chuyển, đẩy mạnh, bắt mảnh, nhập thành, v.v.; vì chúng có thể được xây dựng chỉ từ việc phát lại danh sách di chuyển.

để thăng hạng, chúng ta có thể giữ một mảng vectơ riêng biệt có nội dung "ở nước đi N thăng hạng đến Mảnh XYZ". chúng ta có thể giữ một vector của (int, byte).

Cũng rất hấp dẫn để tối ưu hóa vectơ (Tới, Từ), Vì nhiều vectơ (Tới, Từ) này không thể tìm được trong cờ vua. ví dụ. sẽ không có sự di chuyển từ e1 sang d8, vv Nhưng tôi không thể đưa ra bất kỳ kế hoạch nào. Bất kỳ ý tưởng nào khác đều được hoan nghênh nhất.


2

Tôi đã nghĩ về điều đó trong một thời gian dài (+ - 2 giờ). Và không có câu trả lời rõ ràng.

Giả định:

  1. Bỏ qua trạng thái thời gian (Một người chơi không sử dụng giới hạn thời gian, do đó có thể buộc một trận hòa bằng cách không chơi)
  2. Trò chơi được chơi khi nào?!? Điều quan trọng là vì các quy tắc đã thay đổi theo thời gian (vì vậy sẽ cho rằng một trò chơi hiện đại trong thời điểm tiếp theo là một trò chơi hiện đại ...) Hãy tham khảo quy tắc cầm đồ chết chẳng hạn (wikipedia có một vấn đề rất nổi tiếng hiển thị nó), và nếu bạn muốn quay ngược thời gian chúc may mắn Bishop từng chỉ di chuyển chậm và xúc xắc từng được sử dụng. cười lớn.

... vì vậy nó được cập nhật các quy tắc hiện đại. Đầu tiên không phân biệt giới hạn lặp lại và di chuyển.

-C 25 byte được làm tròn (64b + 32 * 4b + 5b = 325b)

= 64 bit (cái gì đó / không có gì) + 32 * 4 bit [1bit = color {black / withe} + 3bit = type of piece {King, Queen, Bishop, kNight, Rook, Pawn, MovedPawn} NB: Đã di chuyển ... ví dụ: nếu nó là con tốt được di chuyển cuối cùng trong lượt trước đó cho thấy rằng 'en passant' là khả thi. ] + 5bit cho trạng thái thực tế (đến lượt ai, người đi qua, khả năng xảy ra hay không ở mỗi bên)

Càng xa càng tốt. Có lẽ có thể được nâng cao nhưng sau đó sẽ có độ dài và sự thăng hạng thay đổi để xem xét !?

Giờ đây, các quy tắc sau đây chỉ được áp dụng KHI người chơi yêu cầu một kết quả hòa, NÓ KHÔNG tự động! Vì vậy, hãy coi 90 nước đi mà không bị bắt hoặc một nước đi tốt là khả thi nếu không có người chơi nào kêu gọi hòa! Có nghĩa là tất cả các động thái cần được ghi lại ... và có sẵn.

-D lặp lại vị trí ... ví dụ trạng thái của hội đồng quản trị như đã đề cập ở trên (xem C) hoặc không ... (xem phần sau liên quan đến các quy tắc FIDE) -E Điều đó khiến vấn đề phức tạp của phụ cấp 50 nước đi mà không bị bắt hoặc cầm đồ di chuyển ở đó a truy cập là cần thiết ... Tuy nhiên.

Vậy làm thế nào để bạn đối phó với điều đó? ... Thực sự là không có cách nào. Vì không người chơi nào có thể muốn rút hoặc nhận ra rằng điều đó đã xảy ra. Bây giờ trong trường hợp E, một bộ đếm có thể là đủ ... nhưng đây là mẹo và thậm chí đọc các quy tắc FIDE (http://www.fide.com/component/handbook/?id=124&view=article) Tôi không thể tìm thấy câu trả lời ... mất khả năng rooking thì sao. Đó có phải là một sự lặp lại? Tôi nghĩ là không, nhưng đây là một chủ đề mù mờ không được giải quyết, không được làm rõ.

Vì vậy, đây là hai quy tắc phức tạp hoặc không xác định ngay cả khi cố gắng mã hóa ... Chúc mừng.

Vì vậy, cách duy nhất để thực sự mã hóa một trò chơi là ghi lại tất cả từ đầu ... mà sau đó xung đột (hay không?) Với câu hỏi "trạng thái bảng".

Hy vọng điều này sẽ giúp đỡ ... không quá nhiều toán học :-) Chỉ để cho thấy rằng một số câu hỏi không phải là dễ dàng, quá mở để giải thích hoặc kiến ​​thức trước là chính xác và hiệu quả. Tôi sẽ không xem xét một trong những cuộc phỏng vấn vì nó mở ra quá nhiều ổ sâu.


2

Có thể cải thiện vị trí bắt đầu trong giải pháp của Yacoby

Không có vị trí hợp pháp nào có nhiều hơn 16 mảnh mỗi màu. Số cách xếp có 16 miếng đen và 16 miếng trắng trên 64 ô vuông là khoảng 3,63e27. Log2 (3,63e27) = 91,55. Điều này có nghĩa là bạn có thể mã hóa vị trí và màu sắc của tất cả các mảnh bằng 92 bit. Con số này ít hơn 64 bit cho vị trí + tối đa 32 bit cho màu mà giải pháp của Yacoby yêu cầu. Bạn có thể tiết kiệm 4 bit trong trường hợp xấu nhất với chi phí phức tạp đáng kể trong mã hóa.

Mặt khác, nó tăng kích thước cho các vị trí thiếu từ 5 mảnh trở lên. Những vị trí này chỉ đại diện cho <4% tất cả các vị trí, nhưng chúng có thể là phần lớn các trường hợp bạn muốn ghi lại vị trí bắt đầu khác với vị trí ban đầu.

Điều này dẫn đến giải pháp hoàn chỉnh

  1. Mã hóa vị trí và màu sắc của các mảnh theo phương pháp trên. 92 bit .
  2. Để chỉ định loại của mỗi quân cờ, hãy sử dụng Mã Huffman: pawn: '0', rook: '100', knight: '101', Bishop: '110', queen: '1110', king: '1111'. Điều này yêu cầu (16 * 1 + 12 * 3 + 4 * 4) = 68 bit cho một tập hợp đầy đủ các mảnh. Vị trí bảng đầy đủ có thể được mã hóa tối đa 92 + 68 = 160 bit .
  3. Trạng thái trò chơi bổ sung được thêm vào: lần lượt: 1 bit, khả năng nhập thành: 4 bit, “en passant” có thể: tối đa 4 bit (1 bit cho biết đó là trường hợp và 3 bit cho biết cái nào). Vị trí bắt đầu được mã hóa trong = 160 + 9 = 169 bit
  4. Đối với danh sách nước đi, hãy liệt kê tất cả các nước đi có thể có cho một vị trí nhất định và lưu trữ vị trí của nước đi trong danh sách. Danh sách các động thái bao gồm tất cả các trường hợp đặc biệt (nhập thành, nhập ngũ và từ chức). Chỉ sử dụng càng nhiều bit càng tốt để lưu trữ vị trí cao nhất. Trung bình nó không được vượt quá 7 bit mỗi nước đi (trung bình 16 quân có thể và 8 di chuyển hợp pháp mỗi quân). Trong một số trường hợp, khi buộc phải di chuyển, nó chỉ yêu cầu 1 bit (di chuyển hoặc từ chức).

1

Có 32 mảnh trên bàn cờ. Mỗi mảnh có một vị trí (một trong 64 ô vuông). Vì vậy, bạn chỉ cần 32 số nguyên dương.

Tôi biết 64 vị trí giữ trong 6 bit nhưng tôi sẽ không làm như vậy. Tôi sẽ giữ lại những phần cuối cùng cho một vài lá cờ (quân cờ bị rơi, quân tốt)


Bạn không cần sử dụng cờ để giữ trạng thái. Bạn có thể cho rằng bộ mã hóa của mình đủ thông minh để "biết các quy tắc". Do đó, nếu một con tốt đột nhiên thay đổi thành quân hậu, điều đó không nhất thiết phải được gắn cờ cụ thể trong bảng mã (trừ khi, tôi cho rằng người chơi đã chọn không thăng hạng).
Andrew Rollings

phải, vì bạn không thể biết bằng vị trí ban đầu của một người cầm đồ nếu người cầm đồ đã được thăng chức hay chưa! Vì vậy, nó như được mã hóa trong thiết lập ban đầu
Toad

À, nhưng tại sao bạn cần biết nếu nó đã được thăng hạng? Nó chỉ là một mảnh. Trạng thái quá khứ sẽ không liên quan trong trường hợp này.
Andrew Rollings

Tôi nghĩ rằng nếu một con tốt vẫn là một con tốt hoặc đã được thăng lên thành nữ hoàng hầu như không có liên quan trong phần còn lại của trò chơi. Nếu bạn không nghĩ vậy, tôi rất muốn chơi một ván cờ với bạn; ^)
Toad

@reinier: Anh ấy khẳng định không liên quan nếu một nữ hoàng hiện tại ban đầu là nữ hoàng hay ban đầu là một con tốt.
A. Rex

1

Câu trả lời của cletus là tốt, nhưng anh ấy cũng quên mã hóa lượt trả lời của ai. Nó là một phần của trạng thái hiện tại và cần thiết nếu bạn đang sử dụng trạng thái đó để thúc đẩy thuật toán tìm kiếm (như dẫn xuất alpha-beta).

Tôi không phải là một kỳ thủ cờ vua, nhưng tôi tin rằng còn một trường hợp khác nữa: có bao nhiêu nước đi đã được lặp lại. Một khi mỗi người chơi thực hiện cùng một nước đi ba lần, trò chơi sẽ hòa, phải không? Nếu vậy, bạn cần lưu thông tin đó ở trạng thái vì sau lần lặp lại thứ ba, trạng thái bây giờ là đầu cuối.


đi theo lộ trình đó, bạn cũng cần thêm thời gian chơi cho cả hai người chơi vì trong một trò chơi cờ vua thực sự, cả hai người chơi chỉ nghĩ tổng cộng 1 hoặc 2 giờ.
Toad

2
Bạn không phải mã hóa các quy tắc trong dữ liệu thực tế. Bạn có thể giả định rằng bản thân bộ mã hóa biết bất kỳ quy tắc nào cần thiết.
Andrew Rollings

Ah .. Tôi đã không tính đến thời gian chơi. Tốt cuộc gọi ... :)
Andrew Rollings

@Andrew Rollings: quy tắc dựa trên trạng thái, như trong, nó chỉ kích hoạt khi một điều kiện tiên quyết nhất định được đáp ứng. Theo dõi trạng thái điều kiện tiên quyết đó cũng là một phần của trạng thái ... tốt. :)
Shaggy Frog

Không liên quan trong trường hợp này. Nếu cần, bộ giải mã có thể kiểm tra trạng thái để xác định người chiến thắng. Hãy nhớ rằng bộ mã hóa / giải mã nhận biết quy tắc. Những thứ duy nhất thực sự cần được mã hóa là lựa chọn của người chơi - bất kỳ thứ gì khác có thể được giả định là bộ mã hóa / giải mã đã biết.
Andrew Rollings

1

Như một số người khác đã đề cập, bạn có thể cho mỗi 32 mảnh, bạn có thể lưu trữ chúng ở ô vuông nào và chúng có trên bảng hay không, điều này cho 32 * (log2 (64) + 1) = 224 bit.

Tuy nhiên, các giám mục chỉ có thể chiếm các ô vuông đen hoặc trắng nên đối với những ô này, bạn chỉ cần log2 (32) bit cho vị trí, cho 28 * 7 + 4 * 6 = 220 bit.

Và vì các con tốt không bắt đầu ở phía sau và chỉ có thể tiến về phía trước, chúng chỉ có thể ở số 56, nên có thể sử dụng giới hạn này để giảm số bit cần thiết cho các con tốt.


các giám mục cũng có thể ra khỏi hội đồng quản trị, vì vậy bạn cần thêm một chút cho những điều đó. Ngoài ra, bạn đang quên về những con tốt được thăng cấp và người sẽ bắt đầu đầu tiên. Tính đến tất cả những điều này về cơ bản bạn sẽ kết thúc với câu trả lời của tôi; ^)
Toad

6 bit cho các giám mục là log2 (32) + 1 = 6, nhưng chắc chắn đây là một câu hỏi phức tạp khi bạn xem xét tất cả các chi tiết :)
Andreas Brinck

Tôi đã suy nghĩ dọc theo những dòng này nhưng nó không giúp ích gì. Nhìn vào câu trả lời của Thomas và sửa đổi mã hóa huffman của anh ấy để xóa bỏ khái niệm về khoảng trống. Bạn sử dụng 64 bit để lưu trữ ma trận mà các ô vuông bị chiếm và bạn xóa 1 bit khỏi mỗi mã hóa - do đó khôi phục chính xác 64 bit giống nhau.
Loren Pechtel

1

Một bảng có 64 ô vuông và có thể được biểu diễn bằng 64 bit cho biết một ô trống hay không. Chúng tôi chỉ cần thông tin mảnh nếu một hình vuông có một mảnh. Vì trình phát + mảnh chiếm 4 bit (như hình trước đó) nên chúng ta có thể nhận được trạng thái hiện tại ở 64 + 4 * 32 = 192 bit. Ném trong lượt hiện tại và bạn có 193 bit.

Tuy nhiên, chúng ta cũng cần mã hóa các bước di chuyển hợp pháp cho mỗi phần. Đầu tiên, chúng tôi tính toán số lần di chuyển hợp pháp cho mỗi phần và thêm nhiều bit đó vào sau số nhận dạng phần của một hình vuông đầy đủ. Tôi tính toán như sau:

Tốt: Chuyển tiếp, đầu tiên chuyển hai về phía trước, vi thụ * 2, thăng cấp = 7 bit. Bạn có thể kết hợp lượt đầu tiên về phía trước và lượt thăng hạng thành một bit duy nhất vì chúng không thể xảy ra từ cùng một vị trí, vì vậy bạn có 6. Xe: 7 hình vuông dọc, 7 hình vuông ngang = 14 bit Hiệp sĩ: 8 hình vuông = 8 bit Bishop: 2 đường chéo * 7 = 14 bit Nữ hoàng: 7 dọc, 7 ngang, 7 chéo, 7 chéo = 28 bit Vua: 8 hình vuông xung quanh

Điều này vẫn có nghĩa là bạn sẽ cần lập bản đồ các ô vuông được nhắm mục tiêu dựa trên vị trí hiện tại, nhưng nó (nên) là một phép tính đơn giản.

Vì chúng ta có 16 quân tốt, 4 quân / kỵ sĩ / giám mục và 2 quân hậu / vua, đây là 16 * 6 + 4 * 14 + 4 * 8 + 4 * 14 + 2 * 28 + 2 * 8 = 312 bit nữa, mang lại tổng số là 505 bit tổng thể.

Đối với số lượng bit cần thiết cho mỗi mảnh để di chuyển có thể, một số tối ưu hóa có thể được thêm vào đó và số lượng bit có thể giảm xuống, tôi chỉ sử dụng các số dễ làm việc. Ví dụ: đối với các mảnh trượt, bạn có thể lưu trữ khoảng cách mà chúng có thể di chuyển, nhưng điều này sẽ yêu cầu tính toán thêm.

Câu chuyện ngắn: Chỉ lưu trữ dữ liệu bổ sung (mảnh, v.v.) khi một hình vuông bị chiếm dụng và chỉ lưu trữ số bit tối thiểu cho mỗi mảnh để thể hiện các nước đi hợp pháp của nó.

EDIT1: Quên về quảng cáo nhập thành và cầm đồ cho bất kỳ phần nào. Điều này có thể nâng tổng số với các vị trí rõ ràng lên 557 lần di chuyển (thêm 3 bit cho quân tốt, 2 cho vua)


1

Mỗi phần có thể được biểu diễn bằng 4 bit (tốt cho vua, 6 loại), đen / trắng = 12 giá trị

Mỗi ô vuông trên bảng có thể được biểu diễn bằng 6 bit (x coord, y coord).

Các vị trí ban đầu yêu cầu tối đa 320 bit (32 miếng, 4 + 6 bit)

Mỗi bước di chuyển tiếp theo có thể được biểu diễn bằng 16 bit (từ vị trí, đến vị trí, mảnh).

Castling sẽ yêu cầu thêm 16 bit, vì đó là một động thái kép.

Các con tốt được xác định có thể được biểu diễn bằng một trong 4 giá trị dự phòng trong số 4 bit.

Nếu không thực hiện các phép toán chi tiết, điều này bắt đầu tiết kiệm không gian sau lần di chuyển đầu tiên so với việc lưu trữ 32 * 7 bit (mảng mảnh được xác định trước) hoặc 64 * 4 bit (phép gán hình vuông được xác định trước)

Sau 10 lần di chuyển cả hai bên, không gian tối đa được yêu cầu là 640 bit

... nhưng sau đó một lần nữa, nếu chúng ta xác định từng phần duy nhất (5 bit) và thêm bit thứ sáu để gắn cờ các con tốt, thì chúng ta chỉ cần mảnh-id + vị trí cho mỗi nước đi. Điều này thay đổi phép tính thành ...

Vị trí ban đầu = tối đa 384 bit (32 mảnh, 6 + 6 bit) Mỗi ​​lần di chuyển = 12 bit (tới vị trí, mảnh-id)

Sau đó, sau 10 lần di chuyển mỗi bên, không gian tối đa cần thiết là 624 bit


Tùy chọn thứ hai có thêm lợi thế là lưu trữ có thể được đọc dưới dạng bản ghi 12 bit, mỗi bản ghi = vị trí và mảnh. Cabin di chuyển đầu tiên được phát hiện bởi thực tế là mảnh đã được nhập trước.
Steve De Caux

cho thời gian giữa các lần di chuyển, thêm x bit cho bộ đếm vào mỗi bản ghi. Đối với các bản ghi thiết lập, điều này sẽ được đặt thành 0.
Steve De Caux

Đây là cách tiếp cận mà tôi sẽ viết ra. Một tối ưu hóa là đối với các trò chơi tiêu chuẩn, bạn không cần phải mã hóa các vị trí ban đầu - một chút ở đầu nói "đây là một trò chơi tiêu chuẩn" là đủ. Ngoài ra, nhập thành không thực hiện hai lần di chuyển - vì một động tác nhập thành luôn hiển nhiên và chỉ có một cách hợp lệ để quân di chuyển khi một vị vua nhất định xảy ra một nửa nhập thành, đó là thông tin thừa. Để thăng hạng, bạn chỉ có thể sử dụng 4 bit sau khi một con tốt di chuyển đến hàng cuối cùng để chỉ định loại quân cờ mới mà nó trở thành.
kyoryu

Vì vậy, đối với một trò chơi điển hình, sau 10 lần di chuyển, bạn sẽ ở mức 121 bit, giả sử không có khuyến mại. Các trò chơi không điển hình sẽ yêu cầu 1 bit cho cờ, quân cờ * 10bits và một bit khác để chỉ người chơi đầu tiên. Ngoài ra, mỗi nước đi sẽ chỉ yêu cầu 12 bit, vì quân cờ trên một hình vuông nhất định là ẩn từ các nước đi trước đó trong trò chơi. Điều này có lẽ kém hiệu quả hơn một số phương pháp được đề xuất, nhưng khá rõ ràng và hiệu quả hợp lý cho các trò chơi "tiêu chuẩn".
kyoryu

@kyoro - Tôi không tin rằng 12 bit mỗi lần di chuyển có thể bị đánh bại - sử dụng ý tưởng của bạn về null cho thiết lập tiêu chuẩn (tôi vẫn sẽ sử dụng 12 bit được đặt thành bin 0) - sau 1000 lần di chuyển trên mỗi bên, đây là 24012 bit aka 3002 byte (làm tròn lên) Thậm chí sử dụng một số hình thức nén bạn cần để lừa để đánh bại này, bằng cách tuyên bố từ điển mã hóa cứng (hoặc logic derivable, điều tương tự) của bạn
Steve De Caux

1

Giống như Robert G, tôi có xu hướng sử dụng PGN vì nó tiêu chuẩn và có thể được sử dụng bởi nhiều loại công cụ.

Tuy nhiên, nếu tôi đang chơi cờ vua AI trên một tàu thăm dò không gian ở xa, và do đó, mọi thứ đều quý giá, thì đây là điều tôi muốn làm cho các nước đi. Tôi sẽ chuyển sang mã hóa trạng thái ban đầu sau.

Các bước di chuyển không cần phải ghi lại trạng thái; bộ giải mã có thể theo dõi trạng thái cũng như những động thái nào là hợp pháp tại bất kỳ thời điểm nào. Tất cả các động thái cần ghi lại là lựa chọn thay thế hợp pháp khác nhau. Vì người chơi luân phiên nên một nước đi không cần ghi lại màu của người chơi. Vì người chơi chỉ có thể di chuyển các mảnh màu của riêng mình, nên lựa chọn đầu tiên là người chơi sẽ di chuyển quân nào (Tôi sẽ quay lại một phương án thay thế sử dụng lựa chọn khác sau). Với tối đa 16 mảnh, điều này yêu cầu tối đa 4 bit. Khi người chơi mất quân cờ, số lượng lựa chọn giảm xuống. Ngoài ra, một trạng thái trò chơi cụ thể có thể giới hạn sự lựa chọn của các quân cờ. Nếu một vị vua không thể di chuyển mà không đặt mình vào vị trí kiểm tra, số lượng lựa chọn sẽ giảm đi một. Nếu vua đang bị kiểm soát, bất kỳ quân cờ nào không thể đưa vua ra khỏi séc không phải là lựa chọn khả thi.

Khi phần được chỉ định, nó sẽ chỉ có một số điểm đến hợp pháp nhất định. Con số chính xác phụ thuộc nhiều vào bố cục bảng và lịch sử trò chơi, nhưng chúng tôi có thể tìm ra các giá trị tối đa và dự kiến ​​nhất định. Đối với tất cả, trừ hiệp sĩ và trong quá trình nhập thành, một mảnh không thể di chuyển qua mảnh khác. Đây sẽ là một nguồn giới hạn di chuyển lớn, nhưng rất khó để định lượng. Một mảnh không thể di chuyển ra khỏi bảng, điều này cũng sẽ hạn chế phần lớn số điểm đến.

Chúng tôi mã hóa điểm đến của hầu hết các mảnh bằng cách đánh số các ô vuông dọc theo các đường theo thứ tự sau: W, NW, N, NE (mặt đen là N). Một dòng bắt đầu trong hình vuông xa nhất theo hướng đã cho hợp pháp để di chuyển đến và tiến về phía. Đối với một vị vua không bị cản trở, danh sách các nước đi là W, E, NW, SE, N, S, NE, SW. Đối với kỵ sĩ, chúng tôi bắt đầu với 2W1N và tiến hành theo chiều kim đồng hồ; đích 0 là điểm đến hợp lệ đầu tiên trong đơn đặt hàng này.

  • Các con tốt: Một con tốt không di chuyển có 2 lựa chọn điểm đến, do đó yêu cầu 1 bit. Nếu một con tốt có thể bắt được một con khác, bình thường hoặc đang bị bắt (mà bộ giải mã có thể xác định, vì nó đang theo dõi trạng thái), nó cũng có 2 hoặc 3 lựa chọn nước đi. Ngoài ra, một người cầm đồ chỉ có thể có 1 lựa chọn, không yêu cầu bit. Khi một con tốt ở hạng thứ 7 , chúng tôi cũng tính đến lựa chọn thăng hạng. Vì những con tốt thường được thăng cấp thành nữ hoàng, theo sau là hiệp sĩ, chúng tôi mã hóa các lựa chọn là:
    • nữ hoàng: 0
    • hiệp sĩ: 10
    • giám mục: 110
    • rook: 111
  • Bishop: nhiều nhất 13 điểm đến khi ở {d, e} {4,5} cho 4 bit.
  • Rook: nhiều nhất 14 điểm đến, 4 bit.
  • Hiệp sĩ: nhiều nhất 8 điểm đến, 3 bit.
  • Kings: Khi nhập thành là một lựa chọn, vua sẽ quay trở lại S và không thể di chuyển xuống dưới; điều này cho tổng cộng 7 điểm đến. Thời gian còn lại, vua có nhiều nhất 8 nước đi, tối đa là 3 bit.
  • Nữ hoàng: Tương tự như các lựa chọn cho giám mục hoặc quân xe, với tổng số 27 lựa chọn, là 5 bit

Vì số lượng sự lựa chọn không phải lúc nào cũng là lũy thừa của hai, phần trên vẫn lãng phí các bit. Giả sử số lựa chọn là C và lựa chọn cụ thể được đánh số c , và n = ceil (lg ( C )) (số bit cần thiết để mã hóa lựa chọn). Chúng tôi sử dụng các giá trị bị lãng phí này bằng cách kiểm tra bit đầu tiên của lựa chọn tiếp theo. Nếu nó là 0, không làm gì cả. Nếu là 1 và c + C <2 n thì thêm C vào c . Giải mã một số đảo ngược điều này: nếu nhận được c > = C , trừ C và đặt bit đầu tiên cho số tiếp theo thành 1. Nếu c<2 n - C , sau đó đặt bit đầu tiên cho số tiếp theo là 0. Nếu 2 n - C <= c < C , thì không làm gì cả. Gọi lược đồ này là "bão hòa".

Một kiểu lựa chọn tiềm năng khác có thể rút ngắn quá trình mã hóa là chọn một mảnh của đối thủ để bắt. Điều này làm tăng số lượng lựa chọn cho phần đầu tiên của nước đi, chọn một mảnh, nhiều nhất là thêm một bit (con số chính xác phụ thuộc vào số lượng quân mà người chơi hiện tại có thể di chuyển). Sự lựa chọn này được theo sau bởi sự lựa chọn của mảnh bắt, có thể nhỏ hơn nhiều so với số lượng nước đi của bất kỳ quân cờ người chơi nào. Một quân chỉ có thể bị tấn công bởi một quân từ bất kỳ hướng chính nào cộng với các hiệp sĩ với tổng số tối đa 10 quân tấn công; điều này cho tổng số tối đa là 9 bit cho một lần di chuyển, mặc dù tôi mong đợi trung bình là 7 bit. Điều này sẽ đặc biệt thuận lợi cho việc bắt giữ của nữ hoàng, vì nó thường sẽ có khá nhiều điểm đến hợp pháp.

Với độ bão hòa, mã hóa chụp có thể không có lợi thế. Chúng tôi có thể cho phép cả hai tùy chọn, chỉ định ở trạng thái ban đầu được sử dụng. Nếu không sử dụng độ bão hòa, mã hóa trò chơi cũng có thể sử dụng các số lựa chọn không được sử dụng ( C <= c <2 n ) để thay đổi các tùy chọn trong trò chơi. Bất kỳ lúc nào C là lũy thừa của hai, chúng tôi không thể thay đổi các tùy chọn.


1

Thomas có cách tiếp cận phù hợp để mã hóa bảng. Tuy nhiên, điều này nên được kết hợp với cách tiếp cận của ralu để lưu trữ các bước di chuyển. Lập danh sách tất cả các bước di chuyển có thể, viết ra số bit cần thiết để thể hiện con số này. Vì bộ giải mã đang thực hiện cùng một phép tính nên nó biết có thể có bao nhiêu bit và có thể biết bao nhiêu bit để đọc, không cần mã độ dài.

Vì vậy, chúng tôi nhận được 164 bit cho các phần, 4 bit cho thông tin nhập thành (giả sử chúng tôi đang lưu trữ một phần của trò chơi, nếu không nó có thể được tạo lại), 3 bit cho thông tin đủ điều kiện của người vượt qua - chỉ cần lưu trữ cột nơi di chuyển xảy ra ( Nếu không thể sử dụng en passant, hãy lưu trữ một cột ở nơi không thể - các cột như vậy phải tồn tại) và 1 cho người sẽ di chuyển.

Các bước di chuyển thường mất 5 hoặc 6 bit nhưng có thể thay đổi từ 1 đến 8.

Một phím tắt bổ sung - nếu mã hóa bắt đầu với 12 bit 1 (trường hợp không hợp lệ - thậm chí không phải một đoạn sẽ có hai vị vua ở một bên) bạn hủy giải mã, xóa sạch bảng và thiết lập một trò chơi mới. Bit tiếp theo sẽ là một chút di chuyển.


1

Thuật toán nên liệt kê một cách xác định tất cả các điểm đến có thể có ở mỗi lần di chuyển. Số điểm đến:

  • 2 giám mục, 13 điểm đến mỗi nơi = 26
  • 2 xe, mỗi xe 14 đích = 28
  • 2 hiệp sĩ, 8 điểm đến mỗi điểm = 16
  • Queen, 27 điểm đến
  • King, 8 điểm đến

8 chân đều có thể trở thành hoàng hậu trong trường hợp xấu nhất (khôn ngoan), do đó làm cho số điểm đến lớn nhất có thể là 9 * 27 + 26 + 28 + 16 + 8 = 321. Do đó, tất cả các điểm đến cho bất kỳ bước di chuyển nào có thể được liệt kê bằng một số 9 bit.

Số nước đi của hai bên tối đa là 100 (nếu tôi không sai, không phải là người chơi cờ). Vì vậy, bất kỳ trò chơi nào cũng có thể được ghi lại trong 900 bit. Cộng với vị trí ban đầu, mỗi mảnh có thể được ghi lại bằng cách sử dụng số 6 bit, tổng cộng là 32 * 6 = 192 bit. Thêm một bit cho bản ghi "ai di chuyển trước". Do đó, bất kỳ trò chơi nào cũng có thể được ghi bằng 900 + 192 + 1 = 1093 bit.


1

Lưu trữ trạng thái hội đồng quản trị

Cách đơn giản nhất mà tôi nghĩ đến là đầu tiên có một mảng 8 * 8 bit đại diện cho vị trí của mỗi quân (Vì vậy, 1 nếu có quân cờ ở đó và 0 nếu không có). Vì đây là độ dài cố định nên chúng ta không cần bất kỳ dấu chấm cuối nào.

Tiếp theo đại diện cho mọi quân cờ theo thứ tự vị trí của nó. Sử dụng 4 bit cho mỗi mảnh, điều này chiếm 32 * 4 bit (tổng cộng là 128). Mà thực sự rất lãng phí.

Sử dụng cây nhị phân, chúng ta có thể đại diện cho một con tốt trong một byte, một hiệp sĩ và quân ngựa và giám mục ở 3 và vua và nữ hoàng trong 4. Vì chúng ta cũng cần lưu trữ màu của mảnh, mất thêm một byte thì nó sẽ kết thúc as (thứ lỗi cho tôi nếu điều này là sai, tôi chưa bao giờ xem xét mã hóa Huffman chi tiết trước đây):

  • Cầm đồ: 2
  • Rook: 4
  • Hiệp sĩ: 4
  • Giám mục: 4
  • Vua: 5
  • Nữ hoàng: 5

Cho tổng số:

2*16 + 4*4 + 4*4 + 4*4 + 2*5 + 2*5 = 100

Nhịp đập bằng cách sử dụng một bộ bit có kích thước cố định là 28 bit.

Vì vậy, phương pháp tốt nhất mà tôi đã tìm thấy là lưu trữ nó trong một mảng 8 2 + 100 bit

8*8 + 100 = 164



Lưu trữ Di chuyển
Điều đầu tiên chúng ta cần biết là mảnh nào đang di chuyển đến đâu. Cho rằng có tối đa 32 mảnh trên bàn cờ và chúng ta biết mỗi mảnh là gì, thay vì một số nguyên đại diện cho hình vuông, chúng ta có thể có một số nguyên đại diện cho phần bù mảnh, có nghĩa là chúng ta chỉ phải lắp 32 giá trị có thể để đại diện cái.

Thật không may, có nhiều quy tắc đặc biệt khác nhau, chẳng hạn như nhập thành hoặc lật đổ nhà vua và thành lập một nước cộng hòa (tham khảo Terry Pratchett), vì vậy trước khi lưu trữ quân cờ để di chuyển, chúng ta cần một chút cho biết đó có phải là nước đi đặc biệt hay không.

Vì vậy, đối với mỗi chuyển động bình thường, chúng ta có một 1 + 5 = 6bit cần thiết . (Loại 1 bit, 5 bit cho mảnh)

Sau khi số mảnh đã được giải mã, chúng ta sẽ biết loại quân và mỗi quân phải đại diện cho nước đi của nó một cách hiệu quả nhất. Ví dụ (Nếu luật chơi cờ vua của tôi là cào) một con tốt có tổng cộng 4 nước đi có thể có (sang trái, sang phải, tiến một bước, tiến hai bước).
Vì vậy, để biểu diễn một nước đi cầm đồ, chúng ta cần các bit '6 + 2 = 8'. (6 bit cho tiêu đề di chuyển ban đầu, 2 bit cho tiêu đề di chuyển)

Di chuyển cho nữ hoàng sẽ phức tạp hơn, trong đó tốt nhất là có một hướng (8 hướng có thể, như vậy 3 bit) và tổng cộng 8 hình vuông có thể di chuyển cho mỗi hướng (vì vậy 3 bit khác). Vì vậy, để biểu diễn việc di chuyển một nữ hoàng, nó sẽ yêu cầu 6 + 3 + 3 = 12các bit.

Điều cuối cùng xảy ra với tôi là chúng ta cần lưu trữ lượt người chơi nào. Đây phải là một bit duy nhất (Trắng hoặc đen để di chuyển tiếp theo)



Định dạng kết quả
Vì vậy, định dạng tệp sẽ giống như thế này

[64 bit] Vị trí mảnh ban đầu
[tối đa 100 bit] Các mảnh ban đầu [1 bit] Lượt người chơi
[n bit] Di chuyển

Nơi di chuyển là
[1 bit] Loại di chuyển (đặc biệt hoặc bình thường)
[n bit] Chi tiết di chuyển

Nếu Di chuyển là một bước di chuyển bình thường, Chi tiết Di chuyển trông giống như
[5 bit] mảnh
[n bit] di chuyển mảnh cụ thể (thường trong phạm vi từ 2 đến 6 bit]

Nếu đó là một nước đi đặc biệt
Nó phải có kiểu số nguyên và sau đó là bất kỳ thông tin bổ sung nào (như nếu nó đang nhập thành). Tôi không thể nhớ số lượng nước đi đặc biệt, vì vậy có thể chỉ cần cho biết đó là nước đi đặc biệt (nếu chỉ có một)


1

Trong trường hợp cơ bản của bảng ban đầu cộng với các nước đi tiếp theo, hãy xem xét những điều sau.

Sử dụng chương trình cờ vua để gán xác suất cho tất cả các nước đi có thể có. Ví dụ: 40% cho e2-e4 20% cho d2-d4, v.v. Nếu một số động thái là hợp pháp nhưng không được chương trình đó xem xét, hãy cho chúng một số xác suất thấp. Sử dụng mã số học để lưu lựa chọn đã được thực hiện, sẽ là một số từ 0 đến 0,4 cho lần di chuyển đầu tiên, 0,4 và 0,6 cho lần thứ hai, v.v.

Lam tương tự cho phia bên kia. Ví dụ: nếu có 50% khả năng e7-e5 là phản ứng với e2-e4 thì số được mã hóa sẽ nằm trong khoảng từ 0 đến 0,2. Lặp lại cho đến khi trò chơi hoàn tất. Kết quả là một phạm vi tiềm năng rất nhỏ. Tìm phân số nhị phân với cơ số nhỏ nhất phù hợp với phạm vi đó. Đó là mã hóa số học.

Điều này tốt hơn Huffman vì nó có thể được coi là mã hóa bit phân đoạn (cộng với một số ở cuối trò chơi để làm tròn thành một bit).

Kết quả phải gọn hơn Huffman, và không có trường hợp đặc biệt nào cho việc thăng hạng, vượt qua, nước đi quy tắc 50 và các chi tiết khác vì chúng được xử lý bởi chương trình đánh giá cờ vua.

Để chơi lại, hãy sử dụng lại chương trình cờ vua để đánh giá bàn cờ và gán tất cả các xác suất cho mỗi nước đi. Sử dụng giá trị được mã hóa số học để xác định nước đi đã thực sự được chơi. Lặp lại cho đến khi hoàn thành.

Nếu chương trình cờ vua của bạn đủ tốt, bạn có thể nén tốt hơn với bộ mã hóa hai trạng thái, nơi xác suất được xác định dựa trên các nước đi cho cả đen và trắng. Trong trường hợp khắc nghiệt nhất là khoảng hơn 200 trạng thái, điều này mã hóa toàn bộ tập hợp tất cả các trò chơi cờ vua có thể có, và do đó không khả thi.

Đây là một cách nói khá khác với những gì Darius đã viết, chỉ với một chút ví dụ về cách mã số học có thể hoạt động và một ví dụ thực tế về việc sử dụng một chương trình cờ vua hiện có để giúp đánh giá xác suất của (các) nước đi tiếp theo.

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.