Assignment 02: Trò chơi bắn máy bay

(sửa ngày 3/12:giới hạn số máy bay trong bản đồ: không quá 100; ra hạn nộp bài) (sửa ngày 29/11: hình 2, tọa độ bắn,... xem các phần mầu đỏ)
Các câu hỏi thường gặp (cập nhật ngày 6/12).


Hạn nộp: 23h59' ngày 19/12/2010.
Nộp tại Bitbucket.

Cách nộp bài

Sinh viên sử dụng tài khoản bitbucket đã dùng cho Bài tập lớn số 1 (username trùng với username tại bbc.vnu.edu.vn).
Bài nộp phải được đặt trong project (tại bitbucket) có tên oop-asg02
Project oop-asg02 phải được cấp quyền đọc (read permission) cho user chauttm (chauttm là người sẽ thu bài các lớp CA, CD, sinh viên các lớp khác cần liên hệ với giáo viên để hỏi username của người thu bài lớp/nhóm mình)
Đến hạn nộp, giáo viên sẽ lấy phiên bản mới nhất của project bằng lệnh
hg clone http://bitbucket.org/username/oop-asg02
Chú ý thực hiện hướng dẫn một cách chính xác. Khác với Bài tập lớn số 1, lần này các bài nộp sai tên project hoặc chưa cấp quyền đọc sẽ không được thu bổ sung

Bài nộp gồm các file mã nguồn và một file dạng text có tên README. Trong file README cần có các thông tin cá nhân như tên, lớp, số sinh viên, và hướng dẫn biên dịch (nếu cần). Các file để nguyên trong thư mục project, không nén, không tạo các thư mục con.

Đề bài

Cũng như Bài tập lớn số 1, bạn cần viết một chương trình cho phép chơi trò bắn máy bay theo tọa độ cho phép một người chơi dò bắn một số máy bay ẩn trên bản đồ. Tuy nhiên, ở bài này, quy tắc bắn và dạng máy bay có thay đổi, và bạn cần dùng thiết kế hướng đối tượng.

Hoạt động của chương trình

Mỗi lần chạy, chương trình cho phép người chơi chơi một ván. Mỗi ván bắt đầu bằng việc chương trình nạp bản đồ từ một file text. Sau đó, người chơi bắt đầu bắn theo tọa độ. Tại mỗi lượt bắn, người chơi nhập các tọa độ bắn từ bàn phím. Nếu tọa độ nhập vào là nằm trong phạm vi bản đồ thì chương trình ghi nhận phát đạn là trúng hay trượt (chương trình có thể hiển thị bản đồ để người chơi tiện theo dõi và xác định tọa độ bắn), tọa độ bắn, kết quả trúng hay trượt, và tình trạng bản đồ được chương trình ghi ra một file log (nhật trình). Nếu tọa độ nhập vào nằm ngoài bản đồ, chương trình bỏ qua lượt bắt này và không ghi gì vào nhật trình.
Chương trình kết thúc khi người chơi đã bắn rơi (diệt/kill) hết máy bay trên bản đồ.

Có ba loại máy bay: Máy bay trực thăng (helicopter), máy bay ném bom (bomber), và máy bay tiêm kích (fighter). Hình ảnh các loại máy bay trên màn tọa độ được minh họa trong hình dưới đây. Các ô chứa kí hiệu chữ cái (o, E, P, R,...) đại diện cho một phần của thân máy bay.

 . . . . . . . . . .	. . . . . . . . . .		. . . . . . . . . .
 . . . . . . . . . .	. . . . . . . . . .		. . . . . P . . . .
 . . . . . . . . . .	. . . . o o . . . .		. . . . o o o . . .
 . . . o . . . . . .	. . . o o o o o o .		. . o E o o o E o .
 . . o P o . . . . .	. . . . o o . . . .		. o o o . o . o o o
 . o . o . o . . . .	. . . . . . . . . .		. . . . . o . . . .
 . . o R o . . . . .	. . . . . . . . . .		. . . . . o . . . .
 . . . . . . . . . .	. . . . . . . . . .		. . . . o E o . . .
 . . . . . . . . . .	. . . . . . . . . .		. . . . . . . . . .
 . . . . .   . . . .	. . . . . . . . . .		. . . . . . . . . .
     fighter                helicopter                 bomber
	 
	 Hình 1: Các loại máy bay.
 
Máy bay các loại được coi là bị diệt (killed) ngay khi một trong các tình huống sau xảy ra:
  1. Máy bay bất kì bị bắn trúng vị trí buồng lái phi công (kí hiệu bằng chữ P trong hình trên).
  2. Máy bay trực thăng bị trúng một phát đạn vào bất cứ bộ phận nào.
  3. Máy bay ném bom bị bắn cháy hết 3 động cơ (chữ E) hoặc đã bị trúng 10 phát đạn.
  4. Máy bay tiêm kích bị bắn trúng động cơ phản lực (chữ R) hoặc đã bị trúng 4 phát đạn.
Các máy bay có thể có các phần trùng tọa độ do ở các độ cao khác nhau (nếu nhìn trên bản đồ thì hình máy bay này đè lên hình máy bay kia). Người bắn sử dụng loại vũ khí cực mạnh, nên nếu bắn vào một tọa độ như vậy thì sẽ trúng cả hai máy bay. Máy bay nào đã bị rơi rồi thì các phát đạn vào nó, kể cả vào các phần chưa bị bắn, không còn được xem là "trúng" nó nữa (tuy nhiên phát đạn này có thể vẫn trúng máy bay khác).

Tọa độ của lưới bản đồ được xác định là một cặp số nguyên không âm x,y, với dòng 0 là dòng trên cùng, cột 0 là cột đầu tiên bên trái. Dưới đây là ví dụ về bản đồ ở thời điểm một máy bay đã bị bắn cháy hoàn toàn khi hiển thị trên màn hình. Các ô 'x' là các tọa độ mà máy bay bị bắn trúng, '.' là các ô chưa hề bị bắn. ' ' là các ô đã bị bắn nhưng máy bay lại không nằm tại tọa độ đó (bắn trượt).

 
    0 1 2 3 4 5 6 7 8 9
  _____________________
0 | . . . . . . . . . .
1 | . . . . . . . . . .
2 | . . . x x . . . . .
3 | x x x x x x . . . .
4 | . . . x x         .
5 | . . . . . . . . . .
6 | . . . . . . . . . .
7 | . . . . . . . . . .
8 | . . . . . . . . . .
9 | . . . . .   . . . .
	Hình 2: Hình một chiếc trực thăng tọa độ (3,5) đang quay về hướng Đông.

Các quy định về vào ra dữ liệu và chạy chương trình

Dữ liệu vào
Có hai phần: cấu hình trò chơi và tọa độ bắn.

1. Cấu hình trò chơi được nạp từ một file text với định dạng như sau: Dòng đầu ghi 2 số nguyên m, n trong khoảng từ 1 đến 20 với mxn là kích thước bản đồ bầu trời. Từ dòng thứ 2 đến hết file, mỗi dòng ghi mô tả về 01 máy bay theo công thức

<type> x y <direction>
trong đó, <type> có thể là một trong các chữ cái H (helicopter), F (fighter), B (bomber); x y là tọa độ (số nguyên) của điểm đầu máy bay (x là tọa độ dòng, y là tọa độ cột); <direction> có thể là một trong các chữ cái N (north - trên), S (south - dưới), E (east - phải), W (west - trái) là hướng của máy bay. Ví dụ mô tả về chiếc trực thăng ở hình 2 sẽ có dạng
H 3 5 E
Cuối và đầu mỗi dòng không có dấu trắng thừa. Trong file không chứa dòng trắng cuối cùng. Chương trình KHÔNG phải kiểm tra tính hợp lệ của file cấu hình. Tên file cấu hình được xác định bởi tham số đầu tiên trong lệnh chạy chương trình (xem chi tiết ở ví dụ bên dưới).

2. Tọa độ bắn (số nguyên) được người dùng nhập từ bàn phím dưới dạng x y (x là tọa độ dòng, y là tọa độ cột), hai số x, y được viết cách nhau ít nhất 1 kí tự trắng. Chương trình KHÔNG phải kiểm tra tình trạng người dùng có nhập số nguyên hay không (người dùng chắc chắn sẽ nhập các số nguyên).

Dữ liệu ra:
Có hai phần: giao diện với người dùng trên màn hình và file nhật trình.

1. Giao diện với người dùng, chẳng hạn vẽ bản đồ lên màn hình và lời mời nhập tọa độ bắn, cũng như thông báo trúng/trượt tại màn hình là do lập trình viên tự quyết định và thiết kế và KHÔNG có yêu cầu cụ thể.

2. Phần nhật trình (log) của mỗi ván chơi được ghi ra 1 file và phải tuân thủ CHÍNH XÁC quy định sau đây về định dạng dữ liệu trong file: với mỗi phát đạn của người chơi, chương trình cần ghi những nội dung sau vào file nhật trình:

- 01 dòng tọa độ bắn theo định dạng:

x<tab>y<tab>result
trong đó x, y lần lượt là các tọa độ dòng và cột của phát đạn, <tab> là 01 kí tự tab, result là miss hay hit tùy theo kết quả là trượt hay trúng. Một phát đạn được coi là "trúng" nếu nó bắn vào một phần chưa bị bắn của một chiếc máy bay chưa rơi.
- Lưới ô vuông m x n chứa các ô 0 hoặc 1 lưu trữ tình trạng bản đồ sau phát bắn. Trong đó các ô 1 biểu thị các tọa độ máy bay chưa bị bắn trúng, còn lại là các ô 0. Có đúng 01 kí tự space (' ') đứng sau mỗi kí hiệu 0 hay 1. Lưu ý: Các máy bay đã bị bắn rơi do đã rơi nên không còn trên bản đồ
Ngoài ra, không được thiếu/thừa bất cứ dòng trắng hay kí tự trắng nào. Tên file nhật trình là tham số thứ hai của dòng lệnh chạy chương trình, nếu lệnh chỉ có 1 tham số thì tên file nhật trình là tên của file cấu hình cộng thêm chuỗi '.log' vào cuối (xem chi tiết tại ví dụ bên dưới).

Ví dụ đoạn nhật trình của một phát bắn:

 
3	3	hit
0 0 0 0 0 0 0
0 0 0 1 0 0 0
0 1 1 1 1 1 0
0 0 0 0 0 0 0
0 0 0 1 0 0 0
0 0 1 1 1 0 0
0 0 0 0 0 0 0

Chạy chương trình:

Chương trình được chạy từ màn hình console (cmd trong môi trường DOS, terminal trong môi trường Linux) bằng dòng lệnh
java <tên chương trình> <tên file cấu hình> <tên file nhật trình>
hoặc
java <tên chương trình> <tên file cấu hình>
Ví dụ,
java Game test1.in test1.out
chương trình tại class Game sẽ nạp cấu hình bản đồ từ test1.in và ghi nhật trình ra test1.out
java Game test1.in
chương trình tại class Game sẽ nạp cấu hình bản đồ từ test1.in và ghi nhật trình ra test1.in.log