Từ đầu của giáo trình này, các bạn đã được làm quen với khá nhiều khái niệm : trình biên dịch, IDE, các biến, các hàm, các lệnh điều kiện, vòng lặp. Các bạn đã được chỉ cho xem rất nhiều ví dụ xuyên suốt các bài học nhưng đã có ai thử viết những chương trình thật sự chưa? Nếu vẫn chưa thì bài học này là 1 cơ hội để bắt đầu thử xem.
Trong giáo trình này, các bạn sẽ thường được rèn luyện qua các bài thực hành, từ 1 đến 2 bài mỗi chương. Đây là cơ hội để bạn thật sự tự mình tạo ra một chương trình tin học có những ứng dụng nhất định.
Chủ đề của bài thực hành lần này không quá khó, nhưng tôi thấy cũng khá thú vị : chúng ta sẽ đảo lộn vị trí các chữ cái trong 1 từ và để người chơi đoán xem từ khóa bí ẩn đó là gì. Đây sẽ 1 trò chơi nhỏ các bạn có thể cùng chơi với bạn bè hoặc người thân trong những lần gặp mặt.
Mục tiêu là tìm được từ khóa bí ẩn trong chuỗi ký tự đã đảo lộn vị trí. Trò chơi mà chúng ta thực hiện nghe có vẻ đơn giản nhưng bạn sẽ thấy là chúng ta sẽ cần dùng đến những khái niệm đã được nói đến trong những bài học trước :
Nếu các bạn thấy vẫn chưa tự tin lắm với kiến thức của mình, có thể đọc lướt qua lại các bài học trước rồi chúng ta sẽ bắt đầu ngay lập tức.
Trò chơi của chúng ta sẽ diễn ra như sau :
Sau đây là 1 ví dụ của trò chơi :
Đương nhiên là trong trường hợp này, người chơi thứ 2 có thể dễ dàng nhìn thấy từ khóa bí ẩn mà người chơi thứ nhất đã nhập vào. Chúng ta sẽ xem xem làm sao có thể giải quyết vấn đề này ở cuối bài thực hành.
Nếu bạn là người mới lần đầu học lập trình, có người đến nói với bạn “Hãy viết cho tôi chương trình làm việc A, việc B, việc C,… !”, bạn sẽ rất dễ mất phương hướng.
“Tôi phải bắt đầu từ đâu?”, “Tôi phải làm gì? Sử dụng những gì để thực hiện?”, vv… thường là những câu hỏi đầu tiên xuất hiện trong đầu những người mới. Điều này là hiển nhiên vì các bạn chưa từng làm điều này trước đây.
Đừng lo, tôi sẽ không bỏ rơi các bạn đâu. Sau đây là 1 vài lời khuyên có thể hữu ích để việc chuẩn bị của bạn được tốt hơn. Thế nhưng cuối cùng thì đây cũng chỉ là những lời khuyên, quyết định nên làm thế nào vẫn hoàn toàn là ở bạn.
Nhắc lại các bước tiến hành chương trình
Chúng ta sẽ nhắc lại 3 bước trong tiến trình của chương trình :
Những bước nêu trên đây về cơ bản khá là độc lập với nhau. Vì thế thay vì viết ngay lập tức cả chương trình, sao chúng ta không tách ra và xử lý từng bước một ?
string
khá là phù hợp trong trường hợp này. Nắm vững kiến thức về nhập và xuất dữ liệu và bạn sẽ dễ dàng hoàn thành bước này.Viết bộ khung xử lý chương trình
Chúng ta đều biết mọi chương trình đều diễn ra trong hàm main()
. Các bạn có thể bắt đầu viết bộ khung của chương trình sử dụng các bình luận, kiểu giống như hồi nhỏ viết dàn bài cho bài tập làm văn vậy.
Nó sẽ kiểu kiểu như sau.
int main(){ //1 : Yeu cau nguoi choi nhap tu khoa //2 : Dao lon vi tri cac ky tu trong tu khoa //3 : On demande à l'utilisateur quel est le mot mystère return 0; }
Chỉ còn việc thực hiện từng bước 1. Để thử với độ khó tăng dần, các bạn có thể viết bước 1 trước tiên, rồi đến bước 3 và bước 2 cuối cùng.
Sau đây là 1 ví dụ của chương trình « bán thành phẩm » sau khi bạn hoàn thành được bước 1 và bước 3.
Như các bạn đã thấy, chương trình của chúng ta vẫn còn thiếu việc đổi chỗ các chữ cái, thế nhưng cũng đã hoàn thành đến 50% rồi.
Đây có thể được coi là phần khó nhất trong bài thực hành này. Đừng lo tôi sẽ không bỏ rơi các bạn đâu. Một vài gợi ý nho nhỏ sau đây có thể rất hữu ích.
Chọn 1 số bất kỳ
Để có thể đổi chỗ các chữ cái 1 cách hỗn loạn, trước tiên bạn phải biết cách làm sao để chọn được 1 số bất kỳ. Vì chúng ta vẫn chưa học cách làm điều này, tôi cần trước tiên giải thích cho các bạn 1 số thứ:
ctime
và cstdlib
vào đầu đoạn mã để có thể thao tác với các số ngẫu nhiên srand(time(0));
1 lần duy nhất ở đầu chương trình để có thể khởi tạo các số ngẫu nhiên.Cuối cùng, ví dụ để tạo ra 1 số ngẫu nhiên giữa 0 và 4 chẳng hạn, chúng ta cần viết soNgauNhien = rand()%5 ;
Đoạn mã ví dụ tạo ra số ngẫu nhiên giữa 0 và 4
#include <iostream> #include <ctime> #include <cstdlib> using namespace std; int main(){ int soNgauNhien(0); srand(time(0)); soNgauNhien = rand() % 5 ; return 0; }
Chọn 1 ký tự bất kỳ trong chuỗi
? Có liên hệ gì giữa việc chọn 1 số bất kỳ và chọn 1 ký tự bất kỳ trong chuỗi ?
Chúng ta từng nói về việc 1 chuỗi ký tự string
có thể được coi như 1 mảng để thao tác. Ví dụ như chúng ta có biến tuKhoa
thì tuKhoa[0]
sẽ là chữ thứ 1, tuKhoa[1]
sẽ là chữ thứ 2, vv…
Vậy chúng ta chỉ cần chọn ra được 1 vị trí bất kỳ giữa 0
và tuKhoa.size()
thì sẽ dễ dàng chọn ra 1 ký tự bất kỳ trong chuỗi đó. Ví dụ :
#include <iostream> #include <string> #include <ctime> #include <cstdlib> using namespace std; int main(){ string tu("TU KHOA BI AN"); srand(time(0)); int viTri = rand() % tu.size(); cout << "Ky tu bat ky :" << tu[viTri]; return 0; }
Xóa 1 ký tự khỏi chuỗi
Để tránh việc chọn 2 lần cùng 1 ký tự, tôi kiến nghị chúng ta xóa dần các ký tự ra khỏi chuỗi mỗi khi 1 ký tự được bốc trúng làm ký tự bất kỳ. Để làm điều này, cần phải sử dụng đến hàm erase()
. Ví dụ :
tuKhoa.erase(4,1);
Hàm này có 2 thông số :
Điều này là không bắt buộc nhưng vẫn tốt hơn là viết tất cả mã nguồn trong hàm main()
. Các bạn có thể viết các hàm làm những thao tác cụ thể ví dụ như trong bước 2, việc tráo vị trí các ký tự có thể viết dưới dạng 1 hàm sau đó được sử dụng đến trong hàm main()
.
tuBiDaoViTri = daoViTriChuCai(tuKhoa);
Hàm này nhận vào 1 tuKhoa
và trả về kết quả là tuBiDaoViTri
. Tất cả khó khăn chỉ còn là viết mã xử lý của hàm daoViTriChuCai()
này.
Cùng bắt tay vào thực hiện thôi !
Dưới đây sẽ là bài chữa.
Chắc hẳn các bạn đã bỏ ra kha khá thời gian để nghĩ về chương trình này. Đôi chỗ không hề đơn giản và bạn không biết phải giải quyết như thế nào. Không sao, quan trọng là bạn đã dám thử ! Đó là cách mà chúng ta tiến bộ.
Về cơ bản thì bước 1 và bước 3 là khá đơn giản với hầu hết mọi người, chỉ duy có bước 2 là có chút phức tạp. Tôi sẽ tách riêng nó ra thành 1 hàm và xử lý riêng như tôi đã đề nghị với các bạn ở bên trên.
Sau đây là chương trình của tôi.
#include <iostream> #include <string> #include <ctime> #include <cstdlib> using namespace std; string daoViTriChuCai(string tu){ string tuBiDaoViTri; int viTri(0); //Khi ban con chua xoa het cac ky tu cua tu while (tu.size() != 0){ //Cho 1 vi tri bat ky trong tu viTri = rand() % tu.size(); //Them ky tu vao tu bi dao vi tri chu cai tuBiDaoViTri += tu[viTri]; //Xoa ky tu vua dung de tranh chon mai ky tu nay lan nua tu.erase(viTri, 1); } return tuBiDaoViTri; } int main(){ string tuKhoa, tuBiDaoViTri, cauTraLoi; srand(time(0)); //1 : Yeu cau nguoi choi nhap tu khoa cout << "Hay nhap 1 tu : " << endl; getline (cin, tuKhoa); //2 : Dao lon vi tri cac ky tu trong tu khoa tuBiDaoViTri = daoViTriChuCai(tuKhoa); //3 : On demande à l'utilisateur quel est le mot mystère do{ cout << endl << "Tu khoa bi an dang sau '" << tuBiDaoViTri << "' ?" << endl; getline (cin, cauTraLoi); if (cauTraLoi == tuKhoa){ cout << "Hoan ho, ban da tra loi chinh xac !" << endl; }else{ cout << "Suyt nua la dung roi, dung bo cuoc !" << endl; } }while (cauTraLoi != tuKhoa); //Chi dung lai khi nao tu khoa duoc tim ra return 0; }
Hãy học cách đọc mã nguồn của chương trình 1 cách khoa học đó là đọc theo thứ tự các câu lệnh được thực hiện thay vì đọc từ trên xuống dưới. Chúng ta nên bắt đầu với hàm main()
mà không phải hàm daoViTriChuCai()
.
Tôi sẽ giải thích cho các bạn từng bước một trong tiến trình của chương trình.
Bước 1 : Nhập từ khóa
Đây rõ là bước dễ nhất rồi : cout
để in câu hỏi ra màn hình và cin
hoặc getline()
để lưu từ khóa nhập bới người dung vào biến tuKhoa. Các từ trong tiếng Việt thường có nhiều chữ cách nhau vởi dấu cách, vậy nên tôi đề nghị sử dụng getline()
.
Bước 2 : Đổi vị trí chữ cái
Bước này đã được tách riêng và đoạn mã xử lý được viết trong hàm daoViTriChuCai()
. Hàm main()
chỉ việc gọi nó và nhận kết quả trả về là 1 từ mà các chữ đều đã được đổi chỗ.
Phân tích đoạn mã bên trên, hàm daoViTriChuCai()
tách ra từng ký tự 1 cách ngẫu nhiên từ từ khóa gốc và lần lượt thêm chúng vào chuỗi ký tự mà ta sẽ trả về làm kết quả của hàm. Vòng lặp được thực hiện tới khi nào tách hết các ký tự trong từ khóa.
while (tu.size() != 0){ //Cho 1 vi tri bat ky trong tu viTri = rand() % tu.size(); //Them ky tu vao tu bi dao vi tri chu cai tuBiDaoViTri += tu[viTri]; //Xoa ky tu vua dung de tranh chon mai ky tu nay lan nua tu.erase(viTri, 1); }
Trong mỗi vòng lặp, ta chọn 1 vị trí bất kỳ nằm giữa 0 và số ký tự còn lại của từ khóa. Ta thêm ký tự vừa chọn được vào biến tuBiDaoViTri
đồng thời xóa nó trong từ khóa để không ngẫu nhiên chọn lại lần thứ 2.
Sau khi tất cả các ký tự đều được tách ra hết, chúng ta kết thúc vòng lặp và trả về biến tuBiDaoViTri
chứa các ký tự được sắp xếp bất kỳ.
Bước 3 : Cho người chơi đoán từ khóa gốc
Chúng ta sử dụng vòng lặp do… while
trong bước này. Vòng lặp này mang đến cho ta 2 lợi ích :
while (cauTraLoi != tuKhoa)
.Các thông điệp khác nhau sẽ được in ra màn hình tùy theo người chơi trả lời đúng hay sai.
Các bạn có thể tải mã nguồn của chương trình theo đường dẫn sau.
Tệp ZIP bao gồm :
Các bạn có thể tham khảo cũng như dung nó làm tiền đề để phát triển 1 số tính năng cho chương trình mà bạn muốn thêm vào.
Chúng ta đến đây là đã hoàn thành mục tiêu của bài thực hành. Thế nhưng tôi biết là nhiều người vẫn chưa hài lòng và muốn cải tiến thêm nữa. Mỗi người có ý tưởng của riêng mình. Sau đây là 1 vài ý tưởng của tôi để hoàn thiện chương trình nếu có bạn nào muốn thử :
endl
để giấu đi từ khóa này trong console.Cuối cùng, đừng ngại thử ý tưởng của chính các bạn để xem liệu bản thân bạn có thể đi xa tới đâu.