Giúp bài hướng đối tượng dạng trò chơi giả lập

Bài số 4: Trò chơi Đấu tranh sinh tồn (khuyến khích, không bắt buộc)
Xây dựng một trò chơi giả lập. Trò chơi có dạng lưới, trên lưới có các sinh vật thuộc nhiều loài. Mục đích của chúng là thống trị tất cả các loài khác bằng cách làm các sinh vật thuộc loài khác nhiễm bộ gien của mình, và như vậy trở thành một sinh vật cùng loài.

Tổng quan

Thế giới của trò chơi là một lưới gồm các ô vuông, trên đó có một số sinh vật. Mỗi sinh vật sống trong ô vuông của mình, hướng về một trong 4 hướng Đông, Tây, Nam, Bắc, và thuộc một về một loài vật nào đó, thuộc loài nào thì có kiểu hành vi của loài đó.

Tại mỗi bước của quá trình mô phỏng, mỗi sinh vật lần lượt nhận được một “lượt đi”. Đến lượt mình, mỗi sinh vật được quan sát xung quanh và thực hiện một số hành động dựa trên trạng thái của môi trường xung quanh. Các sinh vật chỉ biết thực hiện một số hành động. Một sinh vật cơ bản chỉ biết làm 3 việc:

(1) xoay 90 độ để hướng tới một hướng khác,
(2) nhảy tới ô ngay phía trước, hoặc
(3) tấn công sinh vật đứng ngay trước nó. Khi một sinh vật tấn công một sinh vật khác, kẻ bị tấn công trở thành một sinh vật thuộc cùng loài với kẻ tấn công, như vậy tiến gần tới mục tiêu thống trị thế giới. Một số loài có thể sinh sản theo kiểu nguyên thủy khi hai sinh vật cùng loài gặp nhau và sinh ra một sinh vật mới. Tóm lại, tất cả các sinh vật trong Đấu tranh Sinh tồn di chuyển, tìm cách tấn công nhau, và sinh sản để thống trị. Thế giới sẽ bắt đầu với nhiều loài vật, nhưng trong cuộc đấu tranh sinh tồn, loài nào mạnh hơn/may mắn hơn/khôn khéo hơn cuối cùng sẽ giành được thế thắng và làm tất cả các loài khác nhiễm bộ gien của mình - thống trị thế giới.

Luật chơi

Mọi sinh vật phải tuân theo các luật sau:

  • Mỗi sinh vật chỉ có thể nhảy tới ô sát phía trước (theo hướng hiện tại của sinh vật đó)
  • Một sinh vật chỉ có thể tấn công sinh vật đang đứng tại ô ngay trước mặt nó.
  • Một sinh vật có thể quay 90 độ, sang trái hoặc sang phải
  • Một sinh vật có thể nhìn thấy mọi nơi trong thế giới.
  • Mỗi lượt, một sinh vật có thể quan sát thế giới và suy nghĩ tùy ý, rồi thực hiện chỉ một trong 3 hành động: tiến, xoay, hoặc tấn công.
  • Nếu có một sinh vật khác loài đang đứng trước mặt, một sinh vật luôn chọn cách tấn công sinh vật khác loài đó.
  • Các sinh vật không bao giờ tấn công đồng loại hoặc nhảy ra ngoài phạm vi thế giới.
  • Khi một sinh vật bị tấn công, nó bị xóa khỏi thế giới và thay vào đó là một sinh vật mới thuộc cùng loài với kẻ tấn công. Sinh vật mới đứng tại ô của kẻ bị tấn công và hướng theo cùng hướng với kẻ tấn công. Sinh vật mới bắt đầu có lượt kể từ vòng giả lập tiếp theo.
  • Mỗi loài vật tự kiểm soát dân số của loài mình, như vậy, tại thời điểm bất kỳ, ta đều có thể xem có bao nhiêu con thuộc một loài nào đó hiện còn bao nhiêu con.
  • Ban đầu, các sinh vật trong thế giới được phân bố tại các ô ngẫu nhiên, hướng về các hướng ngẫu nhiên.

Những sinh vật sinh sản tuân theo các luật sau:
Một sinh vật sinh sản bằng cách: trong mùa sinh sản, nó cặp đôi với một đồng loại, đẻ một quả trứng, giữ quả trứng đó cho đến khi cho trứng nở thành một sinh vật mới cho thế giới.

Các sinh vật không có giới tính, để đẻ trứng, một sinh vật cần có 2 điều kiện:

  • chính nó đang trong mùa sinh sản (vào các lượt thứ n của mình, n của các loài khác nhau thì khác nhau)
  • nó có một hàng xóm cùng loài (hàng xóm không cần phải cũng đang trong mùa sinh sản, hướng quay của nó và hàng xóm không quan trọng)

Khi đã đẻ trứng, sinh vật phải giữ trứng trong ít nhất một lượt trước khi cho trứng nở (không có giới hạn về thời gian giữ trứng). Mỗi sinh vật, tại mỗi thời điểm chỉ có thể giữ nhiều nhất 1 trứng. Nếu sinh vật bị chết trong khi đang giữ trứng, trứng cũng hỏng vì không được ấp.

Sinh vật đang ấp trứng sẽ cho trứng nở càng sớm càng tốt khi nó thấy một ô vuông trống ở bên cạnh, ô nào cũng được . Khi cho trứng nở, nó tạo một sinh vật mới tại ô trống bên cạnh với hướng ngẫu nhiên (xác xuất 1/4 cho mỗi hướng), và việc giữ trứng kết thúc. Sinh vật mới bắt đầu có lượt từ vòng giả lập tiếp theo.

Một sinh vật đang ấp trứng có thể cho trứng nở và đẻ một trứng khác trong cùng một lượt đi nếu có đủ tất cả các điều kiện cần thiết (đến mùa đẻ trứng, có hàng xóm, có ô trống bên cạnh. Tuy nhiên, trong cùng một lượt, nó không thể vừa cho trứng nở xong là đẻ luôn trứng mới với sinh vật vừa nở ra từ trứng cũ.

Không có việc nào liên quan đến sinh sản được coi là hành động chiếm một lượt đi, do vậy, sau khi đẻ trứng hoặc cho trứng nở, sinh vật vẫn di chuyển, quay, hoặc tấn công để hoàn thành lượt đi của mình.
Trứng chưa nở chưa được tính vào dân số, chỉ có sinh vật đã nở được tính vào dân số của loài vật đó.

Khi một sinh vật đang giữ trứng, trên bàn cờ, nó được vẽ khác đi (chẳng hạn thêm một ký hiệu nhỏ bên cạnh) để ta có thể nhận thấy được.

Các loài vật

Mỗi sinh vật có một tên loài, một vị trí hiện tại trong thế giới và hướng hiện tại mà nó đang quay mặt về. Nó còn có một chiến lược về hành động cần làm mỗi khi đến lượt mình (khi nào tấn công, khi nào rút lui, khi nào sinh sản…). Bằng cách cho các sinh vật với các chiến lược khác nhau cùng cạnh tranh, ta sẽ thấy được về lâu dài, chiến lược nào có lợi hơn.

Dưới đây là các sinh vật cơ bản cho Đấu tranh Sinh tồn:

Vi sinh vật

Vi sinh vật đứng yên tại một chỗ và tấn công mọi vật tình cờ đi ngang qua. Thuật toán của chúng là: Có con gì trước mặt hay không? Nếu có, tấn công nó. Nếu không, quay phải 90 độ. Vi sinh vật không bao giờ di chuyển Có hai loài vi sinh vật: Virus và Germ (vi trùng)

Virus

Virus không thể sinh sản. Một con Virus chỉ bị chết khi bị một sinh vật khác tấn công. Đây là loài vật đơn giản nhất.

Germ (Vi trùng)

Vi trùng sinh sản như mô tả ở trên, với mùa sinh sản xảy ra cứ 3 lượt 1 lần. Vi trùng bị chết khi bị một sinh vật khác tấn công, nó cũng chết nếu xung quanh có quá nhiều hoặc quá ít đồng loại (có 4 con vi trùng hoặc không có con vi trùng nào tại các ô kề cạnh).

Lion (Sư tử)

Sư tử sống theo lý tưởng “Tiến lên hay là chết”. Một con Sư tử tuần tiễu thế giới bằng cách tiến về phía trước, tìm cách thỏa mãn tính phàm ăn của mình. Nếu có con gì ăn được (một sinh vật thuộc loài khác) ở trước mặt một con Sư tử, nó sẽ tấn công. Nếu ô phía trước bị chắn bởi giới hạn thế giới hay một con Sư tử khác, nó sẽ quay trái hoặc phải (với xác suất cùng là 1/2). Một con Khủng long có thể sinh sản bằng cách đẻ trứng (như đã mô tả ở trên) với mùa sinh sản xảy ra cứ 8 lượt một lần. Nếu một con Sư tử đi quá xa (8 lượt) mà không tấn công được con mồi nào, nó sẽ chết đói. Khi một con Sư tử chỉ còn 2 lượt nữa là chết, hình nó trên bàn cờ sẽ được vẽ khác đi (chẳng hạn từ chữ hoa thành chữ thường) để người chơi có thể nhận ra.

Các động vật bay

Có hai loài động vật bay trong Đấu tranh Sinh tồn: Butterfly - Bướm, và Falcon - Chim ưng. Các động vật bay là những kẻ tìm diệt, chúng quan sát toàn bộ thế giới và tìm sinh vật gần nhất thỏa mãn một số điều kiện nhất định. Động vật bay có chiến lược như sau: nếu có một sinh vật khác loài ở trước mặt, nó sẽ tấn công ngay. Nếu không, nó sẽ chọn một sinh vật đích (dựa theo tiêu chí của loài mình), và bắt đầu di chuyển về phía đích.

Sau khi chọn được đích, một động vật bay quyết định sẽ di chuyển tới ô nào bằng cách so sánh khoảng cách giữa các ô lân cận với đích. Quy trình so sánh như sau: nếu khoảng cách từ ô vuông trước mặt tới đích ngắn hơn từ ô hiện tại tới đích và ô trước mặt hiện đang trống thì tiến lên ô phía trước. Nếu không, xem xét hai ô bên trái và bên phải, xoay 90 độ về phía ô có khoảng cách tới đích ngắn hơn. Nếu khoảng cách từ hai ô bên trái và bên phải tới đích là bằng nhau và một trong hai ô đó có sinh vật khác loài, động vật bay sẽ quay về phía ô đó để hy vọng có thể tấn công nó tại lượt sau.

Cuối cùng, nếu cả hai ô trái phải đều có khoảng cách đến đích như nhau và đều trống, sinh vật bay sẽ chọn hướng ngẫu nhiên (xác suất bằng nhau) để quay.

Cũng như Sư tử, các sinh vật bay có tuổi thọ: chúng phải tấn công một sinh vật khác hoặc sẽ chết đói. Một sinh vật bay sẽ chết nếu nó trải qua 6 lượt mà không tấn công được con mồi nào. Hình ảnh của nó trên bàn cờ cũng thay đổi nếu nó sẽ chết trong vòng 2 lượt nữa. Các sinh vật bay cũng có thể sinh sản bằng cách đẻ trứng như mô tả ở trên, mùa sinh sản lặp 4 lượt một lần.

Falcon - Chim ưng

Chim ưng là động vật săn mồi, nó thường xuyên tìm mồi. Nó tìm con mồi (khác loài) gần nhất, cố gắng đuổi theo và tấn công.

Butterfly - Bướm

Bướm là động vật ham chơi, chỉ thích tụ tập với bạn bè. Do đó, các con bướm tìm nhau để tụ tập. Nếu ô vuông trước mặt một con bướm không có con mồi nào để tấn công, nó sẽ lấy con bướm khác ở gần nhất làm đích và tiến về phía nó.

Chương trình

Gồm 2 module: module môi trường giả lập và module các động vật. Module môi trường được cung cấp sẵn. Nhiệm vụ của sinh viên là xây dựng module động vật.

Module động vật

Cây thừa kế của các sinh vật tham gia trò chơi. Các sinh vật có nhiều hành vi giống nhau, phải sử dụng quan hệ thừa kế để có thể tái sử dụng mã được nhiều nhất có thể. Các lớp đối tượng phải có tên bằng tiếng Anh như đã liệt kê ở trên. Các lớp mô tả sinh vật có thể có nhiều phương thức tiện ích nội bộ tuỳ theo thiết kế của bạn, nhưng mọi loài vật phải hỗ trợ các thao tác public sau:

  • constructor cho mỗi sinh vật sẽ lấy tham số là một địa điểm (location), một hướng (Direction), và một đối tượng Game đại diện cho bàn cờ. Constructor có nhiệm vụ cấu hình sinh vật mới một cách hợp lý và đưa nó vào bàn cờ tại vị trí thích hợp

  • phương thức oneTurn() cần thực hiện một lượt đi của sinh vật. Trong đó, các hoạt động liên quan đến quan đến sinh sản thực hiện trước, sau đó mới là những hoạt động liên quan đến di chuyển và tấn công.

  • phương thức draw() lấy tham số là một đối tượng DisplayInterface, và có nhiệm vụ vẽ sinh vật theo vị trí và hướng của nó bằng cách gọi các hàm thích hợp của đối tượng DisplayInterface.

  • phương thức speciesName() trả về tên của loài vật. Mỗi sinh vật cần biết tên của loài mình để vẽ và để so sánh mình với các loài vật khác.

  • phương thức numAlive() trả về dân số của loài

  • phương thức newOfSpecies() tạo một sinh vật mới thuộc loài đó. Phương thức này cần cho việc tạo sinh vật mới khi tấn công và sinh sản.

Module mô phỏng được cung cấp

DisplayInterface

Chi tiết về hỗ trợ hiển thị ra màn hình được ẩn sau lớp trừu tượng DisplayInterface mà các bạn sẽ dùng để vẽ thế giới sinh vật. DisplayInterface cung cấp một số chức năng được thiết kế đặc biệt cho trò chơi Đấu tranh Sinh tồn. Các phương thức các bạn sẽ cần dùng đến: phương thức drawCreature() lấy tên loài, vị trí, hướng, các thông tin về sinh vật có đang giữ trứng hay không, có phải đang trong tình trạng sắp chết đói hay không, và vẽ sinh vật vào bàn cờ (bên trái màn hình trò chơi) theo cách nào đó thích hợp cho thiết bị hiển thị.

phương thức drawSpeciesCount() lấy tên loài, dân số và bổ sung một dòng vào bảng trạng thái trò chơi (bên phải màn hình trò chơi).

bạn có thể dùng phương thức pause() hoặc delay() để làm trễ vòng lặp chính của trò chơi cho tiện theo dõi.

Game

Lớp Game được viết sẵn. Nó có nhiệm vụ thực hiện việc giả lập bằng cách tạo đối tượng DisplayInterface cần thiết và đưa các sinh vật thuộc nhiều loài vào các vị trí ngẫu nhiên trên bàn cờ. Phương thức run() chạy quá trình mô phỏng và lặp đi lặp lại qua các sinh vật, cho từng sinh vật lượt đi và vẽ trạng thái của thế giới cho đến khi nào người chơi muốn dừng lại (bấm Q hoặc q để dừng)

Geometry

Một số kiểu dữ liệu và tiện ích dành cho thao tác với vị trí và hướng Để biết thêm chi tiết, hãy đọc mã nguồn module mô phỏng.

Chính xác mà nói thì không có ví dụ về hướng đối tượng nào hay hơn ví dụ về game mô phỏng thế giới thực trong đó có các loài vật. Đây là một bài viết thực sự công phu. Bạn có biết mình sẽ phải làm gì để xây dựng hệ thống này không? Xin chia sẻ cái bạn có để mọi người cùng trao đổi đóng góp.

đây là bài thi hướng đối tượng của mình thầy cho trước đề tuần sau thi và thật sự rất hoang mang khi đọc đề

Nếu làm kiểu tay to thì cũng không quá khó. Bạn làm việc với các thành phần cơ bản nhất của oop như interface, sau đó tạo ra các abstract class impliments các interface đó, rồi tạo ra các concrete class như Lion…

Thuộc tính có bao nhiêu cái thì add vào đối tượng, phương thức cũng add vào interface > abstract class > concrete class.

Như vậy bạn đã sử dụng 3 sử dụng 3-4 tính chất cơ bản nhất của oop là tính trừu tượng, đa hình kế thừa.

1 Like

yêu cầu đề là code bằng c++

Đọc đề đã thấy chán roài…

Bạn có thể chia sẻ toàn bộ đề với mọi người được không bạn? Cái này làm mình tò mò qúa…

đề có nói cung cấp các file nhưng thầy mình nói phải tự định nghĩa hết

Bài tập của Mr. Nguyễn Văn Nguyên à bạn

Vậy sinh vật tấn công đứng ở ô nào bạn???

Chuẩn luôn . Hehe mai thi bài này mà giờ chỉ biết chuẩn bị $ học lại =))
mà bác học Khóa mấy vậy

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?