



















Preview text:
  lOMoAR cPSD| 58605085
TRƯỜNG ĐẠI HỌC SƯ PHẠM KỸ THUẬT TP. HỒ CHÍ MINH KHOA 
CÔNG NGHỆ THÔNG TIN BỘ MÔN CẤU TRÚC DỮ  LIỆU VÀ GIẢI THUẬT 
GVHD: Ths. Nguyễn Minh Đạo 
Nhóm Báo Hòng_Game Memory 
23110076_Phạm Thị Vân Ánh 
23110146_Võ Thị Mai Quỳnh  BÁO CÁO CUỐI KỲ 
Đề tài: PHÁT TRIỂN TRÒ CHƠI GHI NHỚ VỚI HASHMAP ĐỂ GHÉP CẶP  Mục Lục 
1. Mô tả giao diện trò chơi  1  1.1. Mô tả  1  1.2. Phân tích yêu cầu  1 
1.2.1. Tính năng chính  1 
1.2.2. Yêu cầu kỹ thuật  1  1.3. Thiết kế trò chơi  1 
1.3.1. Giao diện người dùng (UI): 1 
1.3.2. Luồng hoạt động của trò chơi:  2 
2. Triển khai source code 2  2.1. Mô tả sơ bộ  2  2.2. Mô tả chi tiết 3 
2.2.1. Cách hoạt động của JFrame  3 
2.2.2. Cách hoạt động của HashMap  4 
2.2.3. Thư mục path/ và resources/  5 
2.2.4. Các lớp trong thư mục src/mypack 5    ∙ GameStartUp  5    ∙ GridsizeSelector  9    ∙ ModeOption  12    ∙ Guide  15      lOMoAR cPSD| 58605085   ∙ MemoryGame  16        lOMoAR cPSD| 58605085   1. 
Mô tả giao diện trò chơi    1.1.  Mô tả  ● 
Xây dựng trò chơi lật thẻ ghi nhớ (Memory) nơi người chơi ghép cặp các thẻ 
giống nhau. Sử dụng HashMap để lưu vị trí và giá trị của các thẻ.  ● 
Trò chơi sẽ có một bảng lưới chứa các thẻ được ẩn đi. Mỗi thẻ sẽ có một giá trị 
và thẻ sẽ có đôi. Người chơi phải lật thẻ lên để tìm các cặp thẻ giống nhau. Khi lật đúng 
một cặp thẻ giống nhau, người chơi ghi điểm. Trò chơi kết thúc khi hai người chơi đã 
tìm hết tất cả các cặp thẻ hoặc đối với chế độ một người chơi thì họ phải lật hết thẻ trước 
một khoảng thời gian quy định.    1.2.  Phân tích yêu cầu 
1.2.1. Tính năng chính  ● 
Lật thẻ và ghép cặp thẻ giống nhau.  ● 
Tính điểm dựa trên số lần ghép đúng.  ● 
Được chọn một người chơi hoặc hai người chơi.  ● 
Được chọn kích thước lưới 2x2, 4x4, 6x6.  ● 
Lựa chọn chế độ chơi và kích thước lưới được lưu lại trong đối tượng  gameStartup.  ● 
Tính số lần lật đếm số lần người chơi lật thẻ trong trò chơi đối với 1 người  chơi.  ● 
Đếm thời gian để chuyển lượt đối với 2 người chơi và để kết thúc game đối  với 
1 người chơi khi hết thời gian. 
1.2.2. Yêu cầu kỹ thuật 
● Ngôn ngữ lập trình: Java.      lOMoAR cPSD| 58605085
● Giao diện người dùng: Sử dụng thư viện Swing.      lOMoAR cPSD| 58605085
● Lưu trữ dữ liệu: Sử dụng HashMap để quản lý vị trí và giá trị của các thẻ.    1.3. 
Thiết kế trò chơi 
1.3.1. Giao diện người dùng (UI): 
● Một giao diện cài đặt gồm o Nút chọn chế độ chơi: 
- Chế độ 1 người chơi. 
- Chế độ 2 người chơi. 
o Nút chọn kích thước lưới:  - 2x2  - 4x4 
- 6x6 o Nút hiển thị hướng dẫn chơi o Nút bắt đầu chơi 
● Một bảng lưới với các thẻ ẩn, người chơi có thể lật thẻ 
bằng cách nhấn chuột sẽ hiển thị sau khi nhấp bắt đầu. 
1.3.2. Luồng hoạt động của trò chơi: 
● Người chơi chọn chế độ chơi và kích thước lưới. 
● Bảng lưới được khởi tạo với các thẻ có giá trị ngẫu nhiên. 
● Người chơi lật hai thẻ và hệ thống kiểm tra xem các thẻ có khớp hay không. 
● Nếu khớp, thẻ sẽ giữ nguyên trạng thái mở. Nếu không, thẻ sẽ úp lại. 
● Điểm, số lần lật thẻ, và thời gian chơi được cập nhật liên tục.    2. 
Triển khai source code    2.1.  Mô tả sơ bộ 
● Code game trên IntelliJ IDEA bằng ngôn ngữ Java, dùng JFrame – một thành phần 
giao diện đồ họa (GUI) trong Java để xây dựng và hiển thị giao diện người dùng, 
đồng thời dùng HashMap - là một cấu trúc dữ liệu dạng bảng băm, dùng để lưu trữ 
cặp khóa - giá trị (key-value) trong Java.      lOMoAR cPSD| 58605085
● Thư mục path/: Chứa các hình ảnh cho các thẻ trong trò chơi. 
● Thư mục resources/: Chứa các tệp âm thanh. 
● Chương trình gồm 5 class: 
o GameStartup.java: Giao diện khởi động. 
o GridSizeSelector.java: Lựa chọn level của trò chơi (kích thước lưới), gồm  2x2, 
4x4, 6x6 tương đương với Dễ - Trung Bình - Khó o Guide.java: Hướng 
dẫn chơi game o ModeOption.java: Lựa chọn chế độ chơi (1 người chơi hoặc 
2 người chơi) o MemoryGame.java: Logic chính của trò chơi.    2.2.  Mô tả chi tiết 
2.2.1. Cách hoạt động của JFrame 
● Các lớp GameStartup.java, GridSizeSelector.java, ModeOption.java, Guide.java và 
MemoryGame.java đều kế thừa hoặc sử dụng JFrame để tạo giao diện người dùng. 
public class GameStartup extends JFrame { 
this.setTitle("Memory Game"); //Đặt tiêu đề 
this.setSize(600, 400); // Đặt kích thước cho cửa sổ 
 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Định nghĩa hành động khi đóng 
//cửa sổ khi người dùng click vào nút X ở góc trên bên phải cửa sổ ứng  dụng. 
 this.setVisible(true); // Hiển thị cửa sổ lên màn hình 
this.setLayout(null); // Đặt layout là null để sử dụng setBounds()  }      lOMoAR cPSD| 58605085
● Trong lớp GameStartup.java: Tạo một cửa sổ chính JFrame để người dùng bắt đầu 
trò chơi. Bố trí các nút (button) như modeButton, levelButton, guideButton, 
startButton và xử lý các sự kiện khi người dùng nhấn nút. 
● Trong lớp GridSizeSelector.java: Tạo cửa sổ (JDialog) có 3 button (JButton) cho 
người chơi chọn kích thước lưới (2x2, 4x4, 6x6). Cung cấp các tùy chọn để cài đặt 
trò chơi dựa trên lựa chọn. 
● Trong lớp Guide chứa nội dung hướng dẫn chơi bằng một JTextArea. 
● Trong lớp ModeOption.java: Tạo cửa sổ (JDialog) có 2 button (JButton) cho người 
chơi chọn chế độ chơi (1 người chơi, 2 người chơi). Cung cấp các tùy chọn để cài 
đặt trò chơi dựa trên lựa chọn. 
● Trong lớp MemoryGame.java tạo một giao diện JFrame hiển thị giao diện chính của 
trò chơi, bao gồm lưới các ô bài. Sử dụng JPanel để chứa các ô bài và sắp xếp chúng 
trong một lưới. Kết hợp các sự kiện chuột khi người chơi lật các ô bài. 
2.2.2. Cách hoạt động của HashMap 
● Trong project MemoryGame, HashMap đóng vai trò trong việc lưu trữ và quản lý 
dữ liệu của các thẻ hình ảnh (cards) trong trò chơi. 
o Lưu trữ cặp dữ liệu key-value giữa các ô bài và hình ảnh tương ứng. o 
Theo dõi trạng thái của các ô bài (đã mở hay chưa). 
o Liên kết vị trí của ô bài với các giá trị khác như hình ảnh, trạng thái  mở/đóng, hoặc ID. 
// HashMap lưu trữ nút và hình ảnh tương ứng  protected HashMap cardImages;      lOMoAR cPSD| 58605085
● Nhằm lưu trữ mỗi nút (JButton) trong giao diện trò chơi với một hình ảnh tương ứng 
(ImageIcon), tức là liên kết một nút trong lưới của trò chơi với một thẻ hình ảnh 
tương ứng để người dùng có thể lật và kiểm tra. Ở đây mỗi nút JButton là key và  ImageIcon là value. 
● Mỗi nút được lưu vào Hashmap với hình ảnh tương ứng 
cardImages.put(button, image); 
● Truy xuất hình ảnh từ Hashmap 
ImageIcon image = cardImages.get(button); 
● Kiểm tra hình ảnh có giống nhau không 
if (cardImages.get(firstCard).equals(cardImages.get(secondCard)){ // Nếu hai  thẻ giống nhau  } 
2.2.3. Thư mục path/ và resources/ 
● Trong thư mục path/: Các hình ảnh A1.jpg - A18.jpg là các hình ảnh được dùng là  thẻ trong trò chơi 
● Trong thư mục resources/: Chứa âm thanh khi chơi game, bao gồm: 
o Open.wav: Âm thanh khi lật bài o 
Close.wav: Âm thanh khi lật sai, đóng bài lại o 
Correct.wav: Âm thanh khi lật đúng o 
Lose.wav: Âm thanh khi thua o Win.wav: Âm  thanh khi thắng      lOMoAR cPSD| 58605085
2.2.4. Các lớp trong thư mục src/mypack  ● GameStartUp 
o Mục đích: Lớp GameStartup đóng vai trò là giao diện khởi động trò chơi 
Memory Game. Khi người chơi mở ứng dụng, lớp này sẽ xuất hiện và cho phép 
người chơi chọn các tùy chọn trước khi bắt đầu trò chơi thực tế. Nó giúp người 
chơi lựa chọn chế độ chơi (1 người hoặc 2 người ), kích thước của lưới thẻ (2x2, 
4x4, 6x6) và hiển thị hướng dẫn.        lOMoAR cPSD| 58605085  
o Các thành phần chính trong lớp: 
- Khai báo các biến và thành phần của game: 
 protected static int GRID_SIZE=2; //Lưới mặc định 2x2 
protected JButton[][] buttons; //Button chứa các nút thẻ 
//HashMap để 1 nút tham chiếu đến 1 ảnh  protected HashMap cardImages; 
 protected JButton firstCard, secondCard; //Biến tạm chứa 2 nút để kiểm tra      lOMoAR cPSD| 58605085
 protected boolean canClick = true; //Khóa lật thẻ khi cần protected int 
pairsFound = 0; //Đếm số cặp thẻ đã lật đúng protected int countstep 
= 0; //Đếm tổng số cặp đã lật protected boolean isPlayerOneTurn = 
true; //Biến để xét xem lượt chơi của ai protected static boolean 
singlePlayerMode = true; //Để xét xem đây là chế độ nào protected static int 
turnTimeLeft = 10; //Thời gian còn lại trong một lượt chơi protected Timer 
turnTimer; //Bộ đếm thời gian để đổi lượt. protected JLabel 
timeLabel, scoreLabel; //JLabel hiển thị thời gian, điểm....  - Tạo hàm khởi tạo: 
public GameStartup(boolean mode, int level, int time) { 
singlePlayerMode = mode; // Gán giá trị chế độ chơi (1 hoặc 2 người) 
GRID_SIZE = level; // Gán kích thước lưới turnTimeLeft = time; 
// Gán thời gian cho mỗi lượt this.setTitle("Memory Game - Startup"); 
// Đặt tiêu đề cửa sổ 
 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Đóng chương trình khi tắt cửa sổ 
 this.setSize(1000, 1000); // Kích thước cửa sổ 1000x1000 pixels 
this.setLocationRelativeTo(null); // Cửa sổ xuất hiện giữa màn hình 
this.setLayout(null); // Sử dụng layout tự do (null layout) 
- Dùng JButton để tạo nút chọn nút chế độ chơi, chọn kích thước lưới, hướngdẫn 
chơi game và bắt đầu game: 
 // Tạo nút chọn 1 hay 2 người chơi 
 JButton modeButton = new JButton("Chọn chế độ chơi");      lOMoAR cPSD| 58605085
 modeButton.setBounds(400, 200, 200, 50); // Vị trí x = 400, y = 200, kích thước 200x50 pixel 
modeButton.setBackground(Color.PINK); 
 //Tạo nút chọn kích thước lưới 
 JButton levelButton = new JButton("Chọn mức chơi"); 
levelButton.setBounds(400, 300, 200, 50); 
levelButton.setBackground(Color.PINK); 
 //Tạo nút để hiển thị hướng dẫn chơi 
 JButton guideButton = new JButton("Hướng dẫn chơi"); 
guideButton.setBounds(400, 400, 200, 50); 
guideButton.setBackground(Color.PINK); 
 //Tạo nút để bắt đầu chơi 
 JButton startButton = new JButton("Bắt đầu chơi"); 
startButton.setBounds(400, 500, 200, 50); 
startButton.setBackground(Color.PINK); //Chọn màu background là màu hồng 
- Tạo hành động cho các nút đã tạo:    //    Thiết  lập    hành  động  cho  các     
nút modeButton.addActionListener(e    ->    {       
 //Gọi ModeOption.selectMode() để chọn chế độ chơi         
ModeOption.selectMode(this,this);  }); 
levelButton.addActionListener(e    ->    {     
 //Gọi GridSizeSelector.selectGridSize() để chọn kích thước lưới         
GridSizeSelector.selectGridSize(this,    this);          //Cập  nhật  lại    thời  gian    tương  ứng  cho  màn  chơi              lOMoAR cPSD| 58605085               if(GRID_SIZE==2)  turnTimeLeft=10; 
if(GRID_SIZE==4) turnTimeLeft=60; if(GRID_SIZE==6) turnTimeLeft=150;  }); 
guideButton.addActionListener(e    ->    {       
 //Gọi hàm hiển thị hướng dẫn chơi          Guide.showGuide(this);  }); 
startButton.addActionListener(e  ->    {          this.setVisible(false);    //Ẩn  cửa  sổ    khởi    động       
 //Khởi chạy trò chơi và giao diện trò chơi         
SwingUtilities.invokeLater(()->new 
MemoryGame(GRID_SIZE,singlePlayerMode,turnTimeLeft));  }); 
- Thêm các nút đã tạo vào giao diện, đồng thời hiển thị cửa sổ: 
 this.add(modeButton); //thêm nút chế độ chơi 
this.add(levelButton); //thêm nút chọn level (kích thước lưới) 
this.add(guideButton);//thêm nút hướng dẫn game 
this.add(startButton);//thêm nút bắt đầu trò chơi   // Hiển thị cửa sổ  this.setVisible(true);  ● GridsizeSelector 
o Mục đích: Lớp GridSizeSelector có nhiệm vụ hiển thị một hộp thoại cho phép 
người chơi chọn kích thước lưới cho trò chơi Memory Game.      lOMoAR cPSD| 58605085  
o Các thành phần chính trong lớp: 
- JDialog: Trong code sử dụng JDialog để tạo một hộp thoại (pop-up) chophép 
người chơi chọn kích thước lưới. Hộp thoại này là modal, có nghĩa là người 
dùng phải lựa chọn trước khi có thể quay lại tương tác với cửa sổ chính. Cửa 
sổ này có tiêu đề là "Chọn kích thước lưới" và kích thước là 400x200 pixel. 
Hộp thoại này được căn giữa trên cửa sổ cha (cửa sổ của trò chơi) thông qua 
gridDialog.setLocationRelativeTo(parent). 
 JDialog gridDialog = new JDialog(parent, "Chọn kích thước lưới", true); // true để hộp thoại 
là modal, chặn người dùng tương tác với cửa sổ chính gridDialog.setSize(400, 200); // Kích 
thước cửa sổ gridDialog.setLocationRelativeTo(parent); // Căn giữa cửa sổ so với cửa sổ cha 
gridDialog.setLayout(new GridLayout(3, 1, 10, 10)); // Sử dụng GridLayout với 3 hàng, 1 cột 
- JLabel: hiển thị thông báo cho người dùng 
 JLabel messageLabel = new JLabel("Bạn có thể chọn kích thước lưới sau:", JLabel.CENTER); 
// Cập nhật phông chữ cho JLabel 
messageLabel.setFont(new Font("Arial", Font.BOLD, 16)); 
gridDialog.add(messageLabel); // Thêm JLabel vào cửa sổ 
- JPanel: Các nút được thêm vào một JPanel sử dụng GridLayout với 1 hàngvà 
3 cột, điều này giúp các nút có thể được xếp ngang nhau. 
 JPanel buttonPanel = new JPanel(new GridLayout(1, 3, 10, 10)); 
buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - JButton: Tạo các nút 
cho kích thước lưới gồm 2x2, 4x4, 6x6 
 JButton grid2x2Button = new JButton("2x2");      lOMoAR cPSD| 58605085
 JButton grid4x4Button = new JButton("4x4"); 
 JButton grid6x6Button = new JButton("6x6"); 
- Thiết lập giao diện các nút đã tạo: 
 grid2x2Button.setBackground(Color.pink); 
grid2x2Button.setForeground(Color.BLACK); 
grid2x2Button.setFont(new Font("Arial", Font.BOLD, 14)); 
 grid4x4Button.setBackground(Color.pink); 
grid4x4Button.setForeground(Color.BLACK); 
grid4x4Button.setFont(new Font("Arial", Font.BOLD, 14)); 
 grid6x6Button.setBackground(Color.pink); 
grid6x6Button.setForeground(Color.BLACK); 
grid6x6Button.setFont(new Font("Arial", Font.BOLD, 14)); 
 // Thêm các nút vào buttonPanel buttonPanel.add(grid2x2Button); 
buttonPanel.add(grid4x4Button); buttonPanel.add(grid6x6Button); 
 // Thêm buttonPanel vào gridDialog gridDialog.add(buttonPanel);  - Xử lí các sự kiện: 
Kích thước 2x2: Khi người chơi nhấn vào nút 2x2, biến GRID_SIZE trong đối 
tượng gameStartup sẽ được cập nhật thành 2. Sau đó, cửa sổ JDialog sẽ đóng lại  với gridDialog.dispose(). 
 grid2x2Button.addActionListener(new ActionListener() { 
 @Override public void actionPerformed(ActionEvent e) { 
gameStartup.GRID_SIZE = 2; // Cập nhật GRID_SIZE trong gameStartup 
gridDialog.dispose(); // Đóng cửa sổ sau khi chọn   }   });      lOMoAR cPSD| 58605085
- Kích thước 4x4: Tương tự, khi người chơi chọn 4x4, GRID_SIZE 
tronggameStartup sẽ được cập nhật thành 4. 
 grid4x4Button.addActionListener(new ActionListener() { 
 @Override public void actionPerformed(ActionEvent e) { 
gameStartup.GRID_SIZE = 4; // Cập nhật GRID_SIZE trong gameStartup 
gridDialog.dispose(); // Đóng cửa sổ sau khi chọn   }   }); 
- Kích thước 6x6: Khi người chơi chọn 6x6, GRID_SIZE trong gameStartup 
sẽđược cập nhật thành 6. 
 grid6x6Button.addActionListener(new ActionListener() { 
 @Override public void actionPerformed(ActionEvent e) { 
gameStartup.GRID_SIZE = 6; // Cập nhật GRID_SIZE trong gameStartup 
gridDialog.dispose(); // Đóng cửa sổ sau khi chọn   }   });  ● ModeOption 
o Mục tiêu: Lớp ModeOption được thiết kế để hiển thị một hộp thoại cho phép 
người chơi chọn chế độ chơi trong trò chơi (1 người chơi hoặc 2 người chơi). 
Khi người dùng chọn chế độ, thông tin này sẽ được lưu lại và hộp thoại sẽ đóng  lại.        lOMoAR cPSD| 58605085
o Các thành phần chính trong lớp: 
- JDialog: Tạo hộp thoại có tiêu đề là “Chọn chế độ chơi”, hộp thoại này là modal. 
JDialog modeDialog = new JDialog(parent, "Chọn chế độ chơi", true); 
- Sau đó tạo cấu hình cho hộp thoại gồm: kích thước hộp thoại 400x200 pixel, căn giữaso 
với cửa sổ cha, layout 3 hàng 1 cột, khoảng cách ngang, dọc là 10 
JDialog modeDialog = new JDialog(parent, "Chọn chế độ chơi", true); 
modeDialog.setSize(400, 200); // Đặt kích thước hộp thoại 
modeDialog.setLocationRelativeTo(parent); // Đặt vị trí hộp thoại ở giữa cửa sổ cha 
modeDialog.setLayout(new GridLayout(3, 1, 10, 10)); // Đặt layout cho hộp thoại 
- JLabel: Hiển thị thông báo, có font chữ Arial, Bold, cỡ chữ 16, 
JLabel messageLabel = new JLabel("Bạn có thể chọn chế độ sau:", JLabel.CENTER); 
messageLabel.setFont(new Font("Arial", Font.BOLD, 16)); // Đặt font chữ cho thông báo 
modeDialog.add(messageLabel); // Thêm vào hộp thoại 
- JButton: Các nút chọn chế độ chơiChế độ 1 người chơi: 
JButton singlePlayerButton = new JButton("Chế độ 1 người chơi"); 
singlePlayerButton.setBackground(Color.pink); // Đặt màu nền cho nút  Chế độ 2 người chơi: 
JButton twoPlayerButton = new JButton("Chế độ 2 người chơi"); 
twoPlayerButton.setBackground(Color.pink); // Đặt màu nền cho nút 
- JPanel: sử dụng layout GridLayout với 2 nút trên một hàng, giúp các nút được cănđều  trên một hàng 
JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 20, 10)); 
buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); 
// Thêm khoảng cách (padding) cho panel  - Xử lí sự kiện: 
Chế độ một người chơi: Cập nhật biến singlePlayerMode trong đối tượng gameStartup 
thành true, cuối cùng đóng hộp thoại bằng phương thức dispose. 
singlePlayerButton.addActionListener(new ActionListener() {      lOMoAR cPSD| 58605085
 @Override public void actionPerformed(ActionEvent e) { 
gameStartup.singlePlayerMode = true; // Cập nhật chế độ chơi trong đối tượng gameStartup 
modeDialog.dispose(); // Đóng hộp thoại   }  }); 
Chế độ hai người chơi: Cập nhật biến singlePlayerMode trong đối tượng gameStartup  thành false. 
twoPlayerButton.addActionListener(new ActionListener() { 
 @Override public void actionPerformed(ActionEvent e) { 
gameStartup.singlePlayerMode = false; // Cập nhật chế độ chơi trong đối tượng gameStartup 
modeDialog.dispose(); // Đóng hộp thoại   }  }); 
● Hiển thị hộp thoại:  modeDialog.setVisible(true);  ● Guide 
o Mục đích: Lớp Guide, có nhiệm vụ hiển thị một cửa sổ chứa hướng dẫn chơi 
cho trò chơi Memory Game. Cửa sổ này giúp người chơi hiểu cách thức chơi, 
các bước thực hiện và luật chơi.      lOMoAR cPSD| 58605085  
o Các thành phần chính trong lớp: 
- JDialog: Trong code sử dụng JDialog để tạo hộp thoại cho người dùng đọc hướngdẫn 
chơi game. Cửa sổ con này có tiêu đề là “Hướng dẫn chơi”, cửa sổ này là modal, có 
kích thước là 800 x 600 pixel, cửa sổ này cũng được căn chính so với cửa sổ cha. 
 JDialog guideDialog = new JDialog(parent, "Hướng dẫn chơi", true); 
guideDialog.setSize(800, 600); 
guideDialog.setLocationRelativeTo(parent); 
guideDialog.setLayout(new BorderLayout(10, 10)); 
- Ngoài ra, còn thêm một số thành phần khác của hộp thoại 
guideDialog.add(titleLabel, BorderLayout.NORTH); // Tiêu đề ở phía trên 
 // Nội dung ở giữa (cuộn được) guideDialog.add(new 
JScrollPane(guideText), BorderLayout.CENTER); 
guideDialog.add(closeButton, BorderLayout.SOUTH); // Nút đóng ở phía dưới //Hiển thị  Dialog:  guideDialog.setVisible(true);      lOMoAR cPSD| 58605085
- JLabel: Tạo một JLabel có tiêu đề là “HƯỚNG DẪN CHƠI”, căn giữa, phông 
chữArial, bold, kích thước 20, chữ có màu đỏ. 
 JLabel titleLabel = new JLabel("HƯỚNG DẪN CHƠI", JLabel.CENTER); 
titleLabel.setFont(new Font("Arial", Font.BOLD, 20)); 
titleLabel.setForeground(Color.red); 
- JTextArea: Chứa nội dung hướng dẫn chi tiết cho trò chơi: mục tiêu, các bước chơi,luật 
chơi, cách kết thúc trò chơi, mẹo chơi. Có phông chữ Arial, kiểu chữ thường, kích 
thước 16, background màu hồng 
JTextArea guideText = new JTextArea(""" //Nội dung hướng dẫn game """); 
guideText.setFont(new Font("Arial", Font.PLAIN, 16)); guideText.setEditable(false); 
//Không cho phép người dùng sửa nội dung văn bản. 
guideText.setBackground(Color.pink); 
guideText.setBorder(new EmptyBorder(10, 10, 10, 10)); 
- JButton: thêm nút Đóng, có phông chữ Arial, in đậm, cỡ chữ 14, màu của chữ là 
màutrắng và background chữ là đỏ 
 JButton closeButton = new JButton("Đóng"); 
closeButton.setFont(new Font("Arial", Font.BOLD, 14)); 
closeButton.setBackground(Color.RED); 
closeButton.setForeground(Color.WHITE); 
//Xử lí sự kiện khi bấm nút Đóng closeButton.addActionListener(e ->  guideDialog.dispose());  ● MemoryGame 
o Mục đích: Lớp MemoryGame nhằm tạo logic chính cho game gồm: 
- Người dùng khởi động trò chơi. 
- Lật hai thẻ và cố gắng tìm các cặp thẻ giống nhau. Nếu hai thẻ giống nhau, thẻ 
sẽđược vô hiệu hóa và người chơi nhận được điểm. 
- Nếu hết thời gian hoặc lật hết thẻ: Thông báo kết quả (thắng, thua hoặc hòa). 
- Người chơi có thể thoát trò chơi bất cứ lúc nào bằng cách nhấn nút HOME.