/17
lOMoARcPSD| 61549570
ĐẠI HỌC BÁCH KHOA HÀ NỘI
Trường Công nghệ thông tin và Truyền thông
------------------🙡🕮🙣------------------
BÁO CÁO BÀI TẬP LỚN MÔN LẬP TRÌNH MẠNG
Đề tài: Xây dựng trò chơi theo lượt Battleship Online
Sinh viên thực hiện: Đỗ Mạnh Phương 20225660
Lê Quang Khải 20225638
Giảng viên hướng dẫn: TS Đặng Tuấn Linh
Hà Nội, ngày 31 tháng 12 năm 2024
lOMoARcPSD| 61549570
MỤC LỤC
I. Chương I: Giới thiệu đề tài
1. Sơ lược về đề tài
2. Bố cục báo cáo
II. Chương II: Cơ sở lý thuyết
1. Kiến thức cơ bản về lập trình socket TCP
2. Kiến thức về quản lý vào ra và hàm select()
3. Kiến thức về QT trong C++
4. Sử dụng SQLite3 quản lý dữ liệu người chơi
III. Chương III: Kiến trúc mạng
1. Server
IV. Chương IV: Cơ chế game
1. Cơ chế đặt tàu và bắn tàu
2. Chức năng nâng cao : Chat trong game
V. Chương V: Phân chia công việc VI. Chương VI: Kết
luận
CHƯƠNG I: Giới thiệu đề tài
1. Sơ lược về đề tài
Đã từ lâu, Battleship là một trò chơi chiến thuật nổi tiếng, trong đó hai người
chơi cạnh tranh để đánh bại đối phương bằng cách tìm và đánh chìm các tàu chiến
của họ. Mỗi người chơi sđặt các tàu chiến của mình trên một bảng lưới (grid)
10x10 lần lượt phát tín hiệu bằng cách "bắn" vào các tọa độ trên bảng đối
phương. Mục tiêu của trò chơi là xác định vị trí các tàu đối thủ bắn trúng chúng
trước khi đối thủ làm điều tương tự. Tchơi không chỉ đòi hỏi sự tính toán chiến
lược mà còn yêu cầu khả năng phán đoán và sự may mắn. Với sự hấp dẫn và thử
thách trong việc đối kháng qua các lượt đi, Battleship đã trở thành một tchơi
kinh điển trong làng boardgame, mang lại những phút giây thư giãn và kịch tính
cho người chơi.
Vậy nên bọn em đã quyết định tái hiện lại trò chơi này trên máy tính bằng
giao diện đồ họa kết hợp cùng các kiến thức đã học được trong bộ môn Thực hành
Lập trình mạng.
lOMoARcPSD| 61549570
2. Bố cục báo cáo
Chương 1: giới thiệu đề tài
Ở chương này nhóm em sẽ tóm tắt chủ đề mà nhóm thực hiện và nêu tóm tắt
mục đích của từng chương để thầy thể khái quát được báo cáo gồm những gì
và nói về gì.
Chương 2: Cơ sở lý thuyết
Nhóm em sẽ nêu ra các thuyết, công nghệ nhóm em đã tìm hiểu sử
dụng để xây dựng project này. Nhóm em sẽ nêu tóm lược khái niệm và lý do sử
dụng, phần implementation sẽ được đề cập trong các chương sau.
Chương 3: Kiến trúc mạng
Trong chương này, nhóm em sẽ khái quát tổng quan về kiến trúc mạng, cách
thức xtruyền dòng cũng như chế vào ra socket theo hình clientserver
được thực hiện trong ứng dụng.
Chương 4: Cơ chế của game
Trong chương này em sẽ giới thiệu các nh năng game thể cho thầy
một cái nhìn khái quát về độ phức tạp của game nhóm em đã phát triển. Về
chi tiết hình ảnh và thao tác chúng em sẽ nêu đầy đủ trong video demo.
Chương 5: Ni dung phân chia công việc
Chương này sẽ bao gồm bảng chứa danh sách các công việc, lượng điểm ước
chừng người được phân công. Ngoài ra mỗi công việc, nhóm em cũng sẽ nêu
nội dung những công việc đó để thầy thể đánh giá xem lượng điểm
dành cho đầu việc đó có hợp lý hay không.
Chương 6: Kết luận
Bao gồm các tài liệu tham khảo và lời kết.
lOMoARcPSD| 61549570
CHƯƠNG II: Cơ sở lý thuyết
Dưới đây 1 số sở lý thuyết nền tảng chúng em đã áp dụng vào ứng
dụng của mình:
1. Kiến thức cơ bản về lập trình socket và TCP
- Socket giao diện lập trình ứng dụng mạng được dùng đtruyền
và nhận dữ liệu trên internet. Giữa hai chương trình chạy trên mạng
cần một liên kết giao tiếp hai chiều, hay còn gọi là two-way
communication để kết nối 2 process trò chuyện với nhau. Điểm cuối
(endpoint) của liên kết này được gọi là socket.
o Socket định danh ứng dụng mà dữ liệu sẽ được gửi tới thông
qua sràng buộc với 1 cổng port để tiến hành kết nối giữa
client và server.
o Ưu điểm của socket: tương thích với hầu hết các hệ điều
hành, từ Window cho đến Linux Mac OS X... Ngoài ra,
socket còn thể kết hợp được với rất nhiều ngôn ngữ lập
trình như C, C++, C#, Java. Người dùng cũng thể chạy
nhiều socket liên tục cùng một lúc được, giúp nâng cao hiệu
suất làm việc cũng như tiết kiệm thời gian hơn.
- TCP là 1 giao thức truyền thông trong bộ giao thức TCP/IP, được
sử dụng để đảm bảo việc truyền tải dữ liệu giữa các thiết bị trên
mạng một cách tin cậy và có trật tự. TCP đảm bảo rằng dliệu được
truyền từ nguồn đến đích không bị mất mát, bị sai thứ tự, hoặc
bị hỏng. Giao thức này kết nối hướng, nghĩa trước khi truyền
tải dữ liệu, một kết nối phải được thiết lập giữa hai thiết bị thông qua
quá trình gọi 3-way handshake. Dưới đây 1 số đặc trưng của
việc truyền thông bằng TCP:
o Tạo luồng dữ liệu hai chiều, đáng tin cậy, trình tkhông
trùng lặp, dữ liệu chỉ được gửi/nhận khi đã liên kết.
Trong C++ sử dụng hàm socket() để tạo và sử dụng socket.
o Cần liên kết 2 chiều trước khi server client thể trao
đổi thông điệp với nhau.
o Ban đầu, phía server tạo socket được ràng buộc với một cổng
(port number) để chờ nhận yêu cầu từ phía client.
o Tiếp đến phía client yêu cầu server bằng cách tạo một Socket
TCP trên máy kèm với địa chỉ IP và port number của tiến trình
lOMoARcPSD| 61549570
tương ứng trên máy server. Khi client tạo Socket, client TCP
tạo liên kết với server TCP chờ chấp nhận kết nối tserver.
o TCP cung cấp dịch vụ truyền dòng tin cậy thứ tgiữa
client server, giữa máy chủ và máy nhận chcó 1 địa chỉ IP
duy nhất. Thêm vào đó, mỗi thông điệp truyền đi đều xác
nhận trả về.
2. Kiến thức về quản lý vào ra và hàm select()
- Trong lập trình nói chung và lập trình mạng nói riêng, quản lý vào
ra (I/O)một yếu tố quan trọng để đảm bảo hiệu suất và tính khả
dụng của các ứng dụng. Khi một chương trình cần phải giao tiếp với
nhiều nguồn dữ liệu (như nhiều kết nối mạng hoặc tệp tin), việc chờ
đợi các thao tác I/O hoàn tất thể làm giảm hiệu suất nếu không
được quản lý đúng cách.
- Một trong những công cụ mạnh mẽ để giải quyết vấn đề này trong
lập trình mạng hàm select(). Hàm select() cho phép kiểm tra
nhiều file descriptor (bao gồm các socket) để xác định xem sự
kiện I/O nào cần xử lý, chẳng hạn như dữ liệu sẵn để đọc hoặc
socket thghi dữ liệu. Điều này giúp chương trình thể xử
nhiều kết nối đồng thời mà không cần phải sử dụng nhiều luồng, tối
ưu hóa tài nguyên và tăng cường khả năng đáp ứng trong các ứng
dụng mạng lớn. o Hàm select() yêu cầu kernel kiểm tra đồng thời
nhiều socket để xem chúng dữ liệu chờ được recv(), hoặc nếu bạn
thể send() dữ liệu đến chúng không bị chặn, hoặc nếu
ngoại lệ nào đó xảy ra. o Kernel sẽ đánh thức qtrình chỉ khi một
hoặc nhiều sự kiện xảy ra hoặc khi một khoảng thời gian xác định
đã trôi qua.
3. Kiến thức về QT trong C++
- QT một framework phát triển phần mềm đa nền tảng phổ biến,
được sử dụng để xây dựng các ứng dụng GUI, các chương trình
command line còn các ứng dụng của hệ thống nhúng. QT được
rất nhiều lập trình viên ưa thích và sử dụng bởi độ mạnh mẽ
linh hoạt của nó. Đồng thời, QT cũng hỗ trợ nhiều nền tảng như
Windows, macOS, Linux, iOS, Android, v.v...
- Trong bài tập lớn bộ môn Thực hành Lập trình mạng này, chúng em
chọn QT vì QT cung cấp rất nhiều các công cụ lớp hỗ trợ giúp
việc phát triển của trò chơi trở nên dễ dàng hơn như QTcpSocket.
4. Sử dụng SQLite3 trong quản lý dữ liệu trò chơi
lOMoARcPSD| 61549570
- SQLite3 là một hệ quản trị cơ sở dữ liệu quan hệ (RDBMS) nhẹ, dễ
sử dụng, phổ biến, đặc biệt trong các ứng dụng di động, máy
tính cá nhân và các ứng dụng nhúng. Sau đây là 1 số lí do chúng em
chọn SQLite3 để làm quản lý cơ sở dữ liệu cho ứng dụng Battleship
Online:
o SQLite3 không yêu cầu một máy chủ riêng biệt, tức hoạt
động như một thư viện trong ứng dụng. sở dữ liệu được
lưu trữ trong một tệp đơn, giúp giảm chi phí tài nguyên và dễ
dàng tích hợp vào các ứng dụng nhúng hoặc di động không
cần thiết lập phức tạp.
o Không giống như các hệ quản trị sở dữ liệu như MySQL
hay PostgreSQL, SQLite3 không cần phải cài đặt và cấu hình
một máy chủ cơ sở dữ liệu. Chỉ cần tích hợp thư viện SQLite
vào ứng dụng là có thể sử dng cơ sở dữ liệu ngay lập tức.
o Dữ liệu của SQLite được lưu trữ trong một tệp duy nhất.
Điều này khiến SQLite rất dễ di chuyển giữa các hthống
hoặc các nền tảng khác nhau không gặp phải vấn đề tương
thích. Dữ liệu thể sao chép hoặc di chuyển mà không gặp
phải sự phụ thuộc vào cấu hình phần cứng hay phần mềm.
- Từ các lí do trên, chúng em đã chọn SQLite3 hệ quản trị này rất
phù hợp với yêu cầu của trò chơi Battleship.
CHƯƠNG III: Kiến tc mạng
Ứng dụng nhóm em thực hiện theo hình Multi Client-Server với 1 server
tổng. Server tổng để thực hiện truyền thông các chức năng bản của ứng dụng
như đăng nhập, đăng ký, chơi nhanh hoặc thách đấu 1 người chơi khác.
Sơ đồ state machine của game Battleship
Dưới đây là chi tiết cụ thể về kiến trúc mạng cho server game:
lOMoARcPSD| 61549570
Server tổng thực hiện gửi nhận thông điệp với các client (Multiclient)
thông qua giao thức truyền thông TCP để đảm bảo thông tin được truyền đi một
cách đầy đủ và chính xác nhất. Sẽ có 2 dạng thông điệp là Response (thông điệp
từ server trả về cho một hoặc nhiều client) và Request (thông điệp từ một client
gửi lên server). Mỗi dạng thông điệp này sẽ các loại khác nhau (sử dụng enum
trong C++ để phân loại) tương ứng với việc thực hiện các chức năng khác nhau.
Dưới đây là bảng liệt kê các loại thông điệp:
Thông điệp
Mô tả
Tham số
Request
Tham số Response
REQUEST_SIGN_IN
Đăng
nhập
-request_type
-user.username
-user.password
Nếu đăng nhập thành công:
-response.status:STATUS_OK -
response.message thông báo đăng
nhập thành công
-payload(chứa thông tin user)
Nếu đăng nhập thất bại:
-
response.status:STATUS_ERROR
-response.message thông báo loại
lỗi
REQUEST_SIGN_UP
Đăng
-request_type
-user.username
-user.password
Nếu đăng ký thành công:
-response.status:STATUS_OK -
response.message thông báo đăng
ký thành công
Nếu đăng thất bại: tương tự như
đăng nhập thất bại.
REQUEST_SIGN_OUT
Đăng
xuất
-request_type
-user
-response.status: STATUS_OK -
response.message thông báo đăng
xuất thành công
REQUEST_GET_USERS
Tìm tất
cả user
-request_type
-user
-response.status: STATUS_OK -
response.message: thông báo
thành công
-List các user
lOMoARcPSD| 61549570
REQUEST_GET_MATCHES
Tìm
trận
-request_type
-user
Trong trường hợp m trận thành
công:
-response.status: STATUS_OK -
response.message: thông báo
thành công
-khởi tạo match mới Trong
trường hợp thất bại: -
response.status:
STATUS_ERROR
-response.message: Thông báo
loại lỗi
REQUEST_GET_MOVES
Lấy
thông
tin về
nước đi
-request_type
-user
-move.matchID
Trong trường hợp tìm thành công:
-response.status: STATUS_OK -
response.message: thông báo
thành công
-response.move: thông báo về
nước đi được người dùng yêu cầu
Trong trường hợp thất bại: -
response.status:
STATUS_ERROR
-response.message: Thông báo
loại lỗi
REQUEST_CHALLENGE
Chuyển
lời mời
thách
-request_type -
user1: người
thách đấu
Trong trường hợp chuyển lời mời
thách đấu thành công:
-response.status: STATUS_OK
đấu
-user2: người
được thách đấu
-response.message: thông báo
thành công
Trong trường hợp thất bại: -
response.status:
STATUS_ERROR
-response.message: Thông o
loại lỗi
REQUEST_ACCEPT
/REQUEST_DECLINE
Chấp
nhận
hoặc từ
chối lời
mời
thách
đấu
-request_type -
user: người được
thách đấu -user2:
người thách đấu
-response.status: STATUS_OK -
response.message: thông báo chấp
nhận hoặc từ chối
lOMoARcPSD| 61549570
REQUEST_READY
Thông
báo với
server
đã
chuẩn
bị xong
-request_type -
user: người click
nút ok
-response.status: STATUS_OK
REQUEST_SHOT
Yêu
cầu bắn
1 ô cờ
của đối
phương
-request_type
-user: người bắn
-move: thông tin
nước đi
Thành công:
-response.status: STATUS_OK
-response.message: Thông báo -
move.cell: trạng thái của được
chọn
-match: thông tin về lượt bàn cờ
của người chơi
Nếu người chơi thắng cuộc: -
response.status: STATUS_OK -
response.type:
REQUEST_GAME_OVER
-response.message: Thông báo
-response.user: người thắng cuộc
-response.user2: người thua Nếu
người chơi thoát giữa chừng hoặc
đầu hàng:
-Tương tự trường hợp thắng cuộc,
khác biệt response.type Thất
bại:
-response.status:
STATUS_ERROR
-response.message: Thông báo
REQUEST_CHAT
Gửi
-request_type
-response.status: STATUS_OK
đoạn
chat
đến đối
thủ
-user: người gửi
-
request.message
:
Thông điệp chat
-response.message: thông báo
thành công
REQUEST_QUICK_MATC
H
Tìm
trận
nhanh
-request_type
-user
-response.status: STATUS_OK -
response.message: thông o
thành công
lOMoARcPSD| 61549570
REQUEST_CANCEL
Hủy
thao tác
như
chờ tìm
trận,
đầu
hàng
-request_type
-user
-response.status: STATUS_OK
Để thuận tiện trong việc tạo và gửi thông điệp, nhóm bọn em đã tạo ra các
struct sau:
- Struct User: Lưu trữ thông tin người dùng
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Struct Message: lưu trữ tin nhắn server phản hồi đến client
-
-
-
-
-
- Struct Move: chứa các thông tin về nước đi, trận đấu trạng thái
của ô cờ
-
-
-
-
-
-
lOMoARcPSD| 61549570
-
-
-
-
-
-
-
-
-
-
- Struct Match: chứa thông tin về 1 ván đấu đang diễn ra
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Struct Request: chứa thông tin về request
-
-
-
-
-
-
-
-
-
-
-
- Struct Response: chứa các thông tin về phản hồi của server
-
-
-
-
lOMoARcPSD| 61549570
-
-
-
CHƯƠNG IV: Cơ chế game
Trong chương này, bọn em sẽ giới thiệu về chế của game cũng như chức
năng nâng cao đã làm được:
- Cơ chế đặt và bắn tàu:
o Người chơi thể đặt tàu theo các hướng ngang hoặc dọc
tùy theo ý muốn của mình, miễn là hợp lệ.
o Khi người chơi bắn trúng tàu địch, ô bị bắn sẽ hiển thị
màu đỏ, nếu trượt là màu xanh. o 2 người chơi luân phiên
với nhau đến khi có người thắng cuộc.
- Một số hình ảnh demo:
- Chức năng nâng cao: chat o 2 người chơi khi chơi với nhau có thể
chat tùy vào mục đích của mình như cà khịa hay cổ vũ, v.v...
- Một số hình ảnh demo:
lOMoARcPSD| 61549570
CHƯƠNG V: Phân chia công việc
Dưới đây bảng phân công công việc ý tưởng thực hiện của nhóm
chúng em:
Chức năng
Người thực hiện
Ý tưởng và cách thực hiện
Điểm
Xử lý truyền dòng
Đỗ Mạnh Phương
Em thực hiện xử lý truyền
dòng tương tự như các bài
1
tập tuần, kết hợp thêm các
protocol đã liệt chương
3 nhằm mục đích chặt chẽ và
dễ hiểu khi code và sử dụng
Cài đặt chế
vào/ra socket trên
server
Đỗ Mạnh Phương
Lúc đầu em định chọn dùng
pthread, nhưng do phức tạp
khó xử n đồng thời
nhóm em đã loại bỏ chức
năng thời gian thực nên em
quyết định chọn select do số
client trong dự án này rất nhỏ,
chỉ tầm 200 client
2
lOMoARcPSD| 61549570
Đăng quản
lý tài khoản
Đỗ Mạnh Phương
Em thực hiện tương tự như
các bài tập tuần, đồng thời
thêm các chế quản như
tránh đăng nhập trùng tài
khoản hoặc tài khoản rỗng
mật khẩu
2
Đăng nhập
quản lý phiên
Đỗ Mạnh Phương
Em thực hiện đăng nhập
tương tự như các bài tập tuần,
còn về quản phiên, nhóm
chúng em đã thêm 1 map
client nhằm quản cách
client hiện tại đang kết nối
với server nên khi đăng nhập
trùng tài khoản sẽ trả về
thông báo lỗi
2
Cung cấp danh
sách người chơi
sẵn sàng
Đỗ Mạnh Phương
Đối với chức năng này, em
dùng map client trên để lấy
thông tin truyền về client
hiển thị ra danh sách người
chơi đang sẵn sàng
2
Chuyển lời mời
thách đấu
Đỗ Mạnh Phương
Em đã thực hiện chức năng
này theo cách sau:
+Khi người chơi chuyển lời
mời thách đấu, client sẽ tạo 1
request có header là
REQUEST_CHALLENGE,
trong request này User sẽ
người thách đấu và User2 sẽ
2
lOMoARcPSD| 61549570
người được thách đấu.
+Server sẽ kiểm tra bằng
cách check các client xem có
client nào tồn tại người chơi
được thách đấu không. +Nếu
có, kiểm tra xem người chơi
đó trong match nào
không. Nếu đang trong
match sẽ trả về thông báo lỗi,
nếu không sẽ tạo lời mời
thách đấu gửi đến người
chơi kia.
Chấp nhận, từ
chối lời mời thách
đấu
Đỗ Mạnh Phương
Em đã thực hiện chức năng
này theo cách sau: +Người
chơi nhận được
request sẽ có 2 lựa chọn là
Yes hoặc No
+Nếu chọn Yes, Server sẽ
khởi tạo 1 match mới với 2
người chơi đã thách đấu
nhau.
+Nếu chọn No, Server sẽ hủy
lời mời và gửi về client thách
đấu response
REQUEST_DECLINE
1
lOMoARcPSD| 61549570
Xây dựng hệ thống
tính điểm
Đỗ Mạnh Phương
Em đã thực hiện chức năng
này như sau:
+Khi 2 người chơi chơi với
nhau, người chơi thắng sẽ
được cộng nhiều elo hơn nếu
đối thủ rank cao hơn mình,
người thua sẽ bị trừ ít elo hơn
nếu đối thủ elo cao hơn mình,
nếu 2 người chơi bằng rank
nhau sẽ được cộng hoặc trừ
10 điểm. Tất nhiên chúng em
đã ngăn việc để elo giảm
xuống dưới 0 điểm, mức
elo nhỏ hơn 0 không hợp
lệ.
1
+Khi quickmatch, người chơi
sẽ được ghép cặp với player
chênh mình tối đa 20 elo,
điều này thể gây ra việc 2
người chơi chênh điểm nhau
sẽ bị chờ đợi vô thời hạn, em
chưa xử lý được lỗi này.
Xác định kết quả
ván cờ
Đỗ Mạnh Phương
Khi người chơi đang trong
game, sẽ 3 trường hợp sau:
+1 người chơi bắn trúng hết
tàu của đối phương, khi đó
server thông báo kết thúc
game và tuyên bố người chơi
thắng cuộc.
+Khi 1 người chơi thoát đột
ngột hoặc đầu hàng, server sẽ
xử tương tự, người bị x
thua người đầu hàng hoặc
thoát game.
1
lOMoARcPSD| 61549570
Lưu thông tin ván
đấu và replay
Đỗ Mạnh Phương
Khi xác định kết quả ván cờ
xong, server sẽ lưu kết quả
ván đấu vào s dữ liệu
SQLite3, đồng thời tạo ra 1
response hỏi người chơi bị
thua muốn tái đấu không,
nếu người chơi đồng ý, server
sẽ thực hiện phần còn lại
giống như cách xử chuyển
lời mời thách đấu
2
Tổng điểm: 31 điểm Đóng
góp:
- Đỗ Mạnh Phương: 50%(16 điểm)
- Lê Quang Khải: 50%(15 điểm)

Preview text:

lOMoAR cPSD| 61549570
ĐẠI HỌC BÁCH KHOA HÀ NỘI
Trường Công nghệ thông tin và Truyền thông
------------------🙡🕮🙣------------------
BÁO CÁO BÀI TẬP LỚN MÔN LẬP TRÌNH MẠNG
Đề tài: Xây dựng trò chơi theo lượt Battleship Online Sinh viên thực hiện:
Đỗ Mạnh Phương 20225660 Lê Quang Khải 20225638 Giảng viên hướng dẫn: TS Đặng Tuấn Linh
Hà Nội, ngày 31 tháng 12 năm 2024 lOMoAR cPSD| 61549570 MỤC LỤC
I. Chương I: Giới thiệu đề tài
1. Sơ lược về đề tài 2. Bố cục báo cáo
II. Chương II: Cơ sở lý thuyết
1. Kiến thức cơ bản về lập trình socket TCP
2. Kiến thức về quản lý vào ra và hàm select()
3. Kiến thức về QT trong C++
4. Sử dụng SQLite3 quản lý dữ liệu người chơi
III. Chương III: Kiến trúc mạng 1. Server
IV. Chương IV: Cơ chế game
1. Cơ chế đặt tàu và bắn tàu
2. Chức năng nâng cao : Chat trong game
V. Chương V: Phân chia công việc VI. Chương VI: Kết luận
CHƯƠNG I: Giới thiệu đề tài
1. Sơ lược về đề tài
Đã từ lâu, Battleship là một trò chơi chiến thuật nổi tiếng, trong đó hai người
chơi cạnh tranh để đánh bại đối phương bằng cách tìm và đánh chìm các tàu chiến
của họ. Mỗi người chơi sẽ đặt các tàu chiến của mình trên một bảng lưới (grid)
10x10 và lần lượt phát tín hiệu bằng cách "bắn" vào các tọa độ trên bảng đối
phương. Mục tiêu của trò chơi là xác định vị trí các tàu đối thủ và bắn trúng chúng
trước khi đối thủ làm điều tương tự. Trò chơi không chỉ đòi hỏi sự tính toán chiến
lược mà còn yêu cầu khả năng phán đoán và sự may mắn. Với sự hấp dẫn và thử
thách trong việc đối kháng qua các lượt đi, Battleship đã trở thành một trò chơi
kinh điển trong làng boardgame, mang lại những phút giây thư giãn và kịch tính cho người chơi.
Vậy nên bọn em đã quyết định tái hiện lại trò chơi này trên máy tính bằng
giao diện đồ họa kết hợp cùng các kiến thức đã học được trong bộ môn Thực hành Lập trình mạng. lOMoAR cPSD| 61549570 2. Bố cục báo cáo
Chương 1: giới thiệu đề tài
Ở chương này nhóm em sẽ tóm tắt chủ đề mà nhóm thực hiện và nêu tóm tắt
mục đích của từng chương để thầy có thể khái quát được báo cáo gồm những gì và nói về gì.
Chương 2: Cơ sở lý thuyết
Nhóm em sẽ nêu ra các lý thuyết, công nghệ mà nhóm em đã tìm hiểu và sử
dụng để xây dựng project này. Nhóm em sẽ nêu tóm lược khái niệm và lý do sử
dụng, phần implementation sẽ được đề cập trong các chương sau.
Chương 3: Kiến trúc mạng
Trong chương này, nhóm em sẽ khái quát tổng quan về kiến trúc mạng, cách
thức xử lý truyền dòng cũng như là cơ chế vào ra socket theo mô hình clientserver
được thực hiện trong ứng dụng.
Chương 4: Cơ chế của game
Trong chương này em sẽ giới thiệu các tính năng mà game có thể cho thầy
một cái nhìn khái quát về độ phức tạp của game mà nhóm em đã phát triển. Về
chi tiết hình ảnh và thao tác chúng em sẽ nêu đầy đủ trong video demo.
Chương 5: Nội dung phân chia công việc
Chương này sẽ bao gồm bảng chứa danh sách các công việc, lượng điểm ước
chừng và người được phân công. Ngoài ra ở mỗi công việc, nhóm em cũng sẽ nêu
rõ nội dung những công việc đó là gì để thầy có thể đánh giá xem lượng điểm
dành cho đầu việc đó có hợp lý hay không. Chương 6: Kết luận
Bao gồm các tài liệu tham khảo và lời kết. lOMoAR cPSD| 61549570
CHƯƠNG II: Cơ sở lý thuyết
Dưới đây là 1 số cơ sở lý thuyết và nền tảng chúng em đã áp dụng vào ứng dụng của mình:
1. Kiến thức cơ bản về lập trình socket và TCP
- Socket là giao diện lập trình ứng dụng mạng được dùng để truyền
và nhận dữ liệu trên internet. Giữa hai chương trình chạy trên mạng
cần có một liên kết giao tiếp hai chiều, hay còn gọi là two-way
communication để kết nối 2 process trò chuyện với nhau. Điểm cuối
(endpoint) của liên kết này được gọi là socket.
o Socket định danh ứng dụng mà dữ liệu sẽ được gửi tới thông
qua sự ràng buộc với 1 cổng port để tiến hành kết nối giữa client và server.
o Ưu điểm của socket: tương thích với hầu hết các hệ điều
hành, từ Window cho đến Linux và Mac OS X... Ngoài ra,
socket còn có thể kết hợp được với rất nhiều ngôn ngữ lập
trình như C, C++, C#, Java. Người dùng cũng có thể chạy
nhiều socket liên tục cùng một lúc được, giúp nâng cao hiệu
suất làm việc cũng như tiết kiệm thời gian hơn.
- TCP là 1 giao thức truyền thông trong bộ giao thức TCP/IP, được
sử dụng để đảm bảo việc truyền tải dữ liệu giữa các thiết bị trên
mạng một cách tin cậy và có trật tự. TCP đảm bảo rằng dữ liệu được
truyền từ nguồn đến đích mà không bị mất mát, bị sai thứ tự, hoặc
bị hỏng. Giao thức này là kết nối hướng, có nghĩa là trước khi truyền
tải dữ liệu, một kết nối phải được thiết lập giữa hai thiết bị thông qua
quá trình gọi là 3-way handshake. Dưới đây là 1 số đặc trưng của
việc truyền thông bằng TCP:
o Tạo luồng dữ liệu hai chiều, đáng tin cậy, có trình tự và không
trùng lặp, dữ liệu chỉ được gửi/nhận khi có đã có liên kết.
Trong C++ sử dụng hàm socket() để tạo và sử dụng socket.
o Cần có liên kết 2 chiều trước khi server và client có thể trao
đổi thông điệp với nhau.
o Ban đầu, phía server tạo socket được ràng buộc với một cổng
(port number) để chờ nhận yêu cầu từ phía client.
o Tiếp đến phía client yêu cầu server bằng cách tạo một Socket
TCP trên máy kèm với địa chỉ IP và port number của tiến trình lOMoAR cPSD| 61549570
tương ứng trên máy server. Khi client tạo Socket, client TCP
tạo liên kết với server TCP và chờ chấp nhận kết nối từ server.
o TCP cung cấp dịch vụ truyền dòng tin cậy và có thứ tự giữa
client và server, giữa máy chủ và máy nhận chỉ có 1 địa chỉ IP
duy nhất. Thêm vào đó, mỗi thông điệp truyền đi đều có xác nhận trả về.
2. Kiến thức về quản lý vào ra và hàm select()
- Trong lập trình nói chung và lập trình mạng nói riêng, quản lý vào
ra (I/O) là một yếu tố quan trọng để đảm bảo hiệu suất và tính khả
dụng của các ứng dụng. Khi một chương trình cần phải giao tiếp với
nhiều nguồn dữ liệu (như nhiều kết nối mạng hoặc tệp tin), việc chờ
đợi các thao tác I/O hoàn tất có thể làm giảm hiệu suất nếu không
được quản lý đúng cách.
- Một trong những công cụ mạnh mẽ để giải quyết vấn đề này trong
lập trình mạng là hàm select(). Hàm select() cho phép kiểm tra
nhiều file descriptor (bao gồm các socket) để xác định xem có sự
kiện I/O nào cần xử lý, chẳng hạn như dữ liệu có sẵn để đọc hoặc
socket có thể ghi dữ liệu. Điều này giúp chương trình có thể xử lý
nhiều kết nối đồng thời mà không cần phải sử dụng nhiều luồng, tối
ưu hóa tài nguyên và tăng cường khả năng đáp ứng trong các ứng
dụng mạng lớn. o Hàm select() yêu cầu kernel kiểm tra đồng thời
nhiều socket để xem chúng có dữ liệu chờ được recv(), hoặc nếu bạn
có thể send() dữ liệu đến chúng mà không bị chặn, hoặc nếu có
ngoại lệ nào đó xảy ra. o Kernel sẽ đánh thức quá trình chỉ khi một
hoặc nhiều sự kiện xảy ra hoặc khi một khoảng thời gian xác định đã trôi qua.
3. Kiến thức về QT trong C++
- QT là một framework phát triển phần mềm đa nền tảng phổ biến,
nó được sử dụng để xây dựng các ứng dụng GUI, các chương trình
command line và còn có các ứng dụng của hệ thống nhúng. QT được
rất nhiều lập trình viên ưa thích và sử dụng bởi độ mạnh mẽ
và linh hoạt của nó. Đồng thời, QT cũng hỗ trợ nhiều nền tảng như
Windows, macOS, Linux, iOS, Android, v.v...
- Trong bài tập lớn bộ môn Thực hành Lập trình mạng này, chúng em
chọn QT vì QT cung cấp rất nhiều các công cụ và lớp hỗ trợ giúp
việc phát triển của trò chơi trở nên dễ dàng hơn như QTcpSocket.
4. Sử dụng SQLite3 trong quản lý dữ liệu trò chơi lOMoAR cPSD| 61549570
- SQLite3 là một hệ quản trị cơ sở dữ liệu quan hệ (RDBMS) nhẹ, dễ
sử dụng, và phổ biến, đặc biệt là trong các ứng dụng di động, máy
tính cá nhân và các ứng dụng nhúng. Sau đây là 1 số lí do chúng em
chọn SQLite3 để làm quản lý cơ sở dữ liệu cho ứng dụng Battleship Online:
o SQLite3 không yêu cầu một máy chủ riêng biệt, tức là nó hoạt
động như một thư viện trong ứng dụng. Cơ sở dữ liệu được
lưu trữ trong một tệp đơn, giúp giảm chi phí tài nguyên và dễ
dàng tích hợp vào các ứng dụng nhúng hoặc di động mà không
cần thiết lập phức tạp.
o Không giống như các hệ quản trị cơ sở dữ liệu như MySQL
hay PostgreSQL, SQLite3 không cần phải cài đặt và cấu hình
một máy chủ cơ sở dữ liệu. Chỉ cần tích hợp thư viện SQLite
vào ứng dụng là có thể sử dụng cơ sở dữ liệu ngay lập tức.
o Dữ liệu của SQLite được lưu trữ trong một tệp duy nhất.
Điều này khiến SQLite rất dễ di chuyển giữa các hệ thống
hoặc các nền tảng khác nhau mà không gặp phải vấn đề tương
thích. Dữ liệu có thể sao chép hoặc di chuyển mà không gặp
phải sự phụ thuộc vào cấu hình phần cứng hay phần mềm.
- Từ các lí do trên, chúng em đã chọn SQLite3 vì hệ quản trị này rất
phù hợp với yêu cầu của trò chơi Battleship.
CHƯƠNG III: Kiến trúc mạng
Ứng dụng nhóm em thực hiện theo mô hình Multi Client-Server với 1 server
tổng. Server tổng để thực hiện truyền thông các chức năng cơ bản của ứng dụng
như đăng nhập, đăng ký, chơi nhanh hoặc thách đấu 1 người chơi khác.
Sơ đồ state machine của game Battleship
Dưới đây là chi tiết cụ thể về kiến trúc mạng cho server game: lOMoAR cPSD| 61549570
Server tổng thực hiện gửi và nhận thông điệp với các client (Multiclient)
thông qua giao thức truyền thông TCP để đảm bảo thông tin được truyền đi một
cách đầy đủ và chính xác nhất. Sẽ có 2 dạng thông điệp là Response (thông điệp
từ server trả về cho một hoặc nhiều client) và Request (thông điệp từ một client
gửi lên server). Mỗi dạng thông điệp này sẽ có các loại khác nhau (sử dụng enum
trong C++ để phân loại) tương ứng với việc thực hiện các chức năng khác nhau.
Dưới đây là bảng liệt kê các loại thông điệp: Thông điệp Mô tả Tham số Tham số Response Request REQUEST_SIGN_IN Đăng -request_type
Nếu đăng nhập thành công: nhập -user.username -response.status:STATUS_OK - -user.password
response.message thông báo đăng nhập thành công
-payload(chứa thông tin user)
Nếu đăng nhập thất bại: - response.status:STATUS_ERROR
-response.message thông báo loại lỗi REQUEST_SIGN_UP Đăng -request_type
Nếu đăng ký thành công: ký -user.username -response.status:STATUS_OK - -user.password
response.message thông báo đăng ký thành công
Nếu đăng ký thất bại: tương tự như đăng nhập thất bại. REQUEST_SIGN_OUT Đăng -request_type -response.status: STATUS_OK - xuất -user
response.message thông báo đăng xuất thành công REQUEST_GET_USERS Tìm tất -request_type -response.status: STATUS_OK - cả user -user response.message: thông báo thành công -List các user lOMoAR cPSD| 61549570 REQUEST_GET_MATCHES Tìm -request_type
Trong trường hợp tìm trận thành trận -user công: -response.status: STATUS_OK - response.message: thông báo thành công
-khởi tạo match mới Trong
trường hợp thất bại: - response.status: STATUS_ERROR
-response.message: Thông báo loại lỗi REQUEST_GET_MOVES Lấy -request_type
Trong trường hợp tìm thành công: thông -user -response.status: STATUS_OK -
tin về -move.matchID response.message: thông báo nước đi thành công
-response.move: thông báo về
nước đi được người dùng yêu cầu
Trong trường hợp thất bại: - response.status: STATUS_ERROR
-response.message: Thông báo loại lỗi REQUEST_CHALLENGE
Chuyển -request_type - Trong trường hợp chuyển lời mời lời mời user1:
người thách đấu thành công: thách thách đấu -response.status: STATUS_OK đấu -user2:
người -response.message: thông báo được thách đấu thành công
Trong trường hợp thất bại: - response.status: STATUS_ERROR
-response.message: Thông báo loại lỗi REQUEST_ACCEPT Chấp
-request_type - -response.status: STATUS_OK - /REQUEST_DECLINE nhận
user: người được response.message: thông báo chấp
hoặc từ thách đấu -user2: nhận hoặc từ chối
chối lời người thách đấu mời thách đấu lOMoAR cPSD| 61549570 REQUEST_READY
Thông -request_type - -response.status: STATUS_OK
báo với user: người click server nút ok đã chuẩn bị xong REQUEST_SHOT Yêu -request_type Thành công:
cầu bắn -user: người bắn -response.status: STATUS_OK
1 ô cờ -move: thông tin -response.message: Thông báo - của đối nước đi
move.cell: trạng thái của được phương chọn
-match: thông tin về lượt và bàn cờ của người chơi
Nếu có người chơi thắng cuộc: - response.status: STATUS_OK - response.type: REQUEST_GAME_OVER
-response.message: Thông báo
-response.user: người thắng cuộc
-response.user2: người thua Nếu
người chơi thoát giữa chừng hoặc đầu hàng:
-Tương tự trường hợp thắng cuộc,
khác biệt ở response.type Thất bại: -response.status: STATUS_ERROR
-response.message: Thông báo REQUEST_CHAT Gửi -request_type -response.status: STATUS_OK đoạn
-user: người gửi -response.message: thông báo chat - thành công đến đối request.message thủ : Thông điệp chat REQUEST_QUICK_MATC Tìm -request_type -response.status: STATUS_OK - H trận -user response.message: thông báo nhanh thành công lOMoAR cPSD| 61549570 REQUEST_CANCEL Hủy -request_type -response.status: STATUS_OK thao tác -user như chờ tìm trận, đầu hàng
Để thuận tiện trong việc tạo và gửi thông điệp, nhóm bọn em đã tạo ra các struct sau:
- Struct User: Lưu trữ thông tin người dùng - struct User {
- char username[255]{};
- char password[255]{}; - int elo{0}; - - User() = default; -
- User(char* username, char* password, int elo) : elo(elo) {
- strncpy(this->username, username, sizeof(this- >username));
- strncpy(this->password, password, sizeof(this- >password)); - } -
- bool operator==(const User& other) const {
- return strcmp(username, other.username) == 0; - } - };
- Struct Message: lưu trữ tin nhắn server phản hồi đến client - struct Message {
- char message[2048]{}; - - Message() = default; - };
- Struct Move: chứa các thông tin về nước đi, trận đấu và trạng thái của ô cờ - enum CellType { - CELL_EMPTY, - CELL_MISS, - CELL_HIT, - CELL_SHIP, - }; lOMoAR cPSD| 61549570 - - struct Move { - int matchID{}; - int row{}; - int col{}; - int player{}; - CellType type{}; - - Move() = default; - };
- Struct Match: chứa thông tin về 1 ván đấu đang diễn ra - struct Match { - uint64_t id{}; - User player1{}; - User player2{}; - int status1{}; - int status2{}; - int turn{}; - int winner{}; - int point1{}; - int point2{};
- CellType board1[BOARD_SIZE][BOARD_SIZE]{};
- CellType board2[BOARD_SIZE][BOARD_SIZE]{};
- CellType init1[BOARD_SIZE][BOARD_SIZE]{};
- CellType init2[BOARD_SIZE][BOARD_SIZE]{}; - - Match() = default; - };
- Struct Request: chứa thông tin về request - struct Request { - RequestType type{}; - User user{}; - User user2{}; - Move move{}; - Message message{}; - int rShips[5]{}; - int cShips[5]{}; - int oriShips[5]{}; - }; -
- Struct Response: chứa các thông tin về phản hồi của server - struct Response { - RequestType type{}; - Status status{}; - char message[255]{}; lOMoAR cPSD| 61549570 - User user{}; - User user2{}; - }; CHƯƠNG IV: Cơ chế game
Trong chương này, bọn em sẽ giới thiệu về cơ chế của game cũng như chức
năng nâng cao đã làm được:
- Cơ chế đặt và bắn tàu:
o Người chơi có thể đặt tàu theo các hướng ngang hoặc dọc
tùy theo ý muốn của mình, miễn là hợp lệ.
o Khi người chơi bắn trúng tàu địch, ô bị bắn sẽ hiển thị là
màu đỏ, nếu trượt là màu xanh. o 2 người chơi luân phiên
với nhau đến khi có người thắng cuộc.
- Một số hình ảnh demo:
- Chức năng nâng cao: chat o 2 người chơi khi chơi với nhau có thể
chat tùy vào mục đích của mình như cà khịa hay cổ vũ, v.v...
- Một số hình ảnh demo: lOMoAR cPSD| 61549570
CHƯƠNG V: Phân chia công việc
Dưới đây là bảng phân công công việc và ý tưởng thực hiện của nhóm chúng em: Chức năng Người thực hiện
Ý tưởng và cách thực hiện Điểm
Xử lý truyền dòng Đỗ Mạnh Phương Em thực hiện xử lý truyền 1
dòng tương tự như các bài
tập tuần, kết hợp thêm các
protocol đã liệt kê ở chương
3 nhằm mục đích chặt chẽ và
dễ hiểu khi code và sử dụng
Cài đặt cơ chế Đỗ Mạnh Phương Lúc đầu em định chọn dùng 2 vào/ra socket trên
pthread, nhưng do phức tạp server
và khó xử lý hơn đồng thời
nhóm em đã loại bỏ chức
năng thời gian thực nên em
quyết định chọn select do số
client trong dự án này rất nhỏ, chỉ tầm 200 client lOMoAR cPSD| 61549570
Đăng ký và quản Đỗ Mạnh Phương Em thực hiện tương tự như 2 lý tài khoản
các bài tập tuần, đồng thời
thêm các cơ chế quản lý như
tránh đăng nhập trùng tài
khoản hoặc tài khoản rỗng mật khẩu
Đăng nhập và Đỗ Mạnh Phương Em thực hiện đăng nhập 2 quản lý phiên
tương tự như các bài tập tuần,
còn về quản lý phiên, nhóm chúng em đã thêm 1 map
client nhằm quản lý cách
client hiện tại đang kết nối
với server nên khi đăng nhập
trùng tài khoản sẽ trả về thông báo lỗi
Cung cấp danh Đỗ Mạnh Phương Đối với chức năng này, em 2 sách người chơi
dùng map client trên để lấy sẵn sàng
thông tin và truyền về client
hiển thị ra danh sách người chơi đang sẵn sàng
Chuyển lời mời Đỗ Mạnh Phương Em đã thực hiện chức năng 2 thách đấu này theo cách sau:
+Khi người chơi chuyển lời
mời thách đấu, client sẽ tạo 1 request có header là REQUEST_CHALLENGE,
trong request này User sẽ là
người thách đấu và User2 sẽ lOMoAR cPSD| 61549570
là người được thách đấu.
+Server sẽ kiểm tra bằng
cách check các client xem có
client nào tồn tại người chơi
được thách đấu không. +Nếu
có, kiểm tra xem người chơi đó có trong match nào không. Nếu đang trong
match sẽ trả về thông báo lỗi,
nếu không sẽ tạo lời mời
thách đấu và gửi đến người chơi kia. Chấp nhận, từ
Đỗ Mạnh Phương Em đã thực hiện chức năng 1 chối lời mời thách
này theo cách sau: +Người đấu chơi nhận được
request sẽ có 2 lựa chọn là Yes hoặc No
+Nếu chọn Yes, Server sẽ
khởi tạo 1 match mới với 2
người chơi đã thách đấu nhau.
+Nếu chọn No, Server sẽ hủy
lời mời và gửi về client thách đấu response REQUEST_DECLINE lOMoAR cPSD| 61549570
Xây dựng hệ thống Đỗ Mạnh Phương Em đã thực hiện chức năng 1 tính điểm này như sau:
+Khi 2 người chơi chơi với
nhau, người chơi thắng sẽ
được cộng nhiều elo hơn nếu
đối thủ rank cao hơn mình,
người thua sẽ bị trừ ít elo hơn
nếu đối thủ elo cao hơn mình,
nếu 2 người chơi bằng rank
nhau sẽ được cộng hoặc trừ
10 điểm. Tất nhiên chúng em
đã ngăn việc để elo giảm
xuống dưới 0 điểm, vì mức
elo nhỏ hơn 0 là không hợp lệ.
+Khi quickmatch, người chơi
sẽ được ghép cặp với player
chênh mình tối đa 20 elo,
điều này có thể gây ra việc 2
người chơi chênh điểm nhau
sẽ bị chờ đợi vô thời hạn, em
chưa xử lý được lỗi này.
Xác định kết quả Đỗ Mạnh Phương Khi người chơi đang trong 1 ván cờ
game, sẽ có 3 trường hợp sau:
+1 người chơi bắn trúng hết
tàu của đối phương, khi đó
server thông báo kết thúc
game và tuyên bố người chơi thắng cuộc.
+Khi 1 người chơi thoát đột
ngột hoặc đầu hàng, server sẽ
xử lý tương tự, người bị xử
thua là người đầu hàng hoặc thoát game. lOMoAR cPSD| 61549570
Lưu thông tin ván Đỗ Mạnh Phương Khi xác định kết quả ván cờ 2 đấu và replay
xong, server sẽ lưu kết quả
ván đấu vào cơ sở dữ liệu
SQLite3, đồng thời tạo ra 1
response hỏi người chơi bị
thua có muốn tái đấu không,
nếu người chơi đồng ý, server
sẽ thực hiện phần còn lại
giống như cách xử lý chuyển lời mời thách đấu
Tổng điểm: 31 điểm Đóng góp:
- Đỗ Mạnh Phương: 50%(16 điểm)
- Lê Quang Khải: 50%(15 điểm)