Giải pháp tốt nhất cho chuỗi cấp độ nghiêm trọng?


10

Tôi có một trò chơi tạo ra một bản đồ cấp ngẫu nhiên khi bắt đầu cấp. Tôi muốn thực hiện một số cách để lưu và tải cấp độ.

Tôi đã nghĩ có lẽ XML sẽ là một lựa chọn tốt để lưu tất cả các biến, sau đó tôi có thể dễ dàng xây dựng một cái gì đó có thể phân tích cú pháp XML đó và tạo ra cùng một mức chính xác.

Nhưng XML có lẽ là quá mức cần thiết cho nhu cầu của tôi. Tôi nhớ lại ngày trước với bảng điều khiển Sega cũ không có khả năng lưu trò chơi của bạn (tôi nghĩ rằng trò chơi Worms cũng vậy), rằng họ sẽ cung cấp cho bạn một loạt các nhân vật mà bạn có thể viết ra. Nếu bạn bấm vào chuỗi đó sau này, nó sẽ tải mức chính xác.

Một "chuỗi cấp độ" sẽ là một lựa chọn tốt? Nó sẽ là một loại chuyển đổi "base60"? Làm thế nào tôi có thể thực hiện điều này?

Câu trả lời:


20

Có lẽ tất cả những gì bạn cần lưu là hạt giống ngẫu nhiên, thường chỉ là một int. Bạn có thể mã hóa int thành base64 nếu bạn muốn làm cho nó mờ hơn một chút, nhưng điều đó có lẽ không cần thiết.


Bạn cũng có thể tạo hạt giống từ một từ thực sự (có thể mua thêm các ký tự để lấy hạt giống của bạn) và theo cách đó trả lại một cái gì đó có ý nghĩa hơn. Bạn sẽ phải lưu trữ các từ trong trò chơi của bạn hoặc lấy chúng mặc dù.
Jonathan Fischoff

Điều đó tốt, nhưng nó cũng sẽ phải lưu trữ dữ liệu động nếu trò chơi đang được chơi. Chuỗi sẽ cần lưu vị trí / điểm của nhân vật, v.v ... Vậy cách tốt nhất để tạo chuỗi này là gì?
Adam Harte

Tôi có thể sẽ sử dụng JSON (hoặc XML nếu bạn muốn) để tuần tự hóa trạng thái thế giới và sau đó mã hóa chuỗi 64. Tuy nhiên, không chắc chắn đó là tất cả những gì hữu ích, tại sao không tạo ra một hệ thống lưu / tải theo định hướng GUI hơn? Tôi giả định rằng đây là dựa trên web và bạn muốn không xử lý phía máy chủ này. Có thể nhìn vào shygypsy.com/farm/p.cgi để biết ví dụ?
coderanger

23

Dù bạn sử dụng định dạng nào cho các trò chơi lưu của mình, vì lợi ích, hãy đặt số phiên bản vào. Bạn sẽ có thể tải ngược tương ứng bằng cách phân nhánh số phiên bản hoặc bạn có thể nhận ra các bản lưu quá cũ một cách an toàn để tải.

Bạn sẽ hối tiếc nếu bạn không.


7
+1 không thực sự trả lời câu hỏi nhưng rất quan trọng.
Jonathan Fischoff

10

JSON là tốt, nhưng YAML là tốt hơn. :) http://www.yaml.org/http://code.google.com.vn/p/yaml-cpp/ cho một trong những triển khai dễ sử dụng hơn.

YAML là một siêu bộ JSON có thêm hỗ trợ cho một vài tính năng hay, đáng chú ý nhất là:

  • Hạch nhị phân. Điều này là tuyệt vời để tuần tự hóa loại dữ liệu bạn có thể xử lý cho các mô tả cấp độ. JSON yêu cầu bạn dịch sang một số định dạng trung gian mà bạn chọn, như Base64, trước khi viết / sau khi phân tích cú pháp. YAML có một loại nút nhị phân !! thông báo cho thư viện trình phân tích cú pháp để làm điều đó cho bạn.
  • Tài liệu tham khảo nội bộ. Nếu cùng một đối tượng xuất hiện hai lần trong tài liệu, JSON sẽ viết nó hai lần và khi bạn đọc lại, bạn sẽ nhận được hai bản sao. Nhiều trình phát YAML có thể phát hiện tình huống này và thay vì bản sao thứ hai, xuất tham chiếu đến bản đầu tiên, khi có thể được phát hiện khi tải.
  • Các loại nút tùy chỉnh. Bạn có thể gắn cờ mỗi bản đồ trong một danh sách với ví dụ: !! Người chơi, !! Kẻ thù, v.v., và vì vậy hãy giữ thông tin loại của bạn ngoài luồng hơn.
  • YAML hỗ trợ định dạng dễ đọc hơn.
  • Vì JSON là tập con của YAML, nên hầu hết người đọc YAML sẽ không gặp khó khăn khi đọc tài liệu JSON.

1
Yaml rất tuyệt, và nếu bạn tránh được một số tính năng của superset, nó có thể được chuyển đổi thành json mà không gặp khó khăn gì.
Jethro Larson

3

Nếu bạn muốn tuần tự hóa tất cả dữ liệu trong trò chơi, tôi muốn giới thiệu JSON làm định dạng tệp của bạn, đó là lý do tại sao sử dụng XML dễ dàng hơn và hỗ trợ rất tốt trên nhiều ngôn ngữ.

Tôi đã sử dụng thư viện này cho C ++ và nó hoạt động rất tốt.

http://jsoncpp.sourceforge.net/


3

XML là một lựa chọn tốt nếu bạn không bị giới hạn bởi kích thước và nó được hỗ trợ nguyên bản (ví dụ: trong .NET và Flash) nhưng nếu bạn muốn định dạng mỏng, bạn có thể tạo định dạng và trình phân tích cú pháp của riêng mình khá dễ dàng. Tôi thường sử dụng 1 ký tự, vd. dấu phẩy để ngăn cách từng đối tượng. Để giải mã chuỗi, hãy phân tách bằng dấu phẩy. Bây giờ mỗi đối tượng cần các thuộc tính khác nhau để phân tách chúng với một ký tự khác nhau, ví dụ: dấu hai chấm và sử dụng một ký tự khác để tách các tên thuộc tính từ các giá trị thuộc tính, ví dụ. Đại tràng. Tất cả do đó có thể được giải mã dễ dàng mà không cần regex chỉ bằng cách sử dụng chuỗi.split. Đây là một ví dụ:

id:1;x:5;y:45.2;angle:45,id:28;x:56;y:89;angle:12;health:78

bạn có thể tiết kiệm nhiều không gian hơn bằng cách giữ tên thuộc tính xuống 1 ký tự, ví dụ: h cho sức khỏe. Ví dụ.

i:1;x:5;y:45.2;a:45,i:28;x:56;y:89;a:12;h:78

So sánh với JSON thay thế:

{"o":[{"i":1, "x":5, "y":45.2, "a":45}, {"i":28, "x":56, "y":89, "a":12, "h":78}]}

Ngoài ra, nếu bạn muốn giảm kích thước số của mình, bạn có thể mã hóa chúng bằng cách sử dụng bộ ký tự UTF16 có thể in đầy đủ. Chủ đề này đã truyền cảm hứng cho tôi để hỏi một câu hỏi về Stack Overflow về số lượng dữ liệu bạn có thể đóng gói thành một nhân vật trên màn hình . Câu trả lời dường như ở đâu đó hơn 40.000 giá trị cho một số nguyên, nếu bạn không phiền khi có các quân cờ, Kanji và cờ vua:

Để giảm kích thước hơn nữa, bạn có thể sử dụng thứ tự đọc / ghi để xác định giá trị nào, vì vậy hai ký tự đầu tiên đại diện cho id, hai ký tự tiếp theo là vị trí x, hai tiếp theo là y, sau đó là góc, sau đó là sức khỏe , v.v.

F5DGP@%&002DFTK#OP1F

có thể lưu trữ tất cả các thông tin giống như các ví dụ khác.

Các ô xếp có thể được lưu trữ dưới dạng một chuỗi với mỗi ký tự đại diện cho một loại ô khác nhau, ví dụ:

i789pog5h3kl

trong đó tôi có thể có nghĩa là dung nham, 9 có nghĩa là cỏ vv


Đây là nhiều hơn những gì tôi đang hỏi. Tôi đề cập đến XML trong câu hỏi của tôi, nhưng mọi người vẫn đề xuất nó!
Adam Harte

1
Thêm {} xung quanh đó và về cơ bản bạn có JSON ;-)
coderanger

Bạn cũng cần thêm một dấu ngoặc kép. Có thể sẽ tăng gấp đôi số ký tự, nhưng bạn sẽ có được các đối tượng lồng nhau.
Iain

1

Nếu bạn đang mã hóa bằng .Net thì XML cực kỳ dễ sử dụng, vì bạn có thể tuần tự hóa / giải tuần tự hóa lớp cấp của bạn thành / ra khỏi XML chỉ bằng một vài dòng, và sau đó tất cả trong một lớp được quản lý độc đáo.

TheMap sẽ là một biến loại Bản đồ mà bạn có tất cả dữ liệu của mình được tải vào.

Dim TheMap As New Map

Giả sử bạn đã xây dựng lớp Bản đồ, điều này sẽ lưu bản đồ của bạn vào XML:

Dim Serializer As New System.Xml.Serialization.XmlSerializer(GetType(TheMap))
Dim Strm As New FileStream("c:\Map.xml", FileMode.Create, FileAccess.Write, FileShare.None)
Serializer.Serialize(Strm, TheMap)
Strm.Close()

Điều này sau đó sẽ tải XML đó trở lại lớp bản đồ của bạn, để được sử dụng lại trong mã.

Dim Reader As New StreamReader("map.xml")
Dim Serializer As New System.Xml.Serialization.XmlSerializer(GetType(TheMap))

TheMap = Serializer.Deserialize(Reader)
Reader.Close()

Từ thời điểm này, tệp XML của bạn hiện được tải vào lớp của bạn để dễ sử dụng.

Đối với vấn đề "Chuỗi cấp độ" của bạn, những gì đã nêu trước đây sẽ hoạt động rất tốt, bạn chỉ có thể sử dụng số Seed làm "Chuỗi cấp độ".

Mặt khác, bạn chỉ có thể tạo trước tuy nhiên nhiều bản đồ khác nhau mà bạn muốn và lưu tất cả chúng bằng "Chuỗi cấp độ" và sau đó sử dụng bản đồ đó để kéo lên bản đồ phù hợp.


+1 ngay cả khi tôi ghét XML - Nếu ngôn ngữ cung cấp định dạng tuần tự hóa mặc định, tốt nhất bạn nên xem xét điều đó trước tiên, đặc biệt nếu đó là định dạng mà các công cụ khác có thể phân tích theo lý thuyết (như XML / JSON / YAML).

0

Tôi sẽ sử dụng một structthiết bị đơn giản hoặc tương tự (tùy thuộc vào ngôn ngữ của bạn) để lưu trữ tất cả trạng thái trò chơi ở vị trí trung tâm. Nếu bạn muốn bảo vệ setters / getters, bạn có thể bọc struct trong a class.

Nếu bạn cảm thấy như vậy, hãy sử dụng bitfield hoặc đơn giản là tự thao tác bit bằng cách sử dụng các toán tử bitwise.

Hãy lưu ý rằng trong một số ngôn ngữ, quy tắc về đệm cấu trúc và đóng gói có thể hơi phức tạp - nhưng nó cũng có thể không quan trọng đối với trường hợp của bạn nếu bạn có một hoặc hai byte đệm.

Bạn cũng có thể sử dụng một #pragma(như#pragma pack(1) ) hoặc một __attribute__gói chặt chẽ cấu trúc, loại bỏ phần đệm. Điều này có thể hoặc có thể không hoạt động tùy thuộc vào trình biên dịch và kiến ​​trúc đích của bạn.

Lưu ý rằng việc sử dụng bitfield và gói pragma hoặc thuộc tính có thể làm giảm tính di động. Trên các kiến ​​trúc phần cứng, độ bền của trường cấu trúc (thứ tự byte) cũng có thể thay đổi. Vì vậy, bạn có thể muốn tránh điều này nếu bạn đang cố gắng cho tính di động.

. dù tối đa là gì.)

Khi bạn đã có cấu trúc của mình, hãy chuyển nó tới một cái gì đó giống như hàm xxencode :

encode_save( char * outStringBuf, size_t outStringBufSize,
             const SaveStruct * inSaveData, size_t inSaveDataSize )

Viết chức năng này là một chút dễ bị lỗi; bạn cần dịch chuyển và kết hợp các byte khi cần thiết để lấy ví dụ 6 bit mỗi lần, sau đó dịch thành một ký tự phù hợp. Cá nhân tôi sẽ cố gắng tìm kiếm mã của người khác, trừ khi tôi đang làm điều này vì "vui vẻ" (và có lẽ tôi muốn có một bộ thử nghiệm cho nó).

Đừng bao giờ đánh giá thấp sức mạnh của trường học cũ structở đúng nơi. Chúng tôi đã sử dụng nó một tấn cho các trò chơi GBA và DS ở đây.


Tuần tự cấu trúc thô là mã mới không di động và cực kỳ dễ vỡ. Trừ khi đó là bước cuối cùng của dữ liệu nướng cho một nền tảng với nguồn lực rất hạn chế, đó là tối ưu hóa rất sớm. Có một lý do bạn thích 6 bit đến 8? Định dạng dù sao cũng không thể đọc được bằng con người, bạn cũng có thể tận dụng tốc độ và khả năng sửa lỗi của bố cục cấu trúc thực.

@Joe: Tôi đã đề cập rằng nó không di động và một số mối quan tâm tiềm năng. Câu hỏi đặc biệt yêu cầu một "chuỗi cấp độ" có thể đọc được của con người như các trò chơi Sega cũ và chuyển đổi cơ sở 60 được đề cập; truyền một cấu trúc thông qua một cái gì đó như xxencode sẽ làm điều này. Đây không nhất thiết là tối ưu hóa sớm: một cấu trúc đơn giản, không phải bitpack, là một cách "trung tâm" độc đáo để lưu trữ dữ liệu và có thể đơn giản hóa phần lớn mã tương tác với dữ liệu. Xem ví dụ các bài viết gần đây của Noel Llopis về các cấu trúc không phải là thành viên và lập trình "từ trong ra ngoài". Đây chỉ là HÔN.
leander

1
Tôi hoàn toàn đồng ý với cách này. Đúng, nó không di động trên các phiên bản, cũng không phải hệ thống, nhưng một lần nữa, trò chơi tiết kiệm không phải là tài nguyên cần được sử dụng lại trong quá trình phát triển hoặc sao chép trên các nền tảng. Khả năng gỡ lỗi hầu như không phải là vấn đề với việc đọc / ghi tại chỗ, thực hiện nó một lần và nó sẽ hoạt động mãi mãi. Khả năng mở rộng của IF thực sự là một vấn đề - thêm số phiên bản là ybyte / word đầu tiên và bạn có thể bật nó (mặc dù điều đó sẽ gây ra lỗ hổng dữ liệu). Không giống như xml sẽ giải quyết các vấn đề về phiên bản - xu hướng liên quan nhiều hơn là chỉ đặt giá trị. Vâng, tôi thực dụng.
Kaj

0

XML tốt cho các tài liệu có cấu trúc tùy ý (các yếu tố có thể xuất hiện ở các cấp độ khác nhau của cây) hoặc nhúng định dạng nước ngoài (như đặt svg vào trang xhtml). Nếu bạn không có những yêu cầu đó thì đó là một định dạng thực sự không hiệu quả, và một cái gì đó đơn giản hơn như csv hoặc json thì tốt hơn.

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.