Lập Trình Trò Chơi Lật Hình Với Java

Lập Trình Trò Chơi Lật Hình Với Java

Trò chơi lật hình là một trò chơi quen thuộc với đa số mọi người. Để trò chơi thú vị hơn, hãy thử với những tấm hình của crush xem sao, biết đâu vừa thực hành được kỹ năng code, vừa cưa đổ được crush với game đơn giản thế này

Luật chơi rất đơn giản

Mỗi màn chơi sẽ có 2 * k (mội số chẵn) tấm hình đã bị ẩn đi, các tấm hình không thay đổi vị trí trong mỗi màn chơi. Bạn có thể mở liên tiếp hai tấm hình (bạn sẽ thấy hai tấm hình đó) nếu hai hình đó giống nhau thì chúng sẽ bị xóa đi, còn không hai tấm hình đó tiếp tục bị ẩn.

Khi bạn mở được tất cả những cặp hình giống nhau, màn chơi sẽ kết thúc, để trò chơi thêm hấp dẫn, sẽ có áp lực về thời gian trong mỗi màn chơi, đòi hỏi bạn phải thật bình tĩnh để ghi nhớ vị trí của các bức hình.

Khởi tạo dữ liệu và thiết lập giao diện.

1. Hình ảnh

Để làm trò chơi này các bạn cần có một số lượng hình ảnh khác nhau.

Các tên của anh nên đặt theo thứ tự như hình dưới, ví dụ icon1.jpg, icon2.jpg, icon2.jpg, ...

Các các có thể sử dụng luôn hình ảnh của mình Tại đây.

2. Ma trận - biểu diễn hình ảnh

Ta có thể xem mỗi số sẽ biểu diễn cho một tấm hình, hai hình ảnh giống nhau nếu giá trị trong ma trận tương ứng của chúng bằng nhau.
Nếu trong màn chơi đó, các tấm hình được sắp xếp trong m hàng và n cột. Ta sẽ dùng matrix a để tượng trừng cho các hình ảnh đó.

	private int a[][] = new int[maxXY][maxXY];

Ta nhận thấy rằng, trong ma trận, các số luôn xuất hiện trong ma trận đúng 2 lần, vậy làm sao thiết lập được ma trận như thế, đặc biết là nó phải được sắp xếp ngẫu nhiên.

Ví dụ như bạn đã có nhiều nhất images tấm ảnh, bạn cần tạo một ma trận kích thước m * n cho trò chơi, việc đầu tiên là bạn cần chọn ra (m * n) / 2 tấm ảnh trong images tấm ảnh của bạn, sau đó chỉ việc nhân đôi số lượng của nó lên.

		int images = 50;
		int N = m * n;
		int b[] = new int [m * n + images];
		int c[] = new int [m * n + images];
		for (int i = 0; i < images; i++) {
			b[i] = i;
			c[i] = (int) (Math.random() * 1000000);
		}
		for (int i = 0; i < images - 1; i++)
			for (int j = i + 1; j < images; j++)
				if (c[i] > c[j]) {
					int tmp = b[i];
					b[i] = b[j];
					b[j] = tmp;
					tmp = c[i];
					c[i] = c[j];
					c[j] = tmp;
				}

Sau khi thực hiện đoạn code trên, thì m * n / 2 phần tử đầu tiên của dãy b chính là cách chỉ số phân biệt của các tấm ảnh (không có hai số nào giống nhau)

Ta sẽ nhân đôi m * n / 2 của số đầu của dãy b.

for (int i = N / 2; i < N; i++)
			b[i] = b[i - N/2];

Cuối cùng là sắp xếp random dãy b từ 0 đến m * n - 1 và đưa nó vào matrix a. chương trình đầy đủ cho đoạn tạo matrix a:

	public void createMatrix() {
		int images = 50;
		int N = m * n;
		int b[] = new int [m * n + images];
		int c[] = new int [m * n + images];
		for (int i = 0; i < images; i++) {
			b[i] = i;
			c[i] = (int) (Math.random() * 1000000);
		}
		for (int i = 0; i < images - 1; i++)
			for (int j = i + 1; j < images; j++)
				if (c[i] > c[j]) {
					int tmp = b[i];
					b[i] = b[j];
					b[j] = tmp;
					tmp = c[i];
					c[i] = c[j];
					c[j] = tmp;
				}
		for (int i = N / 2; i < N; i++)
			b[i] = b[i - N/2];
		for (int i = 0; i < m * n; i++) {
			c[i] = (int) (Math.random() * 1000000);
		}
		for (int i = 0; i < N - 1; i++)
			for (int j = i + 1; j < N; j++)
				if (c[i] > c[j]) {
					int tmp = b[i];
					b[i] = b[j];
					b[j] = tmp;
					tmp = c[i];
					c[i] = c[j];
					c[j] = tmp;
				}
		N = 0;
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
				a[i][j] = b[N++];
	}

3. Đưa hình ảnh vào giao diện.

Giao diện chính sẽ gồm các Jbutton trong class JFrame như sau:

Để đưa hình ảnh vào ta chỉ cần dùng hàm setIcon(). Tuy nhiên mỗi hình ảnh sẽ nhận một hình ảnh khác nhau, nên ta cần viết thêm hàm getIcon() như sau:

	private Icon getIcon(int index) {
		int width = 120, height = 170;
		Image image = new ImageIcon(getClass().getResource("/Game/icon/icon" + index + ".jpg")).getImage();
		Icon icon = new ImageIcon(image.getScaledInstance(width, height, image.SCALE_SMOOTH));
		return icon;
	}

Để đưa hình ảnh tương ứng với button (i, j) ta sẽ sử dụng lệnh bt[i][j].setIcon(getIcon(a[i][j])), Lúc đó giao diện sẽ là:

Xử lý các thao tác

1. Bấm vào một hình ảnh

Khi bắt đầu trò chơi, ta sẽ ẩn các hình ảnh đi, ví dụ:

Ta nhận thấy rằng, khi bấm vào ảnh lần thứ nhất thì lập tức mở hình ảnh đó, lúc mở ảnh lần thứ hai ta mới cần kiểm tra xem chúng có giống nhau hay không, nếu giống nhau thì xóa hai ảnh ấy đi, còn không thì đưa hai ảnh đó về trạng thái ẩn.

			if (count == 0) {
				bt[i][j].setIcon(getIcon(a[i][j]));
				id = a[i][j];
				preX = i;
				preY = j;
			}else {
				bt[i][j].setIcon(getIcon(a[i][j]));
				X = i; Y = j;
				timer.start(); 
			}
			count = 1 - count;

Dùng class Timer để kiểm tra ảnh, đồng thời tạo hiệu ứng delay lúc kiểm tra ảnh.

		timer = new Timer(240, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				open();
				timer.stop();
			}
		});

2. Thời gian trong màn chơi

Để tạo thanh thời gian như hình trên ta sử dụng JProgressBar trong JFrame 

	private JProgressBar progressTime;
	maxTime = TIME[k] * 10 ;
	time = 0

Kết hợp Timer (sẽ chạy khi các hoạt động bấm button):

		timer2 = new Timer(100, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				time ++;
				progressTime.setValue(maxTime - time);
				if (maxTime == time) {
					timer2.stop();
					showDialogNewGame("Hết thời gian.\n" +
							"Điểm: " + score_bt.getText() + "\n" +
							"Bạn có muốn chơi lại không?", "Thông báo");
				}
			}
		});

Hàm hiện thị thông báo:

	public void showDialogNewGame(String message, String title) {
		int select = JOptionPane.showOptionDialog(null, message, title,
				JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null,
				null, null);
		if (select == 0) {
			newGame();
		} else {
			System.exit(0);
		}
	}

3. New game và Next level

Hàm newGame():

	public void newGame() {
		this.dispose();
		new GameLatHinh(0, 100);
	}

Hàm nextGame() cũng tượng tự, nhưng chú ý là phải truyền thêm tham số để lưa số điểm đã đat được trong màn chơi trước.

	public void nextGame() {
		this.dispose();
		new GameLatHinh(level + 1, Integer.parseInt(score_bt.getText()) + (maxTime - time)/50);
	}

Lúc khai báo biến lưu score:

		score_bt = new JButton(String.valueOf(score));

Kết

Trên đây là hướng dẫn tạo trò chơi lật hình bằng Java, mình đã bỏ qua những chỗ không cần thiết trong lúc làm trò chơi, nếu bạn nào chưa hiểu phần nào có thể bình luận cho mình biết.

Bài viết còn nhiều thiếu sót, rất mong nhận được sự góp ý của các bạn.

Có thể tham khảo source code của mình Tại đây.

Video demo: