Xem thêm

Phát sinh số ngẫu nhiên trong C++ (Random number generation)

Huy Erick
Giới thiệu Trong bài viết trước, chúng ta đã tìm hiểu về từ khóa BREAK & CONTINUE. Từ khóa break được sử dụng để kết thúc các vòng lặp while, do-while, for và câu điều...

Giới thiệu

Trong bài viết trước, chúng ta đã tìm hiểu về từ khóa BREAK & CONTINUE. Từ khóa break được sử dụng để kết thúc các vòng lặp while, do-while, for và câu điều kiện switch. Từ khóa continue sẽ nhảy đến cuối vòng lặp hiện tại và thực thi lần lặp tiếp theo.

Trong bài viết này, mình sẽ giới thiệu về phương pháp phát sinh số ngẫu nhiên trong C++. Bạn có thể áp dụng nó vào các chương trình cần phát sinh số ngẫu nhiên, các trò chơi, hoặc để ứng dụng trong các bài học về mảng.

Nội dung

Để hiểu bài viết này tốt nhất, bạn nên có kiến thức cơ bản về:

  • Vòng lặp do-while trong C++ (Do while statements)
  • Vòng lặp for trong C++ (For statements)

Trong bài viết này, chúng ta sẽ tìm hiểu các vấn đề sau:

  • Tổng quan về phát sinh số ngẫu nhiên
  • Phát sinh số ngẫu nhiên trong C++
  • Phát sinh số ngẫu nhiên trong C++ 11

Tổng quan về phát sinh số ngẫu nhiên

Phương pháp phát sinh các số ngẫu nhiên được ứng dụng rất nhiều trong lập trình, đặc biệt là trong các trò chơi và các chương trình cần dữ liệu ngẫu nhiên. Ví dụ, trong trò chơi bắn máy bay, nếu không có sự kiện ngẫu nhiên, các máy bay sẽ luôn xuất hiện ở cùng một vị trí, tấn công bạn theo cùng một cách, và các vật thể xuất hiện trên đường sẽ không bao giờ thay đổi. Điều này sẽ làm cho trò chơi trở nên nhàm chán.

Vậy số ngẫu nhiên được tạo ra bằng cách nào?

Trong cuộc sống, chúng ta thường tạo ra số ngẫu nhiên bằng cách như lắc một con xúc xắc, rút một lá bài, tung một đồng xu và rất nhiều trường hợp ngẫu nhiên khác.

Trong lập trình, máy tính chỉ sử dụng số 0 và 1. Máy tính không thể lắc con xúc xắc, rút lá bài hay tung đồng xu. Mọi thứ trong máy tính đều được tạo nên từ hai số 0 và 1, chỉ có đúng hoặc sai, không có giá trị trung gian. Do đó, máy tính không thể tạo ra số ngẫu nhiên. Để tạo số ngẫu nhiên, lập trình viên phải xây dựng một hệ thống phát sinh số ngẫu nhiên.

Trong C++, để đáp ứng nhu cầu này, đã xây dựng sẵn một số thuật toán phát sinh số ngẫu nhiên.

Phát sinh số ngẫu nhiên trong C++

Ngôn ngữ C++ cung cấp 2 hàm khởi tạo và phát sinh số ngẫu nhiên trong thư viện cstdlib.

Khởi tạo số ngẫu nhiên

Để khởi tạo số ngẫu nhiên, chúng ta sử dụng hàm srand() thuộc thư viện cstdlib.

void srand(unsigned int seed);

Lưu ý:

  • Hàm srand() nhận vào một đối số kiểu số nguyên không dấu, được gọi là seed (hạt giống).
  • Với mỗi seed khác nhau, hàm srand() sẽ tạo ra những bộ số ngẫu nhiên khác nhau. Những số ngẫu nhiên này sẽ được lấy ra bởi hàm rand().
  • Hai khởi tạo số ngẫu nhiên khác nhau với cùng một seed sẽ tạo ra cùng một kết quả.
  • Chúng ta chỉ cần gọi hàm srand() một lần trước khi phát sinh số ngẫu nhiên.

Kết quả phát sinh số ngẫu nhiên của hàm rand() phụ thuộc vào giá trị của seed (hạt giống). Nếu mỗi lần khởi tạo đều sử dụng cùng một seed, chúng ta sẽ nhận được các số ngẫu nhiên giống nhau.

Vì vậy, giá trị của seed cũng phải là một số ngẫu nhiên trong mỗi lần truyền vào hàm srand(). Điều này có vẻ mâu thuẫn, chúng ta cần một số ngẫu nhiên để tạo ra các số ngẫu nhiên. Một giải pháp cho vấn đề này là sử dụng thời gian hệ thống. Mỗi lần chương trình được chạy, thời gian sẽ khác nhau. Chính vì vậy, chúng ta có thể lấy giá trị thời gian hệ thống làm seed, kết quả sẽ là những số ngẫu nhiên khác nhau trong mỗi lần chạy chương trình.

Để lấy được thời gian từ hệ thống, chúng ta có thể sử dụng hàm time() thuộc thư viện ctime. Hàm này trả về số giây từ 00:00 giờ, ngày 01 tháng 1 năm 1970.

Ví dụ:

#include 
#include  // for rand() and srand()
#include  // for time()

using namespace std;

int main() {
    // khởi tạo seed từ thời gian hệ thống
    srand(time(0));

    // phát sinh số ngẫu nhiên
    // ...

    return 0;
}

Ví dụ trên chỉ mới khởi tạo số ngẫu nhiên từ thời gian hệ thống, cách phát sinh các số ngẫu nhiên sẽ được giới thiệu ở phần tiếp theo.

Phát sinh số ngẫu nhiên

Để phát sinh một số ngẫu nhiên, chúng ta sử dụng hàm rand() thuộc thư viện cstdlib.

int rand(void);

Lưu ý:

  • Hàm rand() trả về một số nguyên ngẫu nhiên trong khoảng từ 0 đến RAND_MAX.
  • RAND_MAX là hằng số có giá trị 32767, được định nghĩa trong thư viện cstdlib.

Ví dụ về phát sinh số ngẫu nhiên:

int v1 = rand(); // v1 trong khoảng 0 đến 32767
int v2 = rand() % 100; // v2 trong khoảng 0 đến 99
int v3 = rand() % 100 + 1; // v3 trong khoảng 1 đến 100
int v4 = rand() % 30 + 1985; // v4 trong khoảng 1985 đến 2014

Dưới đây là một ví dụ về trò chơi đoán số từ một số phát sinh ngẫu nhiên:

#include 
#include  // for rand() and srand()
#include  // for time()

using namespace std;

int main() {
    int nSecret, nGuess;

    // khởi tạo seed từ thời gian hệ thống
    srand(time(NULL));

    // phát sinh số bí mật trong khoảng từ 1 đến 10
    nSecret = rand() % 10 + 1;

    do {
        cout << "Đoán số (1 đến 10): ";
        cin >> nGuess;

        if (nSecret < nGuess)
            cout << "Số bí mật nhỏ hơn" << endl;
        else if (nSecret > nGuess)
            cout << "Số bí mật lớn hơn" << endl;
    } while (nSecret != nGuess);

    cout << "Chúc mừng!" << endl;

    return 0;
}

Chương trình trên phát sinh một số ngẫu nhiên từ 1 đến 10, và yêu cầu người dùng lặp lại việc đoán một số sao cho trùng với số ngẫu nhiên của hệ thống.

Đối với việc phát sinh một dãy gồm 10 chữ số ngẫu nhiên:

#include 
#include  // for rand() and srand()
#include  // for time()

using namespace std;

int main() {
    srand(time(0)); // khởi tạo seed từ thời gian hệ thống

    for (int count = 0; count < 10; ++count) {
        cout << rand() << "\t";

        // nếu đã in ra 5 số, xuống dòng
        if ((count + 1) % 5 == 0)
            cout << endl;
    }

    return 0;
}

Còn rất nhiều thuật toán phát sinh số ngẫu nhiên khác, bạn có thể tìm hiểu thêm và chia sẻ cho mọi người.

Kết luận

Qua bài viết này, bạn đã hiểu rõ về phương pháp phát sinh số ngẫu nhiên trong C++. Bạn có thể áp dụng nó vào các chương trình cần phát sinh số ngẫu nhiên, các trò chơi, hoặc để ứng dụng trong các bài học về mảng.

Trong bài viết tiếp theo, mình sẽ giới thiệu về mảng 1 chiều trong C++.

Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên "Luyện tập - Thử thách - Không ngại khó".

1