2009-12-07 33 views
15

Bạn đang viết một chương trình Tetris trong Java. Làm thế nào bạn sẽ thiết lập thiết kế lớp học của bạn liên quan đến các khía cạnh sau đây?Câu hỏi thiết kế triết học cho OOP-Tetris

  • lớp Piece: Có một Piece lớp, với một mảng nội bộ mà quyết định hình dạng của các mảnh, so với có bảy Piece lớp học, một cho mỗi miếng. Chúng là tất cả các lớp con của một lớp Piece chung.
  • đại diện lớp Piece: Có một mảng của 4 trường hợp của Block, đại diện cho một hình vuông của một mảnh, và mỗi Block chứa vị trí của nó trên Board (trong tọa độ đồ họa) so với việc có một mảng 4x4 nơi null có nghĩa là không có khối, và vị trí được xác định bởi hình dạng của mảng.
  • Location: Mỗi Block trong mảng Piece hoặc trên mảng Board lưu trữ vị trí của nó so với các PieceBoard biết vị trí của các Blocks mà bao gồm họ.
  • Tạo một Piece: Có một phương pháp tĩnh của lớp mảnh getRandomPiece, hoặc có một PieceFactory mà bạn thực hiện một ví dụ về điều đó có phương pháp genRandomPiece trên ví dụ.
  • Thao tác các mảnh hiện tại: Sử dụng mô hình Proxy, do đó tất cả những gì cần truy cập vào nó chỉ sử dụng các proxy, hoặc có một phương pháp getCurrentPiece trên lớp Board và gọi đó là bất cứ lúc nào bạn muốn làm điều gì đó với hiện tại cái.

Đây không phải là bài tập về nhà. Tôi chỉ mâu thuẫn với những gì khóa học CS giới thiệu giảng dạy tại trường đại học của tôi và tôi muốn xem những gì mọi người nói chung tin tưởng. Điều gì sẽ được cho là thiết kế OOP "tốt"? Bỏ qua thực tế là nó cho một khóa học giới thiệu - làm thế nào để bạn làm điều đó?

+2

phải là cộng đồng wiki – Malfist

+1

Tất cả các lớp và nội dung này ... có thể khiến cho vấn đề quá trừu tượng đối với những gì nó thực sự là. Nhiều cách khác nhau để biểu diễn các phần tetris (http://stackoverflow.com/questions/233850/tetris-piece-rotation-algorithm) và nhiều cách khác nhau để thao tác chúng. Nếu nó cho một khóa học * giới thiệu * tôi sẽ không lo lắng về OOP. Chỉ cần ý kiến ​​của tôi, không phải là một câu trả lời thực sự cho câu hỏi của bạn. –

+0

@roygbiv: đăng nhận xét này làm câu trả lời! Tôi nghĩ bạn ít nhất sẽ có một hoặc hai lớp học – Claudiu

Trả lời

10

Thứ nhất, tôi sẽ không phân lớp lớp Piece vì nó không cần thiết. Lớp Piece phải có khả năng mô tả bất kỳ hình dạng nào mà không cần sử dụng thừa kế. IMHO, đây không phải là những gì thừa kế đã được thực hiện cho và nó chỉ phức tạp mọi thứ.

Thứ hai, tôi sẽ không lưu trữ tọa độ x/y trong các đối tượng Block vì nó cho phép hai khối tồn tại ở cùng một vị trí. Các lớp Piece sẽ giữ một lưới (tức là mảng 2D) giữ các đối tượng khối. Tọa độ x/y sẽ là các chỉ mục của mảng 2D. Đối với phương pháp tĩnh so với đối tượng nhà máy để nhận được một mảnh ngẫu nhiên, tôi muốn đi với đối tượng nhà máy cho một thực tế đơn giản là đối tượng nhà máy có thể được chế nhạo để thử nghiệm.

Tôi sẽ coi bảng là một đối tượng lớn Piece. Lớp Board sẽ giữ đối tượng Piece lớn làm biến thành viên và có thể giữ các đối tượng Piece khác như đoạn hiện tại đang phát và đoạn tiếp theo sẽ được phát. Điều này được thực hiện bằng cách sử dụng bố cục để tránh thừa kế.

+3

+1 Thừa kế là không cần thiết, thậm chí có hại, bởi vì chúng tôi muốn tất cả các phần có cùng một hành vi. Các mảnh chỉ khác nhau về hình dạng và màu sắc của chúng. Ví dụ duy nhất tôi có thể nghĩ về nơi bạn muốn hành vi đặc biệt là một cái gì đó giống như điểm thưởng "t-spin" trong Tetris DS, nhưng điều đó có thể được xử lý tốt hơn như một trường hợp đặc biệt trong mã số điểm. Không sử dụng phân cấp lớp như là một thay thế cho câu lệnh if() {}. – Theran

+0

Bạn có thể giải thích câu cuối cùng không? Khi bạn nói rằng hội đồng quản trị sẽ là một mảnh lớn có thể chứa một mảnh khác, tôi tự động thừa kế thừa kế – Claudiu

+1

Bạn nói đúng, có một chút không rõ ràng. Hội đồng quản trị sẽ giữ cho "một mảnh lớn" như là một biến thành viên. –

3
  • Một Piece giao diện, với bảy lớp mà thực hiện mà giao diện cho các phần riêng lẻ (mà cũng sẽ cho phép quá trình OOP để thảo luận về giao diện) (EDIT:. Một Piece lớp Xem bình luận)
  • Tôi sẽ có một lớp BlockGrid có thể được sử dụng cho bất kỳ bản đồ khối nào - cả bảng và các phần riêng lẻ. BlockGrid cần có phương pháp để phát hiện giao lộ - ví dụ: boolean intersects(Block block2, Point location) - cũng như xoay lưới (điểm thảo luận thú vị cho khóa học: Nếu Board không cần xoay, phương pháp rotate() phải ở BlockGrid?). Đối với một Piece, BlockGrid sẽ đại diện cho một lưới 4x4.
  • tôi sẽ tạo ra một PieceFactory với một phương pháp getRandomShape() để có được một thể hiện của một trong bảy hình dạng
  • Đối với thao tác mảnh, tôi muốn nhận được vào một kiến ​​trúc MVC. Mô hình là Mảnh. Bộ điều khiển có lẽ là PieceController và cũng sẽ cho phép hoặc không cho phép di chuyển hợp pháp/bất hợp pháp.Điều đó sẽ hiển thị Piece trên màn hình là một PieceView(HRM, hoặc là nó một có thể hiển thị Piece.getBlockGrid()? Một điểm thảo luận!)

Có nhiều cách hợp pháp để kiến ​​trúc sư này. Nó sẽ có lợi cho khóa học để có các cuộc thảo luận về các chuyên gia và con của các nguyên tắc OOP khác nhau áp dụng cho vấn đề này. Trong thực tế, nó có thể là thú vị để so sánh và tương phản điều này với một thực hiện không OOP mà chỉ sử dụng mảng để đại diện cho hội đồng quản trị và miếng.

EDIT:Claudiu đã giúp tôi nhận ra rằng BlockGrid sẽ đủ phân biệt mảnh, vì vậy không có nhu cầu về một giao diện Piece với nhiều lớp con; thay vào đó, một phiên bản của Piecelớp có thể khác với các phiên bản khác dựa trên BlockGrid của nó.

+2

+1 cho ý tưởng so sánh và đối chiếu với một giải pháp không phải OO thay vì chỉ nhấn mạnh vào thiết kế OO mà không có bất kỳ cuộc thảo luận nghiêm túc nào về sự cân bằng liên quan. – dsimcha

+0

Bạn nhận ra rằng vì BlocKGrid chỉ là một giao diện, bạn sẽ viết 7 chức năng dò tìm xung đột riêng biệt với thiết kế mà bạn đã đặt ra ở đây? Cũng như 7 chức năng xoay riêng biệt? Bạn có thực sự làm theo cách này không? – Claudiu

+0

Có lẽ tôi không rõ ràng trong việc xác định BlockGrid. BlockGrid về bản chất là một mảng bit n * n. Hàm phát hiện va chạm sẽ tương tự như khi nói, "if ((array1 (x, y) == TRUE) && (mảng2 (x, y) == TRUE)) {collision = TRUE;}" (với toán học thích hợp để bù đắp vị trí của một BlockGrid khác) –

2

Lớp học: Tôi nghĩ rằng một lớp duy nhất cho tất cả các phần là đủ. Hàm shoudl của lớp là đủ chung để làm việc cho bất kỳ phần nào, do đó không cần phải phân lớp.

Đại diện lớp mẫu: Tôi tin rằng một mảng 4x4 có lẽ là một cách tốt hơn vì bạn sẽ thấy việc xoay mảnh dễ dàng hơn nhiều.

Vị trí: Vị trí chắc chắn nên được lưu trữ bởi bảng chứ không phải mảnh nếu không bạn sẽ phải trải qua toàn bộ các khối để đảm bảo không có hai khối nào ở cùng vị trí.

Tạo một mảnh: Thành thật mà nói, tôi không cảm thấy nó sẽ tạo ra quá nhiều sự khác biệt. Có nói rằng, tôi sẽ thích một chức năng tĩnh như có thực sự không quá nhiều đến chức năng này mà nó đảm bảo lớp riêng của mình.

Thao tác mảnh hiện tại: Tôi sẽ chỉ triển khai hàm getCurrent vì tôi không cần phải giải quyết vấn đề bằng cách thêm vào lớp bổ sung để làm proxy.

Đây là cách tôi sẽ làm, nhưng có rất nhiều cách khác nhau và vào cuối ngày, điều cần tập trung vào đơn giản là chạy chương trình.

3

Tất cả các lớp và nội dung này ... có thể khiến cho vấn đề quá trừu tượng đối với thực tế. Nhiều cách khác nhau để biểu diễn các phần tetris (stackoverflow.com/questions/233850/…) và nhiều cách khác nhau để thao tác chúng. Nếu nó cho một khóa học giới thiệu, tôi sẽ không lo lắng về OOP. Chỉ cần ý kiến ​​của tôi, không phải là một câu trả lời thực sự cho câu hỏi của bạn.

Có thể nói rằng, người ta có thể chỉ cần một bảng và lớp Piece.

Lớp bảng: Đóng gói một mảng 2d hình chữ nhật đơn giản. Các tính chất như phôi, phụ tùng. Các thói quen như draw(), fullrows(), drop(), vv .. thao tác với phần hiện tại và các ô vuông trong bảng.

Lớp mẫu: Đóng gói một mảng số 16 bit chưa ký mã hóa các phần theo các phép xoay khác nhau của chúng. Bạn sẽ theo dõi màu sắc, vị trí hiện tại và xoay vòng. Có lẽ một thói quen, xoay() sẽ là cần thiết.

Phần còn lại, sẽ là, tùy thuộc vào môi trường, xử lý sự kiện bàn phím vv ...

tôi đã tìm thấy rằng việc đặt quá nhiều nhấn mạnh vào thiết kế có xu hướng làm cho mọi người quên rằng những gì họ thực sự cần phải làm là để có được một cái gì đó đang chạy. Tôi không nói không thiết kế, tôi nói rằng thường xuyên hơn không, có giá trị hơn trong việc nhận được một cái gì đó đi, cho bạn lực kéo và động lực để tiếp tục đi.

Tôi muốn nói, với lớp học, bạn có X giờ để tạo thiết kế cho trò chơi Tetris. Sau đó, họ sẽ cần phải biến trong thiết kế đó. Sau đó, tôi sẽ nói, bạn có X ngày, để có được một cái gì đó chạy dựa trên thiết kế bạn đã bật hoặc thậm chí không phải dựa trên thiết kế.

Các vấn đề liên quan