Caro
Đề bài
Tí và Tèo đang chơi trò chơi caro, Tí đi quân 'x' và Tèo đi quân 'o' vào các ô vuông trên bàn cờ. Ai đi được 5 ký hiệu liên tiếp (theo đường dọc, hoặc đường ngang, hoặc đường chéo) trước thì thắng. Giả sử bàn cờ là một hình vuông kích thước $n \times n$. Cho tình trạng của một bàn cờ, bạn hãy cho biết giữa Tí và Tèo có người thắng hay chưa, hay ván cờ vẫn đang tiếp diễn.
Dữ liệu nhập:
- Dòng đầu tiên là số nguyên $n$ $(5 \le n \le 20)$ là kích thước bàn cờ.
- Trong $n$ dòng tiếp theo, mỗi dòng gồm $n$ ký tự biểu thị tình trạng bàn cờ. Mỗi ký tự là một trong ba giá trị
'x','o'và dấu chấm'.'(x và o viết thường, dấu chấm là ô chưa đánh).
Dữ liệu xuất:
- Nếu Tí thắng, in ra dòng chữ
Ti wins. Nếu Tèo thắng, in ra dòng chữTeo wins(Tí Tèo không dấu). - Nếu ván cờ vẫn đang tiếp diễn chưa có ai thắng, in ra dòng chữ
Not yet(chú ý chữ hoa chữ thường).
Ghi chú: dữ liệu cho đảm bảo không có trường hợp 2 đấu thủ cùng thắng. Luật chơi cho phép chặn 2 đầu cũng thắng, liên tiếp nhiều hơn 5 quân cũng thắng.
5
xo...
.xo..
..xo.
...xo
....xTi wins5
xo...
.xx..
ooooo
...xo
....xTeo wins5
ox...
.xoo.
..ox.
.o.xo
..x..Not yetLời mở đầu
Đây là bài mở màn của chương Mảng 2 chiều: đọc một bàn cờ vào mảng 2 chiều rồi "đi dạo" trên đó theo các hướng. Bài không khó nhưng rất hay bị sai ở chỗ quên đường chéo phụ hoặc truy cập ra ngoài bàn cờ. Mình sẽ giải thích thật kỹ để các bạn nắm chắc kỹ thuật duyệt theo hướng – kỹ thuật này sẽ dùng lại ở rất nhiều bài sau trong chương.
Link này chỉ học viên đã tham gia tổ chức mới vào được. Học viên nên ưu tiên nộp ở đây vì sẽ được chấm nhanh hơn.
Nộp bài trên CLUE OJLộ trình lời giải, bấm vào từng phần để nhảy tới:
Bộ testBộ test chính thức có gì?
| Số test | Kích thước n | Ti wins | Teo wins | Not yet |
|---|---|---|---|---|
| 12 | 5 (3 test), 7 (3 test), 10 (3 test), 15 (3 test) | 4 | 4 | 4 |
Bài không chia subtask: $n$ tối đa chỉ 20 nên cách duyệt mọi ô, mọi hướng ở dưới chạy thoải mái cho toàn bộ test. Ba kết quả được chia đều nhau, nên code phải xử lý đúng cả trường hợp chưa ai thắng.
Ý tưởngMỗi ô là một điểm xuất phát, thử 4 hướng
Một dãy 5 quân liên tiếp luôn có một quân đầu tiên. Nếu ta đứng ở quân đầu tiên đó thì 4 quân còn lại nằm theo một trong các hướng:
- Ngang sang phải: $(0, +1)$
- Dọc xuống dưới: $(+1, 0)$
- Chéo chính xuống phải: $(+1, +1)$
- Chéo phụ xuống trái: $(+1, -1)$
Không cần xét thêm các hướng ngược lại (trái, lên, ...) vì dãy 5 quân đi ngược lại thì vẫn là dãy đó, chỉ là ta đứng ở quân cuối thay vì quân đầu. Vậy thuật toán là:
Vì "liên tiếp nhiều hơn 5 quân cũng thắng" nên chỉ cần tìm thấy một đoạn đúng 5 quân là đủ (một dãy 6 quân chắc chắn chứa một đoạn 5 quân). Và "chặn 2 đầu cũng thắng" nên ta không phải quan tâm 2 đầu dãy có bị chặn hay không. Đề cũng đảm bảo không có chuyện cả 2 cùng thắng, nên kiểm tra x trước hay o trước đều được.
Em sửa bàn cờ rồi bấm Tiếp để xem máy "quét" từng ô, từng hướng:
CodeCài đặt
Mình viết hàm check(i, j, dx, dy, c) kiểm tra 5 ô theo một hướng, và hàm win(c) duyệt mọi ô, mọi hướng. Hai mảng dx[], dy[] giúp viết 4 hướng gọn trong một vòng lặp thay vì chép 4 đoạn code gần giống nhau.
if trong hàm check mỗi khi một hướng thất bại (ra ngoài bàn cờ hoặc gặp quân khác).- Điều kiện
x < 0 || x >= n || y < 0 || y >= nphải đặt trướca[x][y] != c: nhờ toán tử||"ngắt mạch", khi ô đã ra ngoài bàn cờ thì máy không đọca[x][y]nữa, tránh truy cập ngoài mảng. - Ngay khi gặp một ô sai là
return false, không cần xét tiếp các ô còn lại của đoạn. - Mảng
a[25][25]kiểuchar, đọc mỗi dòng bằngcin >> a[i]là đọc được cả chuỗi $n$ ký tự (chuỗi không có dấu cách).
Nhận xét
Đăng nhận xét